From 37f294fec20e5b27532c156cd6956d65d804a5df Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Tue, 27 Dec 2016 03:21:13 +0200 Subject: [PATCH 001/167] Disable the test for valgrind builds Test is very slow with valgrind, and pointless because it is initially about a race condition which is hardly achievable with valgrind --- mysql-test/t/mdev-504.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/mdev-504.test b/mysql-test/t/mdev-504.test index fb5c7666d33..b96c8779c68 100644 --- a/mysql-test/t/mdev-504.test +++ b/mysql-test/t/mdev-504.test @@ -1,3 +1,4 @@ +--source include/not_valgrind.inc --disable_ps_protocol SET GLOBAL net_write_timeout = 900; From 2f5670dc269ce19f14132d54e54060c91cc028e3 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 27 Dec 2016 14:13:32 +0530 Subject: [PATCH 002/167] MDEV-11636 Extra persistent columns on slave always gets NULL in RBR Problem:- In replication if slave has extra persistent column then these column are not computed while applying write-set from master. Solution:- While applying row events from server, we will generate values for extra persistent columns. --- .../rpl/r/rpl_alter_extra_persistent.result | 220 ++++++++++++++++++ .../rpl/t/rpl_alter_extra_persistent.test | 106 +++++++++ sql/rpl_record.cc | 32 +++ sql/rpl_record.h | 1 + 4 files changed, 359 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result create mode 100644 mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test diff --git a/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result new file mode 100644 index 00000000000..84915073d87 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result @@ -0,0 +1,220 @@ +include/master-slave.inc +[connection master] +connection master; +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); +connection slave; +select * from t1 order by a; +a +1 +2 +3 +4 +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +connection master; +insert into t1 values(5); +insert into t1 values(6); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#UPDATE query +connection master; +update t1 set a = a+10; +select * from t1 order by a; +a +11 +12 +13 +14 +15 +16 +connection slave; +select * from t1 order by a; +a z1 z2 +11 12 13 +12 13 14 +13 14 15 +14 15 16 +15 16 17 +16 17 18 +connection master; +update t1 set a = a-10; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#DELETE quert +connection master; +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +#REPLACE query +connection master; +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#SELECT query +connection master; +select * from t1 where a > 2 and a < 4; +a +3 +connection slave; +select * from t1 where a > 2 and a < 4; +a z1 z2 +3 4 5 +#UPDATE with SELECT query +connection master; +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +13 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +13 14 15 +connection master; +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; +connection master; +#entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +connection slave; +include/wait_for_slave_sql_error.inc [errno=1062] +connection slave; +connection slave; +select * from t1 order by a; +a z1 z2 z4 +1 2 3 1 +2 3 4 2 +3 4 5 3 +4 5 6 4 +5 6 7 5 +6 7 8 0 +alter table t1 drop column z4; +start slave; +include/wait_for_slave_sql_to_start.inc +connection slave; +connection slave; +connection master; +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +7 8 9 +connection master; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +drop table t1; +include/rpl_end.inc +connection server_2; +connection server_2; +connection server_2; +connection server_2; +connection server_1; +connection server_1; +connection server_1; +connection server_2; +connection server_1; +connection server_2; +connection server_2; +connection server_1; +connection server_1; diff --git a/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test new file mode 100644 index 00000000000..3b2fff1cb13 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test @@ -0,0 +1,106 @@ +--source include/master-slave.inc +--source include/have_binlog_format_row.inc + +--enable_connect_log +--connection master +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); + +--sync_slave_with_master +select * from t1 order by a; +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; + +--connection master +insert into t1 values(5); +insert into t1 values(6); + +--sync_slave_with_master +select * from t1 order by a; + + +--echo #UPDATE query + +--connection master +update t1 set a = a+10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a-10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #DELETE quert +--connection master +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #REPLACE query +--connection master +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); + +--sync_slave_with_master +select * from t1 order by a; + +--echo #SELECT query +--connection master +select * from t1 where a > 2 and a < 4; + +--connection slave +select * from t1 where a > 2 and a < 4; + +--echo #UPDATE with SELECT query +--connection master +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; + +--connection master + +--echo #entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; + +--connection slave +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc +select * from t1 order by a; +alter table t1 drop column z4; +start slave; + +--source include/wait_for_slave_sql_to_start.inc + +--connection master +--sync_slave_with_master +select * from t1 order by a; + +--connection master +select * from t1 order by a; +drop table t1; + +--source include/rpl_end.inc diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index f82c5a3982a..e62f722675d 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -416,6 +416,13 @@ unpack_row(rpl_group_info *rgi, } } + /* + Add Extra slave persistent columns + */ + int error= 0; + if ((error= fill_extra_persistent_columns(table, cols->n_bits))) + DBUG_RETURN(error); + /* We should now have read all the null bytes, otherwise something is really wrong. @@ -489,5 +496,30 @@ int prepare_record(TABLE *const table, const uint skip, const bool check) DBUG_RETURN(0); } +/** + Fills @c table->record[0] with computed values of extra persistent column which are present on slave but not on master. + @param table Table whose record[0] buffer is prepared. + @param master_cols No of columns on master + @returns 0 on success + */ +int fill_extra_persistent_columns(TABLE *table, int master_cols) +{ + int error= 0; + Field **vfield_ptr, *vfield; + if (!table->vfield) + return 0; + for (vfield_ptr= table->vfield; *vfield_ptr; ++vfield_ptr) + { + vfield= *vfield_ptr; + if (vfield->field_index >= master_cols && vfield->stored_in_db) + { + /*Set bitmap for writing*/ + bitmap_set_bit(table->vcol_set, vfield->field_index); + error= vfield->vcol_info->expr_item->save_in_field(vfield,0); + bitmap_clear_bit(table->vcol_set, vfield->field_index); + } + } + return error; +} #endif // HAVE_REPLICATION diff --git a/sql/rpl_record.h b/sql/rpl_record.h index c10eb8225b0..be69716d9d5 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -38,6 +38,7 @@ int unpack_row(rpl_group_info *rgi, // Fill table's record[0] with default values. int prepare_record(TABLE *const table, const uint skip, const bool check); +int fill_extra_persistent_columns(TABLE *table, int master_cols); #endif #endif From d02a77bc5fbaf2e9504035e98f132fdf7145fd94 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 27 Dec 2016 14:13:32 +0530 Subject: [PATCH 003/167] MDEV-11636 Extra persistent columns on slave always gets NULL in RBR Problem:- In replication if slave has extra persistent column then these column are not computed while applying write-set from master. Solution:- While applying row events from server, we will generate values for extra persistent columns. --- .../rpl/r/rpl_alter_extra_persistent.result | 220 ++++++++++++++++++ .../rpl/t/rpl_alter_extra_persistent.test | 106 +++++++++ sql/rpl_record.cc | 31 +++ sql/rpl_record.h | 1 + 4 files changed, 358 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result create mode 100644 mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test diff --git a/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result new file mode 100644 index 00000000000..84915073d87 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result @@ -0,0 +1,220 @@ +include/master-slave.inc +[connection master] +connection master; +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); +connection slave; +select * from t1 order by a; +a +1 +2 +3 +4 +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +connection master; +insert into t1 values(5); +insert into t1 values(6); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#UPDATE query +connection master; +update t1 set a = a+10; +select * from t1 order by a; +a +11 +12 +13 +14 +15 +16 +connection slave; +select * from t1 order by a; +a z1 z2 +11 12 13 +12 13 14 +13 14 15 +14 15 16 +15 16 17 +16 17 18 +connection master; +update t1 set a = a-10; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#DELETE quert +connection master; +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +#REPLACE query +connection master; +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#SELECT query +connection master; +select * from t1 where a > 2 and a < 4; +a +3 +connection slave; +select * from t1 where a > 2 and a < 4; +a z1 z2 +3 4 5 +#UPDATE with SELECT query +connection master; +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +13 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +13 14 15 +connection master; +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; +connection master; +#entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +connection slave; +include/wait_for_slave_sql_error.inc [errno=1062] +connection slave; +connection slave; +select * from t1 order by a; +a z1 z2 z4 +1 2 3 1 +2 3 4 2 +3 4 5 3 +4 5 6 4 +5 6 7 5 +6 7 8 0 +alter table t1 drop column z4; +start slave; +include/wait_for_slave_sql_to_start.inc +connection slave; +connection slave; +connection master; +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +7 8 9 +connection master; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +drop table t1; +include/rpl_end.inc +connection server_2; +connection server_2; +connection server_2; +connection server_2; +connection server_1; +connection server_1; +connection server_1; +connection server_2; +connection server_1; +connection server_2; +connection server_2; +connection server_1; +connection server_1; diff --git a/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test new file mode 100644 index 00000000000..3b2fff1cb13 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test @@ -0,0 +1,106 @@ +--source include/master-slave.inc +--source include/have_binlog_format_row.inc + +--enable_connect_log +--connection master +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); + +--sync_slave_with_master +select * from t1 order by a; +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; + +--connection master +insert into t1 values(5); +insert into t1 values(6); + +--sync_slave_with_master +select * from t1 order by a; + + +--echo #UPDATE query + +--connection master +update t1 set a = a+10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a-10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #DELETE quert +--connection master +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #REPLACE query +--connection master +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); + +--sync_slave_with_master +select * from t1 order by a; + +--echo #SELECT query +--connection master +select * from t1 where a > 2 and a < 4; + +--connection slave +select * from t1 where a > 2 and a < 4; + +--echo #UPDATE with SELECT query +--connection master +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; + +--connection master + +--echo #entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; + +--connection slave +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc +select * from t1 order by a; +alter table t1 drop column z4; +start slave; + +--source include/wait_for_slave_sql_to_start.inc + +--connection master +--sync_slave_with_master +select * from t1 order by a; + +--connection master +select * from t1 order by a; +drop table t1; + +--source include/rpl_end.inc diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 183248ad1b8..5e48cfb02e5 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -389,6 +389,12 @@ unpack_row(rpl_group_info *rgi, } } + /* + Add Extra slave persistent columns + */ + if ((error= fill_extra_persistent_columns(table, cols->n_bits))) + DBUG_RETURN(error); + /* We should now have read all the null bytes, otherwise something is really wrong. @@ -461,5 +467,30 @@ int prepare_record(TABLE *const table, const uint skip, const bool check) DBUG_RETURN(0); } +/** + Fills @c table->record[0] with computed values of extra persistent column which are present on slave but not on master. + @param table Table whose record[0] buffer is prepared. + @param master_cols No of columns on master + @returns 0 on success + */ +int fill_extra_persistent_columns(TABLE *table, int master_cols) +{ + int error= 0; + Field **vfield_ptr, *vfield; + if (!table->vfield) + return 0; + for (vfield_ptr= table->vfield; *vfield_ptr; ++vfield_ptr) + { + vfield= *vfield_ptr; + if (vfield->field_index >= master_cols && vfield->stored_in_db) + { + /*Set bitmap for writing*/ + bitmap_set_bit(table->vcol_set, vfield->field_index); + error= vfield->vcol_info->expr_item->save_in_field(vfield,0); + bitmap_clear_bit(table->vcol_set, vfield->field_index); + } + } + return error; +} #endif // HAVE_REPLICATION diff --git a/sql/rpl_record.h b/sql/rpl_record.h index c10eb8225b0..be69716d9d5 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -38,6 +38,7 @@ int unpack_row(rpl_group_info *rgi, // Fill table's record[0] with default values. int prepare_record(TABLE *const table, const uint skip, const bool check); +int fill_extra_persistent_columns(TABLE *table, int master_cols); #endif #endif From efcd0935f77c1080cf00f86e70f28b8a74762475 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 27 Dec 2016 14:13:32 +0530 Subject: [PATCH 004/167] MDEV-11636 Extra persistent columns on slave always gets NULL in RBR Problem:- In replication if slave has extra persistent column then these column are not computed while applying write-set from master. Solution:- While applying row events from server, we will generate values for extra persistent columns. --- .../rpl/r/rpl_alter_extra_persistent.result | 203 ++++++++++++++++++ .../rpl/t/rpl_alter_extra_persistent.test | 106 +++++++++ sql/rpl_record.cc | 32 +++ sql/rpl_record.h | 1 + 4 files changed, 342 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result create mode 100644 mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test diff --git a/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result new file mode 100644 index 00000000000..96df87d8ad4 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result @@ -0,0 +1,203 @@ +include/master-slave.inc +[connection master] +connection master; +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); +connection slave; +select * from t1 order by a; +a +1 +2 +3 +4 +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +connection master; +insert into t1 values(5); +insert into t1 values(6); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#UPDATE query +connection master; +update t1 set a = a+10; +select * from t1 order by a; +a +11 +12 +13 +14 +15 +16 +connection slave; +select * from t1 order by a; +a z1 z2 +11 12 13 +12 13 14 +13 14 15 +14 15 16 +15 16 17 +16 17 18 +connection master; +update t1 set a = a-10; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#DELETE quert +connection master; +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +#REPLACE query +connection master; +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#SELECT query +connection master; +select * from t1 where a > 2 and a < 4; +a +3 +connection slave; +select * from t1 where a > 2 and a < 4; +a z1 z2 +3 4 5 +#UPDATE with SELECT query +connection master; +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +13 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +13 14 15 +connection master; +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; +connection master; +#entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +connection slave; +include/wait_for_slave_sql_error.inc [errno=1062] +select * from t1 order by a; +a z1 z2 z4 +1 2 3 1 +2 3 4 2 +3 4 5 3 +4 5 6 4 +5 6 7 5 +6 7 8 0 +alter table t1 drop column z4; +start slave; +include/wait_for_slave_sql_to_start.inc +connection master; +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +7 8 9 +connection master; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test new file mode 100644 index 00000000000..3b2fff1cb13 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test @@ -0,0 +1,106 @@ +--source include/master-slave.inc +--source include/have_binlog_format_row.inc + +--enable_connect_log +--connection master +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); + +--sync_slave_with_master +select * from t1 order by a; +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; + +--connection master +insert into t1 values(5); +insert into t1 values(6); + +--sync_slave_with_master +select * from t1 order by a; + + +--echo #UPDATE query + +--connection master +update t1 set a = a+10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a-10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #DELETE quert +--connection master +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #REPLACE query +--connection master +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); + +--sync_slave_with_master +select * from t1 order by a; + +--echo #SELECT query +--connection master +select * from t1 where a > 2 and a < 4; + +--connection slave +select * from t1 where a > 2 and a < 4; + +--echo #UPDATE with SELECT query +--connection master +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; + +--connection master + +--echo #entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; + +--connection slave +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc +select * from t1 order by a; +alter table t1 drop column z4; +start slave; + +--source include/wait_for_slave_sql_to_start.inc + +--connection master +--sync_slave_with_master +select * from t1 order by a; + +--connection master +select * from t1 order by a; +drop table t1; + +--source include/rpl_end.inc diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index f82c5a3982a..c753f76c930 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -416,6 +416,13 @@ unpack_row(rpl_group_info *rgi, } } + /* + Add Extra slave persistent columns + */ + int error= 0; + if ((error= fill_extra_persistent_columns(table, cols->n_bits))) + DBUG_RETURN(error); + /* We should now have read all the null bytes, otherwise something is really wrong. @@ -489,5 +496,30 @@ int prepare_record(TABLE *const table, const uint skip, const bool check) DBUG_RETURN(0); } +/** + Fills @c table->record[0] with computed values of extra persistent column which are present on slave but not on master. + @param table Table whose record[0] buffer is prepared. + @param master_cols No of columns on master + @returns 0 on success + */ +int fill_extra_persistent_columns(TABLE *table, int master_cols) +{ + int error= 0; + Field **vfield_ptr, *vfield; + if (!table->vfield) + return 0; + for (vfield_ptr= table->vfield; *vfield_ptr; ++vfield_ptr) + { + vfield= *vfield_ptr; + if (vfield->field_index >= master_cols && vfield->stored_in_db()) + { + /*Set bitmap for writing*/ + bitmap_set_bit(table->vcol_set, vfield->field_index); + error= vfield->vcol_info->expr->save_in_field(vfield,0); + bitmap_clear_bit(table->vcol_set, vfield->field_index); + } + } + return error; +} #endif // HAVE_REPLICATION diff --git a/sql/rpl_record.h b/sql/rpl_record.h index c10eb8225b0..be69716d9d5 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -38,6 +38,7 @@ int unpack_row(rpl_group_info *rgi, // Fill table's record[0] with default values. int prepare_record(TABLE *const table, const uint skip, const bool check); +int fill_extra_persistent_columns(TABLE *table, int master_cols); #endif #endif From 3871477c40efc826805f4c4e35b006c2c233dd26 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 1 Jan 2017 20:06:03 +0200 Subject: [PATCH 005/167] MDEV-10100 main.pool_of_threads fails sporadically in buildbot The patch fixes two test failures: - on slow builders, sometimes a connection attempt which should fail due to the exceeded number of thread_pool_max_threads actually succeeds; - on even slow builders, MTR sometimes cannot establish the initial connection, and check-testcase fails prior to the test start The problem with check-testcase was caused by connect-timeout=2 which was set for all clients in the test config file. On slow builders it might be not enough. There is no way to override it for the pre-test check, so it needed to be substantially increased or removed. The other problem was caused by a race condition between sleeps that the test performs in existing connections and the connect timeout for the connection attempt which was expected to fail. If sleeps finished before the connect-timeout was exceeded, it would allow the connection to succeed. To solve each problem without making the other one worse, connect-timeout should be configured dynamically during the test. Due to the nature of the test (all connections must be busy at the moment when we need to change the timeout, and cannot execute SET GLOBAL ...), it needs to be done independently from the server. The solution: - recognize 'connect_timeout' as a connection option in mysqltest's "connect" command; - remove connect-timeout from the test configuration file; - use the new connect_timeout option for those connections which are expected to fail; - re-arrange the test flow to allow running a huge SLEEP without affecting the test execution time (because it would be interrupted after the main test flow is finished). The test is still subject to false negatives, e.g. if the connection fails due to timeout rather than due to the exceeded number of allowed threads, or if the connection on extra port succeeds due to a race condition and not because the special logic for the extra port. But those false negatives have always been possible there on slow builders, they should not be critical because faster builders should catch such failures if they appear. --- client/mysqltest.cc | 12 +++++++ mysql-test/r/pool_of_threads.result | 21 ++++++------- mysql-test/t/pool_of_threads.cnf | 3 -- mysql-test/t/pool_of_threads.test | 49 +++++++++++++++-------------- 4 files changed, 48 insertions(+), 37 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index ed401b6e4a2..15db5759ac9 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5945,6 +5945,7 @@ void do_connect(struct st_command *command) my_bool con_shm __attribute__ ((unused))= 0; int read_timeout= 0; int write_timeout= 0; + int connect_timeout= 0; struct st_connection* con_slot; static DYNAMIC_STRING ds_connection_name; @@ -6051,6 +6052,11 @@ void do_connect(struct st_command *command) { write_timeout= atoi(con_options + sizeof("write_timeout=")-1); } + else if (strncasecmp(con_options, "connect_timeout=", + sizeof("connect_timeout=")-1) == 0) + { + connect_timeout= atoi(con_options + sizeof("connect_timeout=")-1); + } else die("Illegal option to connect: %.*s", (int) (end - con_options), con_options); @@ -6135,6 +6141,12 @@ void do_connect(struct st_command *command) (char*)&write_timeout); } + if (connect_timeout) + { + mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT, + (char*)&connect_timeout); + } + #ifdef HAVE_SMEM if (con_shm) { diff --git a/mysql-test/r/pool_of_threads.result b/mysql-test/r/pool_of_threads.result index 9611d7ff43b..ddc451516e2 100644 --- a/mysql-test/r/pool_of_threads.result +++ b/mysql-test/r/pool_of_threads.result @@ -2157,23 +2157,22 @@ Warnings: Warning 1052 Column 'kundentyp' in group statement is ambiguous drop table t1; SET optimizer_switch=@save_optimizer_switch; -SELECT sleep(5.5); -SELECT sleep(5); +SELECT sleep(50); +SELECT sleep(50); # -- Success: more than --thread_pool_max_threads normal connections not possible -sleep(5.5) -0 -sleep(5) -0 -SELECT sleep(5); -SELECT sleep(5); SELECT 'Connection on extra port ok'; Connection on extra port ok Connection on extra port ok +SELECT sleep(5.5); SELECT 'Connection on extra port 2 ok'; Connection on extra port 2 ok Connection on extra port 2 ok # -- Success: more than --extra-max-connections + 1 normal connections not possible -sleep(5) -0 -sleep(5) +KILL QUERY ; +KILL QUERY ; +sleep(50) +1 +sleep(50) +1 +sleep(5.5) 0 diff --git a/mysql-test/t/pool_of_threads.cnf b/mysql-test/t/pool_of_threads.cnf index c03e1da6450..f6651c878de 100644 --- a/mysql-test/t/pool_of_threads.cnf +++ b/mysql-test/t/pool_of_threads.cnf @@ -7,8 +7,5 @@ loose-thread_pool_max_threads= 2 extra-port= @ENV.MASTER_EXTRA_PORT extra-max-connections=1 -[client] -connect-timeout= 2 - [ENV] MASTER_EXTRA_PORT= @OPT.port diff --git a/mysql-test/t/pool_of_threads.test b/mysql-test/t/pool_of_threads.test index 24e0218db62..f13a096985c 100644 --- a/mysql-test/t/pool_of_threads.test +++ b/mysql-test/t/pool_of_threads.test @@ -15,23 +15,26 @@ SET optimizer_switch=@save_optimizer_switch; # connections on the extra port. # First set two connections running, and check that extra connection -# on normal port fails due to--thread-pool-max_threads=2 -connection default; +# on normal port fails due to --thread-pool-max-threads=2. +# We can afford using a really long sleep, because we won't wait +# till it ends, we'll interrupt it as soon as we don't need it anymore -# Sleep for slightly longer than 5 sec to trigger MDEV-4566 -# (abort in interruptible wait connection check) -send SELECT sleep(5.5); +connection default; +--let $con1_id= `SELECT CONNECTION_ID()` + +send SELECT sleep(50); --sleep 1 connect(con2,localhost,root,,); -connection con2; -send SELECT sleep(5); +--let $con2_id= `SELECT CONNECTION_ID()` + +send SELECT sleep(50); --sleep 0.5 --disable_abort_on_error --disable_result_log --disable_query_log -connect(con3,localhost,root,,); +connect(con3,localhost,root,,,,,connect_timeout=2); --enable_query_log --enable_result_log --enable_abort_on_error @@ -45,24 +48,15 @@ if ($error) --echo # -- Success: more than --thread_pool_max_threads normal connections not possible } -connection default; ---reap -connection con2; ---reap - -# Now try again, but this time use the extra port to successfully connect. - -connection default; -send SELECT sleep(5); - -connection con2; -send SELECT sleep(5); ---sleep 1 - connect(extracon,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,); connection extracon; SELECT 'Connection on extra port ok'; +# Here, sleep just for slightly longer than 5 sec to trigger MDEV-4566 +# (abort in interruptible wait connection check). +send SELECT sleep(5.5); + + connect(extracon2,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,); connection extracon2; SELECT 'Connection on extra port 2 ok'; @@ -70,7 +64,7 @@ SELECT 'Connection on extra port 2 ok'; --disable_abort_on_error --disable_result_log --disable_query_log -connect(extracon3,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,); +connect(extracon3,127.0.0.1,root,,test,$MASTER_EXTRA_PORT,,connect_timeout=2); --enable_query_log --enable_result_log --enable_abort_on_error @@ -84,7 +78,16 @@ if ($error) --echo # -- Success: more than --extra-max-connections + 1 normal connections not possible } +connection extracon2; +--replace_result $con1_id +eval KILL QUERY $con1_id; +--replace_result $con2_id +eval KILL QUERY $con2_id; + connection default; --reap connection con2; --reap + +connection extracon; +--reap From d9a1a201aae87a655cdf3e5a344b2265912a94a7 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 3 Jan 2017 10:10:58 +0530 Subject: [PATCH 006/167] MDEV-11016 wsrep_node_is_ready() check is too strict Problem:- The condition that checks for node readiness is too strict as it does not allow SELECTs even if these selects do not access any tables. For example,if we run SELECT 1; OR SELECT @@max_allowed_packet; Solution:- We need not to report this error when all_tables(lex->query_tables) is NULL: --- mysql-test/suite/galera/r/MW-284.result | 2 ++ mysql-test/suite/galera/r/galera_var_dirty_reads.result | 9 +++++++++ mysql-test/suite/galera/t/MW-284.test | 5 +++++ mysql-test/suite/galera/t/galera_var_dirty_reads.test | 5 +++++ sql/sql_parse.cc | 5 ++++- 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/r/MW-284.result b/mysql-test/suite/galera/r/MW-284.result index 3ff131674ea..9465370c25b 100644 --- a/mysql-test/suite/galera/r/MW-284.result +++ b/mysql-test/suite/galera/r/MW-284.result @@ -2,12 +2,14 @@ CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET SESSION wsrep_on = OFF; SET SESSION wsrep_on = ON; +SET global wsrep_sync_wait=0; START SLAVE; include/wait_for_slave_param.inc [Slave_IO_Running] SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; include/wait_for_slave_to_start.inc INSERT INTO t1 VALUES (1); DROP TABLE t1; +SET global wsrep_sync_wait=7; STOP SLAVE; RESET SLAVE ALL; CALL mtr.add_suppression('failed registering on master'); diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index 8a3175912c7..52729395b19 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -18,6 +18,15 @@ Variable_name Value wsrep_cluster_status non-Primary SELECT * FROM t1; ERROR 08S01: WSREP has not yet prepared node for application use +SELECT @@wsrep_dirty_reads; +@@wsrep_dirty_reads +0 +SELECT 2; +2 +2 +SELECT 2+2 FROM DUAL; +2+2 +4 SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; i diff --git a/mysql-test/suite/galera/t/MW-284.test b/mysql-test/suite/galera/t/MW-284.test index f3ce1b0dc91..7add82f1227 100644 --- a/mysql-test/suite/galera/t/MW-284.test +++ b/mysql-test/suite/galera/t/MW-284.test @@ -11,12 +11,16 @@ --enable_query_log --connection node_1 +--let $wsrep_sync_wait_state= `SELECT @@global.wsrep_sync_wait;` CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; SET SESSION wsrep_on = OFF; --let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status' --source include/wait_condition.inc SET SESSION wsrep_on = ON; +#wsrep_sync_wait is set to zero because when slave tries to connect it it ask for queries like SELECT UNIX_TIMESTAMP() on node 1 which will fail, causing +#a warning in slave error log. +SET global wsrep_sync_wait=0; --connection node_3 START SLAVE; @@ -47,6 +51,7 @@ INSERT INTO t1 VALUES (1); --connection node_1 DROP TABLE t1; +--eval SET global wsrep_sync_wait=$wsrep_sync_wait_state --connection node_3 --let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' --source include/wait_condition.inc diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index bcdb1574a3d..1fd30c69a7b 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -37,6 +37,11 @@ SHOW STATUS LIKE 'wsrep_cluster_status'; --error ER_UNKNOWN_COM_ERROR SELECT * FROM t1; +#Select query which does not access table should be allowed MDEV-11016 +SELECT @@wsrep_dirty_reads; +SELECT 2; +SELECT 2+2 FROM DUAL; + SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b214a1759be..5717c3dd6c4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -288,6 +288,7 @@ void init_update_queries(void) server_command_flags[COM_STMT_RESET]= CF_SKIP_QUESTIONS | CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_EXECUTE]= CF_SKIP_WSREP_CHECK; server_command_flags[COM_STMT_SEND_LONG_DATA]= CF_SKIP_WSREP_CHECK; + server_command_flags[COM_REGISTER_SLAVE]= CF_SKIP_WSREP_CHECK; /* Initialize the sql command flags array. */ memset(sql_command_flags, 0, sizeof(sql_command_flags)); @@ -2651,7 +2652,7 @@ mysql_execute_command(THD *thd) /* Bail out if DB snapshot has not been installed. SET and SHOW commands, however, are always allowed. - + Select query is also allowed if it does not access any table. We additionally allow all other commands that do not change data in case wsrep_dirty_reads is enabled. */ @@ -2659,6 +2660,8 @@ mysql_execute_command(THD *thd) !wsrep_is_show_query(lex->sql_command) && !(thd->variables.wsrep_dirty_reads && !is_update_query(lex->sql_command)) && + !(lex->sql_command == SQLCOM_SELECT && + !all_tables) && !wsrep_node_is_ready(thd)) goto error; } From b4616c40be00c5c8a2a73d537d676d8ddb7c84cf Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 3 Jan 2017 10:45:55 +0530 Subject: [PATCH 007/167] MDEV-7955 WSREP() appears on radar in OLTP RO This commit is for optimizing WSREP(thd) macro. #define WSREP(thd) \ (WSREP_ON && wsrep && (thd && thd->variables.wsrep_on)) In this we can safely remove wsrep and thd. We are not removing WSREP_ON because this will change WSREP(thd) behaviour. Patch Credit:- Nirbhay Choubay, Sergey Vojtovich --- sql/sql_parse.cc | 2 +- sql/wsrep_mysqld.h | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/trx/trx0trx.cc | 2 +- storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/trx/trx0trx.cc | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5717c3dd6c4..4f630b68264 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2624,7 +2624,7 @@ mysql_execute_command(THD *thd) } /* endif unlikely slave */ #endif #ifdef WITH_WSREP - if (WSREP(thd)) + if (wsrep && WSREP(thd)) { /* change LOCK TABLE WRITE to transaction diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index cf549ffe544..fc4b2a452fe 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -179,7 +179,7 @@ extern wsrep_seqno_t wsrep_locked_seqno; strcmp(wsrep_provider, WSREP_NONE)) #define WSREP(thd) \ - (WSREP_ON && wsrep && (thd && thd->variables.wsrep_on)) + (WSREP_ON && thd->variables.wsrep_on) #define WSREP_CLIENT(thd) \ (WSREP(thd) && thd->wsrep_client_thread) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3713dd959d4..b283bbda7f4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4103,7 +4103,7 @@ innobase_commit_low( #ifdef WITH_WSREP THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; - if (wsrep_on(thd)) { + if (thd && wsrep_on(thd)) { #ifdef WSREP_PROC_INFO char info[64]; info[sizeof(info) - 1] = '\0'; diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index cde32448769..11025b4c21c 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1349,7 +1349,7 @@ trx_commit_in_memory( ut_ad(!trx->in_rw_trx_list); #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd)) { + if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { trx->lock.was_chosen_as_deadlock_victim = FALSE; } #endif diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 8d564df2bb3..8f51b931038 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4742,7 +4742,7 @@ innobase_commit_low( #ifdef WITH_WSREP THD* thd = (THD*)trx->mysql_thd; const char* tmp = 0; - if (wsrep_on(thd)) { + if (thd && wsrep_on(thd)) { #ifdef WSREP_PROC_INFO char info[64]; info[sizeof(info) - 1] = '\0'; diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc index ec57a8e5c54..bdf407ff7fb 100644 --- a/storage/xtradb/trx/trx0trx.cc +++ b/storage/xtradb/trx/trx0trx.cc @@ -1572,7 +1572,7 @@ trx_commit_in_memory( ut_ad(!trx->in_rw_trx_list); #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd)) { + if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { trx->lock.was_chosen_as_deadlock_victim = FALSE; } #endif From 4c610d10d400938481e418d8798279d61ff41d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 09:44:44 +0200 Subject: [PATCH 008/167] Post-fix for MDEV-11195 NUMA does not get enabled even when checks are passed The C preprocessor symbol WITH_NUMA is never defined. Instead, the symbol HAVE_LIBNUMA is used for checking if the feature is to be used. If cmake -DWITH_NUMA=OFF is specified, HAVE_LIBNUMA will not be defined at compilation time even if the library is available. If cmake -DWITH_NUMA=ON is specified but the library is not available at configuration time, the compilation will be aborted. --- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 1 + .../suite/sys_vars/t/innodb_numa_interleave_basic.test | 1 - mysql-test/suite/sys_vars/t/sysvars_innodb.test | 1 + storage/innobase/buf/buf0buf.cc | 10 +++++----- storage/innobase/handler/ha_innodb.cc | 10 +++++----- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 87e000faf02..ad6dcc1bb64 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2,6 +2,7 @@ select * from information_schema.system_variables where variable_name like 'innodb%' and variable_name not in ( 'innodb_disallow_writes', # only available WITH_WSREP +'innodb_numa_interleave', # only available WITH_NUMA 'innodb_sched_priority_cleaner', # linux only 'innodb_use_native_aio') # default value depends on OS order by variable_name; diff --git a/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test b/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test index 518b5ebba17..de89784f7e4 100644 --- a/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test @@ -1,6 +1,5 @@ --source include/have_innodb.inc --source include/have_numa.inc ---source include/have_64bit.inc SELECT @@GLOBAL.innodb_numa_interleave; diff --git a/mysql-test/suite/sys_vars/t/sysvars_innodb.test b/mysql-test/suite/sys_vars/t/sysvars_innodb.test index bd8442b6a44..38f248cb611 100644 --- a/mysql-test/suite/sys_vars/t/sysvars_innodb.test +++ b/mysql-test/suite/sys_vars/t/sysvars_innodb.test @@ -9,6 +9,7 @@ select * from information_schema.system_variables where variable_name like 'innodb%' and variable_name not in ( 'innodb_disallow_writes', # only available WITH_WSREP + 'innodb_numa_interleave', # only available WITH_NUMA 'innodb_sched_priority_cleaner', # linux only 'innodb_use_native_aio') # default value depends on OS order by variable_name; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 935b7fadafa..638126f8de1 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -85,7 +85,7 @@ Created 11/5/1995 Heikki Tuuri #include "lzo/lzo1x.h" #endif -#if defined(HAVE_LIBNUMA) && defined(WITH_NUMA) +#ifdef HAVE_LIBNUMA #include #include struct set_numa_interleave_t @@ -126,7 +126,7 @@ struct set_numa_interleave_t #define NUMA_MEMPOLICY_INTERLEAVE_IN_SCOPE set_numa_interleave_t scoped_numa #else #define NUMA_MEMPOLICY_INTERLEAVE_IN_SCOPE -#endif /* HAVE_LIBNUMA && WITH_NUMA */ +#endif /* HAVE_LIBNUMA */ /* Enable this for checksum error messages. */ //#ifdef UNIV_DEBUG @@ -1608,7 +1608,7 @@ buf_chunk_init( return(NULL); } -#if defined(HAVE_LIBNUMA) && defined(WITH_NUMA) +#ifdef HAVE_LIBNUMA if (srv_numa_interleave) { struct bitmask *numa_mems_allowed = numa_get_mems_allowed(); int st = mbind(chunk->mem, chunk->mem_size(), @@ -1622,7 +1622,7 @@ buf_chunk_init( " (error: " << strerror(errno) << ")."; } } -#endif /* HAVE_LIBNUMA && WITH_NUMA */ +#endif /* HAVE_LIBNUMA */ /* Allocate the block descriptors from diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6a6a049d5a6..9a278143945 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -22724,12 +22724,12 @@ static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio, "Use native AIO if supported on this platform.", NULL, NULL, TRUE); -#if defined(HAVE_LIBNUMA) && defined(WITH_NUMA) +#ifdef HAVE_LIBNUMA static MYSQL_SYSVAR_BOOL(numa_interleave, srv_numa_interleave, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, "Use NUMA interleave memory policy to allocate InnoDB buffer pool.", NULL, NULL, FALSE); -#endif /* HAVE_LIBNUMA && WITH_NUMA */ +#endif /* HAVE_LIBNUMA */ static MYSQL_SYSVAR_BOOL(api_enable_binlog, ib_binlog_enabled, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, @@ -23276,9 +23276,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(autoinc_lock_mode), MYSQL_SYSVAR(version), MYSQL_SYSVAR(use_native_aio), -#if defined(HAVE_LIBNUMA) && defined(WITH_NUMA) +#ifdef HAVE_LIBNUMA MYSQL_SYSVAR(numa_interleave), -#endif /* HAVE_LIBNUMA && WITH_NUMA */ +#endif /* HAVE_LIBNUMA */ MYSQL_SYSVAR(change_buffering), MYSQL_SYSVAR(change_buffer_max_size), #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG From 403f6e96070a3f35745d4d59d12e222d21ac4f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 3 Jan 2017 11:22:09 +0200 Subject: [PATCH 009/167] MDEV-11705: InnoDB: Failing assertion: (&log_sys->mutex)->is_owned() if server started with innodb-scrub-log Problem was that log_scrub function did not take required log_sys mutex. Background: Unused space in log blocks are padded with MLOG_DUMMY_RECORD if innodb-scrub-log is enabled. As log files are written on circular fashion old log blocks can be reused later for new redo-log entries. Scrubbing pads unused space in log blocks to avoid visibility of the possible old redo-log contents. log_scrub(): Take log_sys mutex log_pad_current_log_block(): Increase srv_stats.n_log_scrubs if padding is done. srv0srv.cc: Set srv_stats.n_log_scrubs to export vars innodb_scrub_log ha_innodb.cc: Export innodb_scrub_log to global status. --- .../suite/encryption/r/innodb-scrub-log.result | 3 +++ mysql-test/suite/encryption/t/innodb-scrub-log.opt | 1 + mysql-test/suite/encryption/t/innodb-scrub-log.test | 13 +++++++++++++ storage/innobase/handler/ha_innodb.cc | 3 +++ storage/innobase/include/srv0srv.h | 6 +++++- storage/innobase/log/log0log.cc | 8 +++++++- storage/innobase/srv/srv0srv.cc | 1 + 7 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/encryption/r/innodb-scrub-log.result create mode 100644 mysql-test/suite/encryption/t/innodb-scrub-log.opt create mode 100644 mysql-test/suite/encryption/t/innodb-scrub-log.test diff --git a/mysql-test/suite/encryption/r/innodb-scrub-log.result b/mysql-test/suite/encryption/r/innodb-scrub-log.result new file mode 100644 index 00000000000..8ea75000368 --- /dev/null +++ b/mysql-test/suite/encryption/r/innodb-scrub-log.result @@ -0,0 +1,3 @@ +create table t1(a int not null primary key auto_increment, +b varchar(200), c char(100), d varchar(150)) engine=innodb; +DROP TABLE t1; diff --git a/mysql-test/suite/encryption/t/innodb-scrub-log.opt b/mysql-test/suite/encryption/t/innodb-scrub-log.opt new file mode 100644 index 00000000000..0078065bbf7 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-scrub-log.opt @@ -0,0 +1 @@ +--loose-innodb-scrub-log=on diff --git a/mysql-test/suite/encryption/t/innodb-scrub-log.test b/mysql-test/suite/encryption/t/innodb-scrub-log.test new file mode 100644 index 00000000000..36ecc88b99a --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-scrub-log.test @@ -0,0 +1,13 @@ +--source include/have_innodb.inc + +# +# MDEV-11705: InnoDB: Failing assertion: (&log_sys->mutex)->is_owned() if server started with innodb-scrub-log +# + +create table t1(a int not null primary key auto_increment, +b varchar(200), c char(100), d varchar(150)) engine=innodb; + +let $wait_condition= SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_scrub_log'; +--source include/wait_condition.inc + +DROP TABLE t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9a278143945..aadc7155327 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1273,6 +1273,9 @@ static SHOW_VAR innodb_status_variables[]= { {"scrub_background_page_split_failures_unknown", (char*) &export_vars.innodb_scrub_page_split_failures_unknown, SHOW_LONG}, + {"scrub_log", + (char*) &export_vars.innodb_scrub_log, + SHOW_LONGLONG}, {"encryption_num_key_requests", (char*) &export_vars.innodb_encryption_key_requests, SHOW_LONGLONG}, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 92572a0f8b3..e04726ea837 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation +Copyright (c) 2013, 2017, MariaDB Corporation Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -194,6 +194,9 @@ struct srv_stats_t { /** Number of encryption_get_latest_key_version calls */ ulint_ctr_64_t n_key_requests; + + /** Number of log scrub operations */ + ulint_ctr_64_t n_log_scrubs; }; extern const char* srv_main_thread_op_info; @@ -1118,6 +1121,7 @@ struct export_var_t{ ulint innodb_scrub_page_split_failures_out_of_filespace; ulint innodb_scrub_page_split_failures_missing_index; ulint innodb_scrub_page_split_failures_unknown; + int64_t innodb_scrub_log; }; /** Thread slot in the thread table. */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 979a40e22fe..c9ea1b10b06 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2017, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -2552,6 +2552,10 @@ log_pad_current_log_block(void) pad_length = 0; } + if (pad_length) { + srv_stats.n_log_scrubs.inc(); + } + for (i = 0; i < pad_length; i++) { log_write_low(&b, 1); } @@ -2571,6 +2575,7 @@ void log_scrub() /*=========*/ { + log_mutex_enter(); ulint cur_lbn = log_block_convert_lsn_to_no(log_sys->lsn); if (next_lbn_to_pad == cur_lbn) @@ -2579,6 +2584,7 @@ log_scrub() } next_lbn_to_pad = log_block_convert_lsn_to_no(log_sys->lsn); + log_mutex_exit(); } /* log scrubbing speed, in bytes/sec */ diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 0eda03f7fd7..3df86e25b55 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1705,6 +1705,7 @@ srv_export_innodb_status(void) scrub_stat.page_split_failures_missing_index; export_vars.innodb_scrub_page_split_failures_unknown = scrub_stat.page_split_failures_unknown; + export_vars.innodb_scrub_log = srv_stats.n_log_scrubs; mutex_exit(&srv_innodb_monitor_mutex); } From 509e7773eccfcca2577e980b543f38fe4f0ed4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 12:09:14 +0200 Subject: [PATCH 010/167] MDEV-11695 Define a reasonable upper limit for innodb_spin_wait_delay The upper limit of innodb_spin_wait_delay was ~0UL. It does not make any sense to wait more than a few dozens of microseconds between attempts to acquire a busy mutex. Make the new upper limit 6000. ut_delay(6000) could correspond to several milliseconds even today. --- storage/innobase/handler/ha_innodb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index aadc7155327..9da1e6bcd05 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -22615,7 +22615,7 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds, static MYSQL_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay, PLUGIN_VAR_OPCMDARG, "Maximum delay between polling for a spin lock (6 by default)", - NULL, NULL, 6L, 0L, ~0UL, 0); + NULL, NULL, 6, 0, 6000, 0); static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency, PLUGIN_VAR_RQCMDARG, From fc779252aec56e01c5924d80378cafc8b6ec80b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 13:18:47 +0200 Subject: [PATCH 011/167] MDEV-11688 fil_crypt_threads_end() tries to create threads after aborted InnoDB startup This bug was repeatable by starting MariaDB 10.2 with an invalid option, such as --innodb-flush-method=foo. It is not repeatable in MariaDB 10.1 in the same way, but the problem exists already there. --- storage/innobase/fil/fil0crypt.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 6483cdc5a53..6482956eb0a 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2465,8 +2465,9 @@ void fil_crypt_threads_end() /*===================*/ { - /* stop threads */ - fil_crypt_set_thread_cnt(0); + if (fil_crypt_threads_inited) { + fil_crypt_set_thread_cnt(0); + } } /********************************************************************* From 8a04b8cadedb4b7388379a30b7d7211a2b607bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 13:18:47 +0200 Subject: [PATCH 012/167] MDEV-11688 fil_crypt_threads_end() tries to create threads after aborted InnoDB startup This bug was repeatable by starting MariaDB 10.2 with an invalid option, such as --innodb-flush-method=foo. It is not repeatable in MariaDB 10.1 in the same way, but the problem exists already there. --- storage/innobase/fil/fil0crypt.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index fd1cc24c92a..708dbd0fd01 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2458,8 +2458,9 @@ void fil_crypt_threads_end() /*===================*/ { - /* stop threads */ - fil_crypt_set_thread_cnt(0); + if (fil_crypt_threads_inited) { + fil_crypt_set_thread_cnt(0); + } } /********************************************************************* From a0d396fd3f5f86e09f602ac9f76b8d9f2e739221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 3 Jan 2017 14:35:08 +0200 Subject: [PATCH 013/167] MDEV-11684: post-10.1-merge fixes 10.1 is merged into 10.2 now. Two issues are left to fix: (1) encryption.innochecksum test (2) read_page0 vs page_0_crypt_read (1) innochecksum tool did not compile after merge because buf_page_is_corrupted uses fil_crypt_t that has been changed. extra/CMakeLists.txt: Added fil/fil0crypt.cc as dependency as we need to use fil_crypt_verify_checksum for encrypted pages. innochecksum.cc: If we think page is encrypted i.e. FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION != 0 we call fil_crypt_verify_checksum() function to compare calculated checksum to stored checksum calculated after encryption (this is stored on different offset i.e. FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4). If checksum does not match we call normal buf_page_is_corrupted to compare calculated checksum to stored checksum. fil0crypt.cc: add #ifdef UNIV_INNOCHECKSUM to be able to compile this file for innochecksum tool. (2) read_page0 is not needed and thus removed. --- extra/CMakeLists.txt | 1 + extra/innochecksum.cc | 42 +++++- mysql-test/suite/encryption/disabled.def | 2 +- storage/innobase/buf/buf0buf.cc | 8 +- storage/innobase/fil/fil0crypt.cc | 173 +++++++++++++---------- storage/innobase/fil/fil0fil.cc | 5 +- storage/innobase/include/fil0fil.h | 5 +- 7 files changed, 146 insertions(+), 90 deletions(-) diff --git a/extra/CMakeLists.txt b/extra/CMakeLists.txt index ee696c156f9..480cd6e7fbb 100644 --- a/extra/CMakeLists.txt +++ b/extra/CMakeLists.txt @@ -80,6 +80,7 @@ IF(WITH_INNOBASE_STORAGE_ENGINE OR WITH_XTRADB_STORAGE_ENGINE) ../storage/innobase/buf/buf0buf.cc ../storage/innobase/page/page0zip.cc ../storage/innobase/os/os0file.cc + ../storage/innobase/fil/fil0crypt.cc ) diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index ce631c13952..9d02a545cc5 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - Copyright (c) 2014, 2016, MariaDB Corporation. + Copyright (c) 2014, 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 @@ -70,6 +70,24 @@ The parts not included are excluded by #ifndef UNIV_INNOCHECKSUM. */ #define PRIuMAX "llu" #endif +/********************************************************************* +Verify checksum for a page (iff it's encrypted) +NOTE: currently this function can only be run in single threaded mode +as it modifies srv_checksum_algorithm (temporarily) +@param[in] src_fame page to verify +@param[in] page_size page_size +@param[in] page_no page number of given read_buf +@param[in] strict_check true if strict-check option is enabled +@return true if page is encrypted AND OK, false otherwise */ +UNIV_INTERN +bool +fil_space_verify_crypt_checksum( +/*============================*/ + const byte* src_frame, /*!< in: page the verify */ + const page_size_t& page_size /*!< in: page size */ + ,uintmax_t page_no, + bool strict_check); + /* Global variables */ static bool verbose; static bool just_count; @@ -564,9 +582,25 @@ is_page_corrupted( } } - is_corrupted = buf_page_is_corrupted( - true, buf, page_size, false, cur_page_num, strict_verify, - is_log_enabled, log_file); + /* If page is encrypted, use different checksum calculation + as innochecksum can't decrypt pages. Note that some old InnoDB + versions did not initialize FIL_PAGE_FILE_FLUSH_LSN field + so if crypt checksum does not match we verify checksum using + normal method. + */ + if (mach_read_from_4(buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) != 0) { + is_corrupted = fil_space_verify_crypt_checksum(buf, page_size, + cur_page_num, strict_verify); + } else { + is_corrupted = true; + } + + if (is_corrupted) { + is_corrupted = buf_page_is_corrupted( + true, buf, page_size, false, + cur_page_num, strict_verify, + is_log_enabled, log_file); + } return(is_corrupted); } diff --git a/mysql-test/suite/encryption/disabled.def b/mysql-test/suite/encryption/disabled.def index f8d7fb51865..c4394b26947 100644 --- a/mysql-test/suite/encryption/disabled.def +++ b/mysql-test/suite/encryption/disabled.def @@ -13,4 +13,4 @@ innodb_scrub : MDEV-8139 innodb_scrub_compressed : MDEV-8139 innodb_scrub_background : MDEV-8139 -innochecksum: see buf_page_is_corrupted() + diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 638126f8de1..59b3ee4ca7e 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -846,7 +846,7 @@ buf_page_is_corrupted( ulint checksum_field2; bool page_encrypted = false; -#ifndef UNIV_INNOCHECKSUM // FIXME see also encryption.innochecksum test +#ifndef UNIV_INNOCHECKSUM ulint space_id = mach_read_from_4( read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); fil_space_crypt_t* crypt_data = fil_space_get_crypt_data(space_id); @@ -859,6 +859,12 @@ buf_page_is_corrupted( fil_page_is_encrypted(read_buf)) { page_encrypted = true; } +#else + if (mach_read_from_4(read_buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) != 0 + || mach_read_from_2(read_buf+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { + page_encrypted = true; + } + #endif DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(TRUE); ); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 708dbd0fd01..ff30b3a09e9 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2014, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,14 +24,16 @@ Modified Jan Lindström jan.lindstrom@mariadb.com *******************************************************/ #include "fil0fil.h" +#include "mach0data.h" +#include "page0size.h" +#include "page0zip.h" +#ifndef UNIV_INNOCHECKSUM #include "fil0crypt.h" #include "srv0srv.h" #include "srv0start.h" -#include "mach0data.h" #include "log0recv.h" #include "mtr0mtr.h" #include "mtr0log.h" -#include "page0zip.h" #include "ut0ut.h" #include "btr0scrub.h" #include "fsp0fsp.h" @@ -910,81 +912,6 @@ fil_crypt_calculate_checksum( return checksum; } -/********************************************************************* -Verify checksum for a page (iff it's encrypted) -NOTE: currently this function can only be run in single threaded mode -as it modifies srv_checksum_algorithm (temporarily) -@return true if page is encrypted AND OK, false otherwise */ -UNIV_INTERN -bool -fil_space_verify_crypt_checksum( -/*============================*/ - const byte* src_frame, /*!< in: page the verify */ - const page_size_t& page_size) /*!< in: page size */ -{ - // key version - uint key_version = mach_read_from_4( - src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); - - if (key_version == 0) { - return false; // unencrypted page - } - - /* "trick" the normal checksum routines by storing the post-encryption - * checksum into the normal checksum field allowing for reuse of - * the normal routines */ - - // post encryption checksum - ib_uint32_t stored_post_encryption = mach_read_from_4( - src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4); - - // save pre encryption checksum for restore in end of this function - ib_uint32_t stored_pre_encryption = mach_read_from_4( - src_frame + FIL_PAGE_SPACE_OR_CHKSUM); - - ib_uint32_t checksum_field2 = mach_read_from_4( - src_frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); - - /** prepare frame for usage of normal checksum routines */ - mach_write_to_4(const_cast(src_frame) + FIL_PAGE_SPACE_OR_CHKSUM, - stored_post_encryption); - - /* NOTE: this function is (currently) only run when restoring - * dblwr-buffer, server is single threaded so it's safe to modify - * srv_checksum_algorithm */ - srv_checksum_algorithm_t save_checksum_algorithm = - (srv_checksum_algorithm_t)srv_checksum_algorithm; - - if (!page_size.is_compressed() && - (save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB || - save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) { - /* handle ALGORITHM_INNODB specially, - * "downgrade" to ALGORITHM_INNODB and store BUF_NO_CHECKSUM_MAGIC - * checksum_field2 is sort of pointless anyway... - */ - srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB; - mach_write_to_4(const_cast(src_frame) + - UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, - BUF_NO_CHECKSUM_MAGIC); - } - - /* verify checksums */ - ibool corrupted = buf_page_is_corrupted(false, src_frame, page_size, false); - - /** restore frame & algorithm */ - srv_checksum_algorithm = save_checksum_algorithm; - - mach_write_to_4(const_cast(src_frame) + - FIL_PAGE_SPACE_OR_CHKSUM, - stored_pre_encryption); - - mach_write_to_4(const_cast(src_frame) + - UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, - checksum_field2); - - return (!corrupted); -} - /***********************************************************************/ /** A copy of global key state */ @@ -2671,3 +2598,93 @@ fil_space_get_scrub_status( return crypt_data == NULL ? 1 : 0; } +#endif /* UNIV_INNOCHECKSUM */ + +/********************************************************************* +Verify checksum for a page (iff it's encrypted) +NOTE: currently this function can only be run in single threaded mode +as it modifies srv_checksum_algorithm (temporarily) +@param[in] src_fame page to verify +@param[in] page_size page_size +@param[in] page_no page number of given read_buf +@param[in] strict_check true if strict-check option is enabled +@return true if page is encrypted AND OK, false otherwise */ +UNIV_INTERN +bool +fil_space_verify_crypt_checksum( +/*============================*/ + const byte* src_frame, /*!< in: page the verify */ + const page_size_t& page_size /*!< in: page size */ +#ifdef UNIV_INNOCHECKSUM + ,uintmax_t page_no, + bool strict_check +#endif /* UNIV_INNOCHECKSUM */ +) +{ + // key version + uint key_version = mach_read_from_4( + src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); + + if (key_version == 0) { + return false; // unencrypted page + } + + /* "trick" the normal checksum routines by storing the post-encryption + * checksum into the normal checksum field allowing for reuse of + * the normal routines */ + + // post encryption checksum + ib_uint32_t stored_post_encryption = mach_read_from_4( + src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4); + + // save pre encryption checksum for restore in end of this function + ib_uint32_t stored_pre_encryption = mach_read_from_4( + src_frame + FIL_PAGE_SPACE_OR_CHKSUM); + + ib_uint32_t checksum_field2 = mach_read_from_4( + src_frame + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); + + /** prepare frame for usage of normal checksum routines */ + mach_write_to_4(const_cast(src_frame) + FIL_PAGE_SPACE_OR_CHKSUM, + stored_post_encryption); + + /* NOTE: this function is (currently) only run when restoring + * dblwr-buffer, server is single threaded so it's safe to modify + * srv_checksum_algorithm */ + srv_checksum_algorithm_t save_checksum_algorithm = + (srv_checksum_algorithm_t)srv_checksum_algorithm; + + if (!page_size.is_compressed() && + (save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB || + save_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB)) { + /* handle ALGORITHM_INNODB specially, + * "downgrade" to ALGORITHM_INNODB and store BUF_NO_CHECKSUM_MAGIC + * checksum_field2 is sort of pointless anyway... + */ + srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB; + mach_write_to_4(const_cast(src_frame) + + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, + BUF_NO_CHECKSUM_MAGIC); + } + + /* verify checksums */ + bool corrupted = buf_page_is_corrupted(false, src_frame, + page_size, false +#ifdef UNIV_INNOCHECKSUM + ,page_no, strict_check, false, NULL +#endif /* UNIV_INNOCHECKSUM */ + ); + + /** restore frame & algorithm */ + srv_checksum_algorithm = save_checksum_algorithm; + + mach_write_to_4(const_cast(src_frame) + + FIL_PAGE_SPACE_OR_CHKSUM, + stored_pre_encryption); + + mach_write_to_4(const_cast(src_frame) + + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, + checksum_field2); + + return (!corrupted); +} diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 60ed4e01422..43b31002306 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. -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 @@ -1718,13 +1718,14 @@ fil_space_create( fil_system->max_assigned_id = id; } +#ifdef UNIV_DEBUG if (crypt_data) { - space->read_page0 = true; /* If table could be encrypted print info */ ib::info() << "Tablespace ID " << id << " name " << space->name << ":" << fil_crypt_get_mode(crypt_data) << " " << fil_crypt_get_type(crypt_data); } +#endif mutex_exit(&fil_system->mutex); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 1e07c4f8fb5..30d79a52b4d 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 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 @@ -190,9 +190,6 @@ struct fil_space_t { /** True if we have already printed compression failure */ bool printed_compression_failure; - /** True if page 0 of tablespace is read */ - bool read_page0; - /** Release the reserved free extents. @param[in] n_reserved number of reserved extents */ void release_free_extents(ulint n_reserved); From ba8198a34cf651cce8a1f59f61ba7f31dbe41579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 15:44:44 +0200 Subject: [PATCH 014/167] Post-fix for MDEV-11688 fil_crypt_threads_end() tries to create threads fil_crypt_threads_cleanup(): Do nothing if nothing was initialized. --- storage/innobase/fil/fil0crypt.cc | 3 +++ storage/xtradb/fil/fil0crypt.cc | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 6482956eb0a..1eaabf68678 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2477,6 +2477,9 @@ void fil_crypt_threads_cleanup() /*=======================*/ { + if (!fil_crypt_threads_inited) { + return; + } os_event_free(fil_crypt_event); os_event_free(fil_crypt_threads_event); mutex_free(&fil_crypt_threads_mutex); diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc index 6483cdc5a53..1eaabf68678 100644 --- a/storage/xtradb/fil/fil0crypt.cc +++ b/storage/xtradb/fil/fil0crypt.cc @@ -2465,8 +2465,9 @@ void fil_crypt_threads_end() /*===================*/ { - /* stop threads */ - fil_crypt_set_thread_cnt(0); + if (fil_crypt_threads_inited) { + fil_crypt_set_thread_cnt(0); + } } /********************************************************************* @@ -2476,6 +2477,9 @@ void fil_crypt_threads_cleanup() /*=======================*/ { + if (!fil_crypt_threads_inited) { + return; + } os_event_free(fil_crypt_event); os_event_free(fil_crypt_threads_event); mutex_free(&fil_crypt_threads_mutex); From a758479c103f513077a0b90a9285b17229ee8289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 15:44:44 +0200 Subject: [PATCH 015/167] Post-fix for MDEV-11688 fil_crypt_threads_end() tries to create threads fil_crypt_threads_cleanup(): Do nothing if nothing was initialized. --- storage/innobase/fil/fil0crypt.cc | 3 +++ storage/xtradb/fil/fil0crypt.cc | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index ff30b3a09e9..a0c9fbf57ac 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -2397,6 +2397,9 @@ void fil_crypt_threads_cleanup() /*=======================*/ { + if (!fil_crypt_threads_inited) { + return; + } os_event_destroy(fil_crypt_event); os_event_destroy(fil_crypt_threads_event); mutex_free(&fil_crypt_threads_mutex); diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc index 3670f0fac4f..6252a5470bd 100644 --- a/storage/xtradb/fil/fil0crypt.cc +++ b/storage/xtradb/fil/fil0crypt.cc @@ -2465,8 +2465,9 @@ void fil_crypt_threads_end() /*===================*/ { - /* stop threads */ - fil_crypt_set_thread_cnt(0); + if (fil_crypt_threads_inited) { + fil_crypt_set_thread_cnt(0); + } } /********************************************************************* @@ -2476,6 +2477,9 @@ void fil_crypt_threads_cleanup() /*=======================*/ { + if (!fil_crypt_threads_inited) { + return; + } os_event_free(fil_crypt_event); os_event_free(fil_crypt_threads_event); mutex_free(&fil_crypt_threads_mutex); From 80d5d1452a4a6b7bd1627116f2a5a950003fc3cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 19:32:47 +0200 Subject: [PATCH 016/167] MDEV-11694 InnoDB tries to create unused table SYS_ZIP_DICT MariaDB Server 10.0.28 and 10.1.19 merged code from Percona XtraDB that introduced support for compressed columns. Much but not all of this code was disabled by placing #ifdef HAVE_PERCONA_COMPRESSED_COLUMNS around it. Among the unused but not disabled code is code to access some new system tables related to compressed columns. The creation of these system tables SYS_ZIP_DICT and SYS_ZIP_DICT_COLS would cause a crash in --innodb-read-only mode when upgrading from an earlier version to 10.0.28 or 10.1.19. Let us remove all the dead code related to compressed columns. Users who already upgraded to 10.0.28 and 10.1.19 will have the two above mentioned empty tables in their InnoDB system tablespace. Subsequent versions of MariaDB Server will completely ignore those tables. --- storage/xtradb/dict/dict0boot.cc | 5 +- storage/xtradb/dict/dict0crea.cc | 583 +----------------------- storage/xtradb/dict/dict0dict.cc | 160 +------ storage/xtradb/dict/dict0load.cc | 160 +------ storage/xtradb/handler/ha_innodb.cc | 415 +---------------- storage/xtradb/handler/ha_innodb.h | 38 +- storage/xtradb/handler/handler0alter.cc | 62 +-- storage/xtradb/handler/xtradb_i_s.cc | 330 +------------- storage/xtradb/handler/xtradb_i_s.h | 3 +- storage/xtradb/include/data0type.h | 15 +- storage/xtradb/include/data0type.ic | 16 +- storage/xtradb/include/dict0boot.h | 33 +- storage/xtradb/include/dict0boot.ic | 3 +- storage/xtradb/include/dict0crea.h | 90 +--- storage/xtradb/include/dict0dict.h | 48 +- storage/xtradb/include/dict0load.h | 29 +- storage/xtradb/include/row0mysql.h | 85 +--- storage/xtradb/rem/rem0rec.cc | 18 +- storage/xtradb/row/row0merge.cc | 7 +- storage/xtradb/row/row0mysql.cc | 583 +----------------------- storage/xtradb/row/row0sel.cc | 39 +- storage/xtradb/srv/srv0start.cc | 7 +- 22 files changed, 60 insertions(+), 2669 deletions(-) diff --git a/storage/xtradb/dict/dict0boot.cc b/storage/xtradb/dict/dict0boot.cc index c0bb0298bea..20ab5d75205 100644 --- a/storage/xtradb/dict/dict0boot.cc +++ b/storage/xtradb/dict/dict0boot.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -272,10 +273,6 @@ dict_boot(void) ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME == 2); ut_ad(DICT_NUM_COLS__SYS_FOREIGN_COLS == 4); ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_COLS == 6); - ut_ad(DICT_NUM_COLS__SYS_ZIP_DICT == 3); - ut_ad(DICT_NUM_FIELDS__SYS_ZIP_DICT == 5); - ut_ad(DICT_NUM_COLS__SYS_ZIP_DICT_COLS == 3); - ut_ad(DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS == 5); mtr_start(&mtr); diff --git a/storage/xtradb/dict/dict0crea.cc b/storage/xtradb/dict/dict0crea.cc index db0ca638de4..9a4040421d7 100644 --- a/storage/xtradb/dict/dict0crea.cc +++ b/storage/xtradb/dict/dict0crea.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -1932,135 +1933,6 @@ dict_create_or_check_sys_tablespace(void) return(err); } -/** Creates the zip_dict system table inside InnoDB -at server bootstrap or server start if it is not found or is -not of the right form. -@return DB_SUCCESS or error code */ -UNIV_INTERN -dberr_t -dict_create_or_check_sys_zip_dict(void) -{ - trx_t* trx; - my_bool srv_file_per_table_backup; - dberr_t err; - dberr_t sys_zip_dict_err; - dberr_t sys_zip_dict_cols_err; - - ut_a(srv_get_active_thread_type() == SRV_NONE); - - /* Note: The master thread has not been started at this point. */ - - sys_zip_dict_err = dict_check_if_system_table_exists( - "SYS_ZIP_DICT", DICT_NUM_FIELDS__SYS_ZIP_DICT + 1, 2); - sys_zip_dict_cols_err = dict_check_if_system_table_exists( - "SYS_ZIP_DICT_COLS", DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS + 1, - 1); - - if (sys_zip_dict_err == DB_SUCCESS && - sys_zip_dict_cols_err == DB_SUCCESS) - return (DB_SUCCESS); - - trx = trx_allocate_for_mysql(); - - trx_set_dict_operation(trx, TRX_DICT_OP_TABLE); - - trx->op_info = "creating zip_dict and zip_dict_cols sys tables"; - - row_mysql_lock_data_dictionary(trx); - - /* Check which incomplete table definition to drop. */ - - if (sys_zip_dict_err == DB_CORRUPTION) { - ib_logf(IB_LOG_LEVEL_WARN, - "Dropping incompletely created " - "SYS_ZIP_DICT table."); - row_drop_table_for_mysql("SYS_ZIP_DICT", trx, TRUE, TRUE); - } - if (sys_zip_dict_cols_err == DB_CORRUPTION) { - ib_logf(IB_LOG_LEVEL_WARN, - "Dropping incompletely created " - "SYS_ZIP_DICT_COLS table."); - row_drop_table_for_mysql("SYS_ZIP_DICT_COLS", trx, TRUE, TRUE); - } - - ib_logf(IB_LOG_LEVEL_INFO, - "Creating zip_dict and zip_dict_cols system tables."); - - /* We always want SYSTEM tables to be created inside the system - tablespace. */ - srv_file_per_table_backup = srv_file_per_table; - srv_file_per_table = 0; - - err = que_eval_sql( - NULL, - "PROCEDURE CREATE_SYS_ZIP_DICT_PROC () IS\n" - "BEGIN\n" - "CREATE TABLE SYS_ZIP_DICT(\n" - " ID INT UNSIGNED NOT NULL,\n" - " NAME CHAR(" - STRINGIFY_ARG(ZIP_DICT_MAX_NAME_LENGTH) - ") NOT NULL,\n" - " DATA BLOB NOT NULL\n" - ");\n" - "CREATE UNIQUE CLUSTERED INDEX SYS_ZIP_DICT_ID" - " ON SYS_ZIP_DICT (ID);\n" - "CREATE UNIQUE INDEX SYS_ZIP_DICT_NAME" - " ON SYS_ZIP_DICT (NAME);\n" - "CREATE TABLE SYS_ZIP_DICT_COLS(\n" - " TABLE_ID INT UNSIGNED NOT NULL,\n" - " COLUMN_POS INT UNSIGNED NOT NULL,\n" - " DICT_ID INT UNSIGNED NOT NULL\n" - ");\n" - "CREATE UNIQUE CLUSTERED INDEX SYS_ZIP_DICT_COLS_COMPOSITE" - " ON SYS_ZIP_DICT_COLS (TABLE_ID, COLUMN_POS);\n" - "END;\n", - FALSE, trx); - - if (err != DB_SUCCESS) { - ib_logf(IB_LOG_LEVEL_ERROR, - "Creation of SYS_ZIP_DICT and SYS_ZIP_DICT_COLS" - "has failed with error %lu. Tablespace is full. " - "Dropping incompletely created tables.", - (ulong) err); - - ut_a(err == DB_OUT_OF_FILE_SPACE - || err == DB_TOO_MANY_CONCURRENT_TRXS); - - row_drop_table_for_mysql("SYS_ZIP_DICT", trx, TRUE, TRUE); - row_drop_table_for_mysql("SYS_ZIP_DICT_COLS", trx, TRUE, TRUE); - - if (err == DB_OUT_OF_FILE_SPACE) { - err = DB_MUST_GET_MORE_FILE_SPACE; - } - } - - trx_commit_for_mysql(trx); - - row_mysql_unlock_data_dictionary(trx); - - trx_free_for_mysql(trx); - - srv_file_per_table = srv_file_per_table_backup; - - if (err == DB_SUCCESS) { - ib_logf(IB_LOG_LEVEL_INFO, - "zip_dict and zip_dict_cols system tables created."); - } - - /* Note: The master thread has not been started at this point. */ - /* Confirm and move to the non-LRU part of the table LRU list. */ - - sys_zip_dict_err = dict_check_if_system_table_exists( - "SYS_ZIP_DICT", DICT_NUM_FIELDS__SYS_ZIP_DICT + 1, 2); - ut_a(sys_zip_dict_err == DB_SUCCESS); - sys_zip_dict_cols_err = dict_check_if_system_table_exists( - "SYS_ZIP_DICT_COLS", - DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS + 1, 1); - ut_a(sys_zip_dict_cols_err == DB_SUCCESS); - - return(err); -} - /********************************************************************//** Add a single tablespace definition to the data dictionary tables in the database. @@ -2114,456 +1986,3 @@ dict_create_add_tablespace_to_dictionary( return(error); } - -/** Add a single compression dictionary definition to the SYS_ZIP_DICT -InnoDB system table. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_add_zip_dict( - const char* name, /*!< in: dict name */ - ulint name_len, /*!< in: dict name length */ - const char* data, /*!< in: dict data */ - ulint data_len, /*!< in: dict data length */ - trx_t* trx) /*!< in/out: transaction */ -{ - ut_ad(name); - ut_ad(data); - - pars_info_t* info = pars_info_create(); - - pars_info_add_literal(info, "name", name, name_len, - DATA_VARCHAR, DATA_ENGLISH); - pars_info_add_literal(info, "data", data, data_len, - DATA_BLOB, DATA_BINARY_TYPE | DATA_NOT_NULL); - - dberr_t error = que_eval_sql(info, - "PROCEDURE P () IS\n" - " max_id INT;\n" - "DECLARE CURSOR cur IS\n" - " SELECT ID FROM SYS_ZIP_DICT\n" - " ORDER BY ID DESC;\n" - "BEGIN\n" - " max_id := 0;\n" - " OPEN cur;\n" - " FETCH cur INTO max_id;\n" - " IF (cur % NOTFOUND) THEN\n" - " max_id := 0;\n" - " END IF;\n" - " CLOSE cur;\n" - " INSERT INTO SYS_ZIP_DICT VALUES" - " (max_id + 1, :name, :data);\n" - "END;\n", - FALSE, trx); - - return error; -} - -/** Fetch callback, just stores extracted zip_dict id in the external -variable. -@return TRUE if all OK */ -static -ibool -dict_create_extract_int_aux( - void* row, /*!< in: sel_node_t* */ - void* user_arg) /*!< in: int32 id */ -{ - sel_node_t* node = static_cast(row); - dfield_t* dfield = que_node_get_val(node->select_list); - dtype_t* type = dfield_get_type(dfield); - ulint len = dfield_get_len(dfield); - - ut_a(dtype_get_mtype(type) == DATA_INT); - ut_a(len == sizeof(ib_uint32_t)); - - memcpy(user_arg, dfield_get_data(dfield), sizeof(ib_uint32_t)); - - return(TRUE); -} - -/** Add a single compression dictionary reference to the SYS_ZIP_DICT_COLS -InnoDB system table. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_add_zip_dict_reference( - ulint table_id, /*!< in: table id */ - ulint column_pos, /*!< in: column position */ - ulint dict_id, /*!< in: dict id */ - trx_t* trx) /*!< in/out: transaction */ -{ - pars_info_t* info = pars_info_create(); - - pars_info_add_int4_literal(info, "table_id", table_id); - pars_info_add_int4_literal(info, "column_pos", column_pos); - pars_info_add_int4_literal(info, "dict_id", dict_id); - - dberr_t error = que_eval_sql(info, - "PROCEDURE P () IS\n" - "BEGIN\n" - " INSERT INTO SYS_ZIP_DICT_COLS VALUES" - " (:table_id, :column_pos, :dict_id);\n" - "END;\n", - FALSE, trx); - return error; -} - -/** Get a single compression dictionary id for the given -(table id, column pos) pair. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_get_zip_dict_id_by_reference( - ulint table_id, /*!< in: table id */ - ulint column_pos, /*!< in: column position */ - ulint* dict_id, /*!< out: dict id */ - trx_t* trx) /*!< in/out: transaction */ -{ - ut_ad(dict_id); - - pars_info_t* info = pars_info_create(); - - ib_uint32_t dict_id_buf; - mach_write_to_4(reinterpret_cast(&dict_id_buf ), - ULINT32_UNDEFINED); - - pars_info_add_int4_literal(info, "table_id", table_id); - pars_info_add_int4_literal(info, "column_pos", column_pos); - pars_info_bind_function( - info, "my_func", dict_create_extract_int_aux, &dict_id_buf); - - dberr_t error = que_eval_sql(info, - "PROCEDURE P () IS\n" - "DECLARE FUNCTION my_func;\n" - "DECLARE CURSOR cur IS\n" - " SELECT DICT_ID FROM SYS_ZIP_DICT_COLS\n" - " WHERE TABLE_ID = :table_id AND\n" - " COLUMN_POS = :column_pos;\n" - "BEGIN\n" - " OPEN cur;\n" - " FETCH cur INTO my_func();\n" - " CLOSE cur;\n" - "END;\n", - FALSE, trx); - if (error == DB_SUCCESS) { - ib_uint32_t local_dict_id = mach_read_from_4( - reinterpret_cast(&dict_id_buf)); - if (local_dict_id == ULINT32_UNDEFINED) - error = DB_RECORD_NOT_FOUND; - else - *dict_id = local_dict_id; - } - return error; -} - -/** Get compression dictionary id for the given name. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_get_zip_dict_id_by_name( - const char* dict_name, /*!< in: dict name */ - ulint dict_name_len, /*!< in: dict name length */ - ulint* dict_id, /*!< out: dict id */ - trx_t* trx) /*!< in/out: transaction */ -{ - ut_ad(dict_name); - ut_ad(dict_name_len); - ut_ad(dict_id); - - pars_info_t* info = pars_info_create(); - - pars_info_add_literal(info, "dict_name", dict_name, dict_name_len, - DATA_VARCHAR, DATA_ENGLISH); - - ib_uint32_t dict_id_buf; - mach_write_to_4(reinterpret_cast(&dict_id_buf), - ULINT32_UNDEFINED); - pars_info_bind_function( - info, "my_func", dict_create_extract_int_aux, &dict_id_buf); - - dberr_t error = que_eval_sql(info, - "PROCEDURE P () IS\n" - "DECLARE FUNCTION my_func;\n" - "DECLARE CURSOR cur IS\n" - " SELECT ID FROM SYS_ZIP_DICT\n" - " WHERE NAME = :dict_name;\n" - "BEGIN\n" - " OPEN cur;\n" - " FETCH cur INTO my_func();\n" - " CLOSE cur;\n" - "END;\n", - FALSE, trx); - if (error == DB_SUCCESS) { - ib_uint32_t local_dict_id = mach_read_from_4( - reinterpret_cast(&dict_id_buf)); - if (local_dict_id == ULINT32_UNDEFINED) - error = DB_RECORD_NOT_FOUND; - else - *dict_id = local_dict_id; - } - return error; -} - -/** Auxiliary enum used to indicate zip dict data extraction result code */ -enum zip_dict_info_aux_code { - zip_dict_info_success, /*!< success */ - zip_dict_info_not_found, /*!< zip dict record not found */ - zip_dict_info_oom, /*!< out of memory */ - zip_dict_info_corrupted_name, /*!< corrupted zip dict name */ - zip_dict_info_corrupted_data /*!< corrupted zip dict data */ -}; - -/** Auxiliary struct used to return zip dict info aling with result code */ -struct zip_dict_info_aux { - LEX_STRING name; /*!< zip dict name */ - LEX_STRING data; /*!< zip dict data */ - int code; /*!< result code (0 - success) */ -}; - -/** Fetch callback, just stores extracted zip_dict data in the external -variable. -@return always returns TRUE */ -static -ibool -dict_create_get_zip_dict_info_by_id_aux( - void* row, /*!< in: sel_node_t* */ - void* user_arg) /*!< in: pointer to zip_dict_info_aux* */ -{ - sel_node_t* node = static_cast(row); - zip_dict_info_aux* result = - static_cast(user_arg); - - result->code = zip_dict_info_success; - result->name.str = 0; - result->name.length = 0; - result->data.str = 0; - result->data.length = 0; - - /* NAME field */ - que_node_t* exp = node->select_list; - ut_a(exp != 0); - - dfield_t* dfield = que_node_get_val(exp); - dtype_t* type = dfield_get_type(dfield); - ut_a(dtype_get_mtype(type) == DATA_VARCHAR); - - ulint len = dfield_get_len(dfield); - void* data = dfield_get_data(dfield); - - - if (len == UNIV_SQL_NULL) { - result->code = zip_dict_info_corrupted_name; - } - else { - result->name.str = - static_cast(my_malloc(len + 1, MYF(0))); - if (result->name.str == 0) { - result->code = zip_dict_info_oom; - } - else { - memcpy(result->name.str, data, len); - result->name.str[len] = '\0'; - result->name.length = len; - } - } - - /* DATA field */ - exp = que_node_get_next(exp); - ut_a(exp != 0); - - dfield = que_node_get_val(exp); - type = dfield_get_type(dfield); - ut_a(dtype_get_mtype(type) == DATA_BLOB); - - len = dfield_get_len(dfield); - data = dfield_get_data(dfield); - - if (len == UNIV_SQL_NULL) { - result->code = zip_dict_info_corrupted_data; - } - else { - result->data.str = - static_cast(my_malloc( - len == 0 ? 1 : len, MYF(0))); - if (result->data.str == 0) { - result->code = zip_dict_info_oom; - } - else { - memcpy(result->data.str, data, len); - result->data.length = len; - } - } - - ut_ad(que_node_get_next(exp) == 0); - - if (result->code != zip_dict_info_success) { - if (result->name.str == 0) { - mem_free(result->name.str); - result->name.str = 0; - result->name.length = 0; - } - if (result->data.str == 0) { - mem_free(result->data.str); - result->data.str = 0; - result->data.length = 0; - } - } - - return TRUE; -} - -/** Get compression dictionary info (name and data) for the given id. -Allocates memory for name and data on success. -Must be freed with mem_free(). -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_get_zip_dict_info_by_id( - ulint dict_id, /*!< in: dict id */ - char** name, /*!< out: dict name */ - ulint* name_len, /*!< out: dict name length*/ - char** data, /*!< out: dict data */ - ulint* data_len, /*!< out: dict data length*/ - trx_t* trx) /*!< in/out: transaction */ -{ - ut_ad(name); - ut_ad(data); - - zip_dict_info_aux rec; - rec.code = zip_dict_info_not_found; - pars_info_t* info = pars_info_create(); - - pars_info_add_int4_literal(info, "id", dict_id); - pars_info_bind_function( - info, "my_func", dict_create_get_zip_dict_info_by_id_aux, - &rec); - - dberr_t error = que_eval_sql(info, - "PROCEDURE P () IS\n" - "DECLARE FUNCTION my_func;\n" - "DECLARE CURSOR cur IS\n" - " SELECT NAME, DATA FROM SYS_ZIP_DICT\n" - " WHERE ID = :id;\n" - "BEGIN\n" - " OPEN cur;\n" - " FETCH cur INTO my_func();\n" - " CLOSE cur;\n" - "END;\n", - FALSE, trx); - if (error == DB_SUCCESS) { - switch (rec.code) { - case zip_dict_info_success: - *name = rec.name.str; - *name_len = rec.name.length; - *data = rec.data.str; - *data_len = rec.data.length; - break; - case zip_dict_info_not_found: - error = DB_RECORD_NOT_FOUND; - break; - case zip_dict_info_oom: - error = DB_OUT_OF_MEMORY; - break; - case zip_dict_info_corrupted_name: - case zip_dict_info_corrupted_data: - error = DB_INVALID_NULL; - break; - default: - ut_error; - } - } - return error; -} - -/** Remove a single compression dictionary from the data dictionary -tables in the database. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_remove_zip_dict( - const char* name, /*!< in: dict name */ - ulint name_len, /*!< in: dict name length */ - trx_t* trx) /*!< in/out: transaction */ -{ - ut_ad(name); - - pars_info_t* info = pars_info_create(); - - ib_uint32_t dict_id_buf; - mach_write_to_4(reinterpret_cast(&dict_id_buf), - ULINT32_UNDEFINED); - ib_uint32_t counter_buf; - mach_write_to_4(reinterpret_cast(&counter_buf), - ULINT32_UNDEFINED); - - pars_info_add_literal(info, "name", name, name_len, - DATA_VARCHAR, DATA_ENGLISH); - pars_info_bind_int4_literal(info, "dict_id", &dict_id_buf); - pars_info_bind_function(info, "find_dict_func", - dict_create_extract_int_aux, &dict_id_buf); - pars_info_bind_function(info, "count_func", - dict_create_extract_int_aux, &counter_buf); - - dberr_t error = que_eval_sql(info, - "PROCEDURE P () IS\n" - "DECLARE FUNCTION find_dict_func;\n" - "DECLARE FUNCTION count_func;\n" - "DECLARE CURSOR dict_cur IS\n" - " SELECT ID FROM SYS_ZIP_DICT\n" - " WHERE NAME = :name\n" - " FOR UPDATE;\n" - "DECLARE CURSOR ref_cur IS\n" - " SELECT 1 FROM SYS_ZIP_DICT_COLS\n" - " WHERE DICT_ID = :dict_id;\n" - "BEGIN\n" - " OPEN dict_cur;\n" - " FETCH dict_cur INTO find_dict_func();\n" - " IF NOT (SQL % NOTFOUND) THEN\n" - " OPEN ref_cur;\n" - " FETCH ref_cur INTO count_func();\n" - " IF SQL % NOTFOUND THEN\n" - " DELETE FROM SYS_ZIP_DICT WHERE CURRENT OF dict_cur;\n" - " END IF;\n" - " CLOSE ref_cur;\n" - " END IF;\n" - " CLOSE dict_cur;\n" - "END;\n", - FALSE, trx); - if (error == DB_SUCCESS) { - ib_uint32_t local_dict_id = mach_read_from_4( - reinterpret_cast(&dict_id_buf)); - if (local_dict_id == ULINT32_UNDEFINED) { - error = DB_RECORD_NOT_FOUND; - } - else { - ib_uint32_t local_counter = mach_read_from_4( - reinterpret_cast(&counter_buf)); - if (local_counter != ULINT32_UNDEFINED) - error = DB_ROW_IS_REFERENCED; - } - } - return error; -} - -/** Remove all compression dictionary references for the given table ID from -the data dictionary tables in the database. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_remove_zip_dict_references_for_table( - ulint table_id, /*!< in: table id */ - trx_t* trx) /*!< in/out: transaction */ -{ - pars_info_t* info = pars_info_create(); - - pars_info_add_int4_literal(info, "table_id", table_id); - - dberr_t error = que_eval_sql(info, - "PROCEDURE P () IS\n" - "BEGIN\n" - " DELETE FROM SYS_ZIP_DICT_COLS\n" - " WHERE TABLE_ID = :table_id;\n" - "END;\n", - FALSE, trx); - return error; -} diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 3845138c8bf..339e5615bea 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/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) 2014, 2015, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -7288,161 +7288,3 @@ dict_tf_to_row_format_string( return(0); } #endif /* !UNIV_HOTBACKUP */ - -/** Insert a records into SYS_ZIP_DICT. -@retval DB_SUCCESS if OK -@retval dberr_t if the insert failed */ -UNIV_INTERN -dberr_t -dict_create_zip_dict( - const char* name, /*!< in: zip_dict name */ - ulint name_len, /*!< in: zip_dict name length*/ - const char* data, /*!< in: zip_dict data */ - ulint data_len) /*!< in: zip_dict data length */ -{ - dberr_t err = DB_SUCCESS; - trx_t* trx; - - ut_ad(name); - ut_ad(data); - - rw_lock_x_lock(&dict_operation_lock); - dict_mutex_enter_for_mysql(); - - trx = trx_allocate_for_background(); - trx->op_info = "insert zip_dict"; - trx->dict_operation_lock_mode = RW_X_LATCH; - trx_start_if_not_started(trx); - - err = dict_create_add_zip_dict(name, name_len, data, data_len, trx); - - if (err == DB_SUCCESS) { - trx_commit_for_mysql(trx); - } - else { - trx->op_info = "rollback of internal trx on zip_dict table"; - trx_rollback_to_savepoint(trx, NULL); - ut_a(trx->error_state == DB_SUCCESS); - } - trx->op_info = ""; - trx->dict_operation_lock_mode = 0; - trx_free_for_background(trx); - - dict_mutex_exit_for_mysql(); - rw_lock_x_unlock(&dict_operation_lock); - - return err; -} -/** Get single compression dictionary id for the given -(table id, column pos) pair. -@retval DB_SUCCESS if OK -@retval DB_RECORD_NOT_FOUND if not found */ -UNIV_INTERN -dberr_t -dict_get_dictionary_id_by_key( - ulint table_id, /*!< in: table id */ - ulint column_pos, /*!< in: column position */ - ulint* dict_id) /*!< out: zip_dict id */ -{ - dberr_t err = DB_SUCCESS; - trx_t* trx; - - rw_lock_s_lock(&dict_operation_lock); - dict_mutex_enter_for_mysql(); - - trx = trx_allocate_for_background(); - trx->op_info = "get zip dict id by composite key"; - trx->dict_operation_lock_mode = RW_S_LATCH; - trx_start_if_not_started(trx); - - err = dict_create_get_zip_dict_id_by_reference(table_id, column_pos, - dict_id, trx); - - trx_commit_for_mysql(trx); - trx->dict_operation_lock_mode = 0; - trx_free_for_background(trx); - - dict_mutex_exit_for_mysql(); - rw_lock_s_unlock(&dict_operation_lock); - - return err; -} -/** Get compression dictionary info (name and data) for the given id. -Allocates memory in name->str and data->str on success. -Must be freed with mem_free(). -@retval DB_SUCCESS if OK -@retval DB_RECORD_NOT_FOUND if not found */ -UNIV_INTERN -dberr_t -dict_get_dictionary_info_by_id( - ulint dict_id, /*!< in: table name */ - char** name, /*!< out: dictionary name */ - ulint* name_len, /*!< out: dictionary name length*/ - char** data, /*!< out: dictionary data */ - ulint* data_len) /*!< out: dictionary data length*/ -{ - dberr_t err = DB_SUCCESS; - trx_t* trx; - - rw_lock_s_lock(&dict_operation_lock); - dict_mutex_enter_for_mysql(); - - trx = trx_allocate_for_background(); - trx->op_info = "get zip dict name and data by id"; - trx->dict_operation_lock_mode = RW_S_LATCH; - trx_start_if_not_started(trx); - - err = dict_create_get_zip_dict_info_by_id(dict_id, name, name_len, - data, data_len, trx); - - trx_commit_for_mysql(trx); - trx->dict_operation_lock_mode = 0; - trx_free_for_background(trx); - - dict_mutex_exit_for_mysql(); - rw_lock_s_unlock(&dict_operation_lock); - - return err; -} -/** Delete a record in SYS_ZIP_DICT with the given name. -@retval DB_SUCCESS if OK -@retval DB_RECORD_NOT_FOUND if not found -@retval DB_ROW_IS_REFERENCED if in use */ -UNIV_INTERN -dberr_t -dict_drop_zip_dict( - const char* name, /*!< in: zip_dict name */ - ulint name_len) /*!< in: zip_dict name length*/ -{ - dberr_t err = DB_SUCCESS; - trx_t* trx; - - ut_ad(name); - - rw_lock_x_lock(&dict_operation_lock); - dict_mutex_enter_for_mysql(); - - trx = trx_allocate_for_background(); - trx->op_info = "delete zip_dict"; - trx->dict_operation_lock_mode = RW_X_LATCH; - trx_start_if_not_started(trx); - - err = dict_create_remove_zip_dict(name, name_len, trx); - - if (err == DB_SUCCESS) { - trx_commit_for_mysql(trx); - } - else { - trx->op_info = "rollback of internal trx on zip_dict table"; - trx_rollback_to_savepoint(trx, NULL); - ut_a(trx->error_state == DB_SUCCESS); - } - trx->op_info = ""; - trx->dict_operation_lock_mode = 0; - trx_free_for_background(trx); - - dict_mutex_exit_for_mysql(); - rw_lock_x_unlock(&dict_operation_lock); - - return err; -} diff --git a/storage/xtradb/dict/dict0load.cc b/storage/xtradb/dict/dict0load.cc index 9ea4f4d873a..6cbd0a3d488 100644 --- a/storage/xtradb/dict/dict0load.cc +++ b/storage/xtradb/dict/dict0load.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -56,9 +57,7 @@ static const char* SYSTEM_TABLE_NAME[] = { "SYS_FOREIGN", "SYS_FOREIGN_COLS", "SYS_TABLESPACES", - "SYS_DATAFILES", - "SYS_ZIP_DICT", - "SYS_ZIP_DICT_COLS" + "SYS_DATAFILES" }; /* If this flag is TRUE, then we will load the cluster index's (and tables') @@ -730,161 +729,6 @@ err_len: return(NULL); } -/** This function parses a SYS_ZIP_DICT record, extracts necessary -information from the record and returns to caller. -@return error message, or NULL on success */ -UNIV_INTERN -const char* -dict_process_sys_zip_dict( - mem_heap_t* heap, /*!< in/out: heap memory */ - ulint zip_size, /*!< in: nonzero=compressed BLOB page size */ - const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */ - ulint* id, /*!< out: dict id */ - const char** name, /*!< out: dict name */ - const char** data, /*!< out: dict data */ - ulint* data_len) /*!< out: dict data length */ -{ - ulint len; - const byte* field; - - /* Initialize the output values */ - *id = ULINT_UNDEFINED; - *name = NULL; - *data = NULL; - *data_len = 0; - - if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) { - return("delete-marked record in SYS_ZIP_DICT"); - } - - if (UNIV_UNLIKELY( - rec_get_n_fields_old(rec)!= DICT_NUM_FIELDS__SYS_ZIP_DICT)) { - return("wrong number of columns in SYS_ZIP_DICT record"); - } - - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_ZIP_DICT__ID, &len); - if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) { - goto err_len; - } - *id = mach_read_from_4(field); - - rec_get_nth_field_offs_old( - rec, DICT_FLD__SYS_ZIP_DICT__DB_TRX_ID, &len); - if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) { - goto err_len; - } - - rec_get_nth_field_offs_old( - rec, DICT_FLD__SYS_ZIP_DICT__DB_ROLL_PTR, &len); - if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) { - goto err_len; - } - - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_ZIP_DICT__NAME, &len); - if (UNIV_UNLIKELY(len == 0 || len == UNIV_SQL_NULL)) { - goto err_len; - } - *name = mem_heap_strdupl(heap, (char*) field, len); - - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_ZIP_DICT__DATA, &len); - if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) { - goto err_len; - } - - if (rec_get_1byte_offs_flag(rec) == 0 && - rec_2_is_field_extern(rec, DICT_FLD__SYS_ZIP_DICT__DATA)) { - ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE); - - if (UNIV_UNLIKELY - (!memcmp(field + len - BTR_EXTERN_FIELD_REF_SIZE, - field_ref_zero, - BTR_EXTERN_FIELD_REF_SIZE))) { - goto err_len; - } - *data = reinterpret_cast( - btr_copy_externally_stored_field(data_len, field, - zip_size, len, heap, 0)); - } - else { - *data_len = len; - *data = static_cast(mem_heap_dup(heap, field, len)); - } - - return(NULL); - -err_len: - return("incorrect column length in SYS_ZIP_DICT"); -} - -/** This function parses a SYS_ZIP_DICT_COLS record, extracts necessary -information from the record and returns to caller. -@return error message, or NULL on success */ -UNIV_INTERN -const char* -dict_process_sys_zip_dict_cols( - mem_heap_t* heap, /*!< in/out: heap memory */ - const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */ - ulint* table_id, /*!< out: table id */ - ulint* column_pos, /*!< out: column position */ - ulint* dict_id) /*!< out: dict id */ -{ - ulint len; - const byte* field; - - /* Initialize the output values */ - *table_id = ULINT_UNDEFINED; - *column_pos = ULINT_UNDEFINED; - *dict_id = ULINT_UNDEFINED; - - if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, 0))) { - return("delete-marked record in SYS_ZIP_DICT_COLS"); - } - - if (UNIV_UNLIKELY(rec_get_n_fields_old(rec) != - DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS)) { - return("wrong number of columns in SYS_ZIP_DICT_COLS" - " record"); - } - - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_ZIP_DICT_COLS__TABLE_ID, &len); - if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) { -err_len: - return("incorrect column length in SYS_ZIP_DICT_COLS"); - } - *table_id = mach_read_from_4(field); - - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_ZIP_DICT_COLS__COLUMN_POS, &len); - if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) { - goto err_len; - } - *column_pos = mach_read_from_4(field); - - rec_get_nth_field_offs_old( - rec, DICT_FLD__SYS_ZIP_DICT_COLS__DB_TRX_ID, &len); - if (UNIV_UNLIKELY(len != DATA_TRX_ID_LEN && len != UNIV_SQL_NULL)) { - goto err_len; - } - - rec_get_nth_field_offs_old( - rec, DICT_FLD__SYS_ZIP_DICT_COLS__DB_ROLL_PTR, &len); - if (UNIV_UNLIKELY(len != DATA_ROLL_PTR_LEN && len != UNIV_SQL_NULL)) { - goto err_len; - } - - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_ZIP_DICT_COLS__DICT_ID, &len); - if (UNIV_UNLIKELY(len != DICT_FLD_LEN_SPACE)) { - goto err_len; - } - *dict_id = mach_read_from_4(field); - - return(NULL); -} /********************************************************************//** Determine the flags of a table as stored in SYS_TABLES.TYPE and N_COLS. @return ULINT_UNDEFINED if error, else a valid dict_table_t::flags. */ diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index d072e61a237..ff4f218b557 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -107,14 +107,6 @@ this program; if not, write to the Free Software Foundation, Inc., #define thd_get_trx_isolation(X) ((enum_tx_isolation)thd_tx_isolation(X)) -#ifndef HAVE_PERCONA_COMPRESSED_COLUMNS -#define COLUMN_FORMAT_TYPE_COMPRESSED 0xBADF00D -#define SQLCOM_CREATE_COMPRESSION_DICTIONARY 0xDECAF -#define SQLCOM_DROP_COMPRESSION_DICTIONARY 0xC0FFEE -#define ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST 0xDEADFACE -const static LEX_CSTRING null_lex_cstr={0,0}; -#endif - #ifdef MYSQL_DYNAMIC_PLUGIN #define tc_size 400 #define tdc_size 400 @@ -1476,30 +1468,6 @@ normalize_table_name_low( ibool set_lower_case); /* in: TRUE if we want to set name to lower case */ -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS -/** Creates a new compression dictionary. */ -static -handler_create_zip_dict_result -innobase_create_zip_dict( - handlerton* hton, /*!< in: innobase handlerton */ - THD* thd, /*!< in: handle to the MySQL thread */ - const char* name, /*!< in: zip dictionary name */ - ulint* name_len, - /*!< in/out: zip dictionary name length */ - const char* data, /*!< in: zip dictionary data */ - ulint* data_len); - /*!< in/out: zip dictionary data length */ - -/** Drops a existing compression dictionary. */ -static -handler_drop_zip_dict_result -innobase_drop_zip_dict( - handlerton* hton, /*!< in: innobase handlerton */ - THD* thd, /*!< in: handle to the MySQL thread */ - const char* name, /*!< in: zip dictionary name */ - ulint* name_len); - /*!< in/out: zip dictionary name length */ -#endif /*************************************************************//** Checks if buffer pool is big enough to enable backoff algorithm. InnoDB empty free list algorithm backoff requires free pages @@ -3591,10 +3559,6 @@ innobase_init( if (srv_file_per_table) innobase_hton->tablefile_extensions = ha_innobase_exts; -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - innobase_hton->create_zip_dict = innobase_create_zip_dict; - innobase_hton->drop_zip_dict = innobase_drop_zip_dict; -#endif ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); #ifndef DBUG_OFF @@ -4288,90 +4252,6 @@ innobase_purge_changed_page_bitmaps( return (my_bool)log_online_purge_changed_page_bitmaps(lsn); } -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS -/** Creates a new compression dictionary. */ -static -handler_create_zip_dict_result -innobase_create_zip_dict( - handlerton* hton, /*!< in: innobase handlerton */ - THD* thd, /*!< in: handle to the MySQL thread */ - const char* name, /*!< in: zip dictionary name */ - ulint* name_len, - /*!< in/out: zip dictionary name length */ - const char* data, /*!< in: zip dictionary data */ - ulint* data_len) - /*!< in/out: zip dictionary data length */ -{ - handler_create_zip_dict_result result = - HA_CREATE_ZIP_DICT_UNKNOWN_ERROR; - - DBUG_ENTER("innobase_create_zip_dict"); - DBUG_ASSERT(hton == innodb_hton_ptr); - - if (UNIV_UNLIKELY(high_level_read_only)) { - DBUG_RETURN(HA_CREATE_ZIP_DICT_READ_ONLY); - } - - if (UNIV_UNLIKELY(*name_len > ZIP_DICT_MAX_NAME_LENGTH)) { - *name_len = ZIP_DICT_MAX_NAME_LENGTH; - DBUG_RETURN(HA_CREATE_ZIP_DICT_NAME_TOO_LONG); - } - - if (UNIV_UNLIKELY(*data_len > ZIP_DICT_MAX_DATA_LENGTH)) { - *data_len = ZIP_DICT_MAX_DATA_LENGTH; - DBUG_RETURN(HA_CREATE_ZIP_DICT_DATA_TOO_LONG); - } - - switch (dict_create_zip_dict(name, *name_len, data, *data_len)) { - case DB_SUCCESS: - result = HA_CREATE_ZIP_DICT_OK; - break; - case DB_DUPLICATE_KEY: - result = HA_CREATE_ZIP_DICT_ALREADY_EXISTS; - break; - default: - ut_ad(0); - result = HA_CREATE_ZIP_DICT_UNKNOWN_ERROR; - } - DBUG_RETURN(result); -} - -/** Drops a existing compression dictionary. */ -static -handler_drop_zip_dict_result -innobase_drop_zip_dict( - handlerton* hton, /*!< in: innobase handlerton */ - THD* thd, /*!< in: handle to the MySQL thread */ - const char* name, /*!< in: zip dictionary name */ - ulint* name_len) - /*!< in/out: zip dictionary name length */ -{ - handler_drop_zip_dict_result result = HA_DROP_ZIP_DICT_UNKNOWN_ERROR; - - DBUG_ENTER("innobase_drop_zip_dict"); - DBUG_ASSERT(hton == innodb_hton_ptr); - - if (UNIV_UNLIKELY(high_level_read_only)) { - DBUG_RETURN(HA_DROP_ZIP_DICT_READ_ONLY); - } - - switch (dict_drop_zip_dict(name, *name_len)) { - case DB_SUCCESS: - result = HA_DROP_ZIP_DICT_OK; - break; - case DB_RECORD_NOT_FOUND: - result = HA_DROP_ZIP_DICT_DOES_NOT_EXIST; - break; - case DB_ROW_IS_REFERENCED: - result = HA_DROP_ZIP_DICT_IS_REFERENCED; - break; - default: - ut_ad(0); - result = HA_DROP_ZIP_DICT_UNKNOWN_ERROR; - } - DBUG_RETURN(result); -} -#endif /*****************************************************************//** Check whether this is a fake change transaction. @return TRUE if a fake change transaction */ @@ -5941,88 +5821,6 @@ func_exit: DBUG_RETURN(ret); } -/** This function checks if all the compression dictionaries referenced -in table->fields exist in SYS_ZIP_DICT InnoDB system table. -@return true if all referenced dictionaries exist */ -UNIV_INTERN -bool -innobase_check_zip_dicts( - const TABLE* table, /*!< in: table in MySQL data - dictionary */ - ulint* dict_ids, /*!< out: identified zip dict ids - (at least n_fields long) */ - trx_t* trx, /*!< in: transaction */ - const char** err_dict_name) /*!< out: the name of the - zip_dict which does not exist. */ -{ - DBUG_ENTER("innobase_check_zip_dicts"); - - bool res = true; -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - dberr_t err = DB_SUCCESS; - const size_t n_fields = table->s->fields; - - Field* field_ptr; - for (size_t field_idx = 0; err == DB_SUCCESS && field_idx < n_fields; - ++field_idx) - { - field_ptr = table->field[field_idx]; - if (field_ptr->has_associated_compression_dictionary()) { - err = dict_create_get_zip_dict_id_by_name( - field_ptr->zip_dict_name.str, - field_ptr->zip_dict_name.length, - &dict_ids[field_idx], - trx); - ut_a(err == DB_SUCCESS || err == DB_RECORD_NOT_FOUND); - } - else { - dict_ids[field_idx] = ULINT_UNDEFINED; - } - - } - - if (err != DB_SUCCESS) { - res = false; - *err_dict_name = field_ptr->zip_dict_name.str; - } - -#endif - DBUG_RETURN(res); -} - -/** This function creates compression dictionary references in -SYS_ZIP_DICT_COLS InnoDB system table for table_id based on info -in table->fields and provided zip dict ids. */ -UNIV_INTERN -void -innobase_create_zip_dict_references( - const TABLE* table, /*!< in: table in MySQL data - dictionary */ - table_id_t ib_table_id, /*!< in: table ID in Innodb data - dictionary */ - ulint* zip_dict_ids, /*!< in: zip dict ids - (at least n_fields long) */ - trx_t* trx) /*!< in: transaction */ -{ - DBUG_ENTER("innobase_create_zip_dict_references"); - - dberr_t err = DB_SUCCESS; - const size_t n_fields = table->s->fields; - - for (size_t field_idx = 0; err == DB_SUCCESS && field_idx < n_fields; - ++field_idx) - { - if (zip_dict_ids[field_idx] != ULINT_UNDEFINED) { - err = dict_create_add_zip_dict_reference(ib_table_id, - table->field[field_idx]->field_index, - zip_dict_ids[field_idx], trx); - ut_a(err == DB_SUCCESS); - } - } - - DBUG_VOID_RETURN; -} - /*******************************************************************//** This function uses index translation table to quickly locate the requested index structure. @@ -7289,16 +7087,7 @@ ha_innobase::store_key_val_for_row( blob_data = row_mysql_read_blob_ref(&blob_len, (byte*) (record + (ulint) get_field_offset(table, field)), - (ulint) field->pack_length(), -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - field->column_format() == - COLUMN_FORMAT_TYPE_COMPRESSED, - reinterpret_cast( - field->zip_dict_data.str), - field->zip_dict_data.length, prebuilt); -#else - 0, 0, 0, prebuilt); -#endif + (ulint) field->pack_length()); true_len = blob_len; @@ -7613,14 +7402,6 @@ build_template_field( templ->mbminlen = dict_col_get_mbminlen(col); templ->mbmaxlen = dict_col_get_mbmaxlen(col); templ->is_unsigned = col->prtype & DATA_UNSIGNED; -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - templ->compressed = (field->column_format() - == COLUMN_FORMAT_TYPE_COMPRESSED); - templ->zip_dict_data = field->zip_dict_data; -#else - templ->compressed = 0; - templ->zip_dict_data = null_lex_cstr; -#endif if (!dict_index_is_clust(index) && templ->rec_field_no == ULINT_UNDEFINED) { @@ -8409,10 +8190,8 @@ calc_row_difference( case DATA_BLOB: /* Do not compress blob column while comparing*/ - o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len, - false, 0, 0, prebuilt); - n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len, - false, 0, 0, prebuilt); + o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len); + n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len); break; @@ -8482,17 +8261,7 @@ calc_row_difference( TRUE, new_mysql_row_col, col_pack_len, - dict_table_is_comp(prebuilt->table), -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - field->column_format() == - COLUMN_FORMAT_TYPE_COMPRESSED, - reinterpret_cast( - field->zip_dict_data.str), - field->zip_dict_data.length, -#else - 0, 0, 0, -#endif - prebuilt); + dict_table_is_comp(prebuilt->table)); dfield_copy(&ufield->new_val, &dfield); } else { dfield_set_null(&ufield->new_val); @@ -10179,7 +9948,6 @@ create_table_def( ulint unsigned_type; ulint binary_type; ulint long_true_varchar; - ulint compressed; ulint charset_no; ulint i; ulint doc_id_col = 0; @@ -10329,13 +10097,6 @@ create_table_def( } } - /* Check if the the field has COMPRESSED attribute */ - compressed = 0; - if (field->column_format() == - COLUMN_FORMAT_TYPE_COMPRESSED) { - compressed = DATA_COMPRESSED; - } - /* First check whether the column to be added has a system reserved name. */ if (dict_col_name_is_reserved(field->field_name)){ @@ -10356,8 +10117,7 @@ err_col: dtype_form_prtype( (ulint) field->type() | nulls_allowed | unsigned_type - | binary_type | long_true_varchar - | compressed, + | binary_type | long_true_varchar, charset_no), col_len); } @@ -11187,9 +10947,6 @@ ha_innobase::create( const char* stmt; size_t stmt_len; - mem_heap_t* heap = 0; - ulint* zip_dict_ids = 0; - DBUG_ENTER("ha_innobase::create"); DBUG_ASSERT(thd != NULL); @@ -11280,25 +11037,6 @@ ha_innobase::create( row_mysql_lock_data_dictionary(trx); - heap = mem_heap_create(form->s->fields * sizeof(ulint)); - zip_dict_ids = static_cast( - mem_heap_alloc(heap, form->s->fields * sizeof(ulint))); - - /* This is currently required for valgrind because MariaDB does - not currently support compressed columns. */ - for (size_t field_idx = 0; field_idx < form->s->fields; ++field_idx) { - zip_dict_ids[field_idx] = ULINT_UNDEFINED; - } - - const char* err_zip_dict_name = 0; - if (!innobase_check_zip_dicts(form, zip_dict_ids, - trx, &err_zip_dict_name)) { - error = -1; - my_error(ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST, - MYF(0), err_zip_dict_name); - goto cleanup; - } - error = create_table_def(trx, form, norm_name, temp_path, remote_path, flags, flags2); if (error) { @@ -11406,22 +11144,6 @@ ha_innobase::create( dict_table_get_all_fts_indexes(innobase_table, fts->indexes); } - /* - Adding compression dictionary <-> compressed table column links - to the SYS_ZIP_DICT_COLS table. - */ - ut_a(zip_dict_ids != 0); - { - dict_table_t* local_table = dict_table_open_on_name( - norm_name, TRUE, FALSE, DICT_ERR_IGNORE_NONE); - - ut_a(local_table); - table_id_t table_id = local_table->id; - dict_table_close(local_table, TRUE, FALSE); - innobase_create_zip_dict_references(form, - table_id, zip_dict_ids, trx); - } - stmt = innobase_get_stmt(thd, &stmt_len); if (stmt) { @@ -11538,9 +11260,6 @@ ha_innobase::create( trx_free_for_mysql(trx); - if (heap != 0) - mem_heap_free(heap); - DBUG_RETURN(0); cleanup: @@ -11550,9 +11269,6 @@ cleanup: trx_free_for_mysql(trx); - if (heap != 0) - mem_heap_free(heap); - DBUG_RETURN(error); } @@ -13834,10 +13550,6 @@ ha_innobase::extra( row_mysql_prebuilt_free_blob_heap(prebuilt); } - if (prebuilt->compress_heap) { - row_mysql_prebuilt_free_compress_heap(prebuilt); - } - break; case HA_EXTRA_RESET_STATE: reset_template(); @@ -13889,10 +13601,6 @@ ha_innobase::reset() row_mysql_prebuilt_free_blob_heap(prebuilt); } - if (prebuilt->compress_heap) { - row_mysql_prebuilt_free_compress_heap(prebuilt); - } - reset_template(); ds_mrr.dsmrr_close(); @@ -14092,11 +13800,7 @@ ha_innobase::external_lock( && lock_type == F_WRLCK) || thd_sql_command(thd) == SQLCOM_CREATE_INDEX || thd_sql_command(thd) == SQLCOM_DROP_INDEX - || thd_sql_command(thd) == SQLCOM_DELETE - || thd_sql_command(thd) == - SQLCOM_CREATE_COMPRESSION_DICTIONARY - || thd_sql_command(thd) == - SQLCOM_DROP_COMPRESSION_DICTIONARY)) { + || thd_sql_command(thd) == SQLCOM_DELETE)) { if (thd_sql_command(thd) == SQLCOM_CREATE_TABLE) { @@ -14864,9 +14568,7 @@ ha_innobase::store_lock( && lock_type <= TL_WRITE)) || sql_command == SQLCOM_CREATE_INDEX || sql_command == SQLCOM_DROP_INDEX - || sql_command == SQLCOM_DELETE - || sql_command == SQLCOM_CREATE_COMPRESSION_DICTIONARY - || sql_command == SQLCOM_DROP_COMPRESSION_DICTIONARY)) { + || sql_command == SQLCOM_DELETE)) { ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); @@ -15807,84 +15509,6 @@ ha_innobase::check_if_incompatible_data( return(COMPATIBLE_DATA_YES); } -/** This function reads zip dict-related info from SYS_ZIP_DICT -and SYS_ZIP_DICT_COLS for all columns marked with -COLUMN_FORMAT_TYPE_COMPRESSED flag and updates -zip_dict_name / zip_dict_data for those which have associated -compression dictionaries. -*/ -UNIV_INTERN -void -ha_innobase::update_field_defs_with_zip_dict_info() -{ - DBUG_ENTER("update_field_defs_with_zip_dict_info"); - ut_ad(!mutex_own(&dict_sys->mutex)); - - char norm_name[FN_REFLEN]; - normalize_table_name(norm_name, table_share->normalized_path.str); - - dict_table_t* ib_table = dict_table_open_on_name( - norm_name, FALSE, FALSE, DICT_ERR_IGNORE_NONE); - - /* if dict_table_open_on_name() returns NULL, then it means that - TABLE_SHARE is populated for a table being created and we can - skip filling zip dict info here */ - if (ib_table == 0) - DBUG_VOID_RETURN; - -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - table_id_t ib_table_id = ib_table->id; - dict_table_close(ib_table, FALSE, FALSE); - Field* field; - for (uint i = 0; i < table_share->fields; ++i) { - field = table_share->field[i]; - if (field->column_format() == - COLUMN_FORMAT_TYPE_COMPRESSED) { - bool reference_found = false; - ulint dict_id = 0; - switch (dict_get_dictionary_id_by_key(ib_table_id, i, - &dict_id)) { - case DB_SUCCESS: - reference_found = true; - break; - case DB_RECORD_NOT_FOUND: - reference_found = false; - break; - default: - ut_error; - } - if (reference_found) { - char* local_name = 0; - ulint local_name_len = 0; - char* local_data = 0; - ulint local_data_len = 0; - if (dict_get_dictionary_info_by_id(dict_id, - &local_name, &local_name_len, - &local_data, &local_data_len) != - DB_SUCCESS) { - ut_error; - } - else { - field->zip_dict_name.str = - local_name; - field->zip_dict_name.length = - local_name_len; - field->zip_dict_data.str = - local_data; - field->zip_dict_data.length = - local_data_len; - } - } - else { - field->zip_dict_name = null_lex_cstr; - field->zip_dict_data = null_lex_cstr; - } - } - } -#endif - DBUG_VOID_RETURN; -} - /****************************************************************//** Update the system variable innodb_io_capacity_max using the "saved" value. This function is registered as a callback with MySQL. */ @@ -19276,21 +18900,6 @@ static MYSQL_SYSVAR_BOOL(use_stacktrace, srv_use_stacktrace, "Print stacktrace on long semaphore wait (off by default supported only on linux)", NULL, NULL, FALSE); -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS -static MYSQL_SYSVAR_UINT(compressed_columns_zip_level, - srv_compressed_columns_zip_level, - PLUGIN_VAR_RQCMDARG, - "Compression level used for compressed columns. 0 is no compression" - ", 1 is fastest and 9 is best compression. Default is 6.", - NULL, NULL, DEFAULT_COMPRESSION_LEVEL, 0, 9, 0); - -static MYSQL_SYSVAR_ULONG(compressed_columns_threshold, - srv_compressed_columns_threshold, - PLUGIN_VAR_RQCMDARG, - "Compress column data if its length exceeds this value. Default is 96", - NULL, NULL, 96, 1, ~0UL, 0); -#endif - static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(log_block_size), MYSQL_SYSVAR(additional_mem_pool_size), @@ -19494,10 +19103,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(tmpdir), MYSQL_SYSVAR(use_stacktrace), MYSQL_SYSVAR(simulate_comp_failures), -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - MYSQL_SYSVAR(compressed_columns_zip_level), - MYSQL_SYSVAR(compressed_columns_threshold), -#endif NULL }; @@ -19520,10 +19125,6 @@ maria_declare_plugin(xtradb) i_s_xtradb_read_view, i_s_xtradb_internal_hash_tables, i_s_xtradb_rseg, -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS -i_s_xtradb_zip_dict, -i_s_xtradb_zip_dict_cols, -#endif i_s_innodb_trx, i_s_innodb_locks, i_s_innodb_lock_waits, diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index f01faaf41d8..f4c73fda89d 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 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 @@ -290,14 +290,6 @@ class ha_innobase: public handler bool check_if_supported_virtual_columns(void) { return TRUE; } - /** This function reads zip dict-related info from SYS_ZIP_DICT - and SYS_ZIP_DICT_COLS for all columns marked with - COLUMN_FORMAT_TYPE_COMPRESSED flag and updates - zip_dict_name / zip_dict_data for those which have associated - compression dictionaries. - */ - virtual void update_field_defs_with_zip_dict_info(); - private: /** Builds a 'template' to the prebuilt struct. @@ -691,31 +683,3 @@ ib_push_frm_error( TABLE* table, /*!< in: MySQL table */ ulint n_keys, /*!< in: InnoDB #keys */ bool push_warning); /*!< in: print warning ? */ - -/** This function checks if all the compression dictionaries referenced -in table->fields exist in SYS_ZIP_DICT InnoDB system table. -@return true if all referenced dictionaries exist */ -UNIV_INTERN -bool -innobase_check_zip_dicts( - const TABLE* table, /*!< in: table in MySQL data - dictionary */ - ulint* dict_ids, /*!< out: identified zip dict ids - (at least n_fields long) */ - trx_t* trx, /*!< in: transaction */ - const char** err_dict_name); /*!< out: the name of the - zip_dict which does not exist. */ - -/** This function creates compression dictionary references in -SYS_ZIP_DICT_COLS InnoDB system table for table_id based on info -in table->fields and provided zip dict ids. */ -UNIV_INTERN -void -innobase_create_zip_dict_references( - const TABLE* table, /*!< in: table in MySQL data - dictionary */ - table_id_t ib_table_id, /*!< in: table ID in Innodb data - dictionary */ - ulint* zip_dict_ids, /*!< in: zip dict ids - (at least n_fields long) */ - trx_t* trx); /*!< in: transaction */ diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 362ac9c1b89..c5ac48dc4e3 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -21,11 +22,6 @@ this program; if not, write to the Free Software Foundation, Inc., Smart ALTER TABLE *******************************************************/ -#ifndef HAVE_PERCONA_COMPRESSED_COLUMNS -#define COLUMN_FORMAT_TYPE_COMPRESSED 0xBADF00D -#define ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST 0xDEADFACE -#endif - #include #include #include @@ -1185,15 +1181,6 @@ innobase_col_to_mysql( field->reset(); if (field->type() == MYSQL_TYPE_VARCHAR) { - if (field->column_format() == - COLUMN_FORMAT_TYPE_COMPRESSED) { - /* Skip compressed varchar column when - reporting an erroneous row - during index creation or table rebuild. */ - field->set_null(); - break; - } - /* This is a >= 5.0.3 type true VARCHAR. Store the length of the data to the first byte or the first two bytes of dest. */ @@ -2492,14 +2479,7 @@ innobase_build_col_map_add( byte* buf = static_cast(mem_heap_alloc(heap, size)); row_mysql_store_col_in_innobase_format( - dfield, buf, TRUE, field->ptr, size, comp, -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - field->column_format() == COLUMN_FORMAT_TYPE_COMPRESSED, - reinterpret_cast(field->zip_dict_data.str), - field->zip_dict_data.length, prebuilt); -#else - 0,0,0, prebuilt); -#endif + dfield, buf, TRUE, field->ptr, size, comp); } /** Construct the translation table for reordering, dropping or @@ -2753,7 +2733,6 @@ prepare_inplace_alter_table_dict( ulint num_fts_index; ha_innobase_inplace_ctx*ctx; uint sql_idx; - ulint* zip_dict_ids = 0; DBUG_ENTER("prepare_inplace_alter_table_dict"); @@ -2890,26 +2869,6 @@ prepare_inplace_alter_table_dict( ulint n_cols; dtuple_t* add_cols; - zip_dict_ids = static_cast( - mem_heap_alloc(ctx->heap, - altered_table->s->fields * sizeof(ulint))); - - /* This is currently required for valgrind because MariaDB does - not currently support compressed columns. */ - for (size_t field_idx = 0; - field_idx < altered_table->s->fields; - ++field_idx) { - zip_dict_ids[field_idx] = ULINT_UNDEFINED; - } - - const char* err_zip_dict_name = 0; - if (!innobase_check_zip_dicts(altered_table, zip_dict_ids, - ctx->trx, &err_zip_dict_name)) { - my_error(ER_COMPRESSION_DICTIONARY_DOES_NOT_EXIST, - MYF(0), err_zip_dict_name); - goto new_clustered_failed; - } - if (innobase_check_foreigns( ha_alter_info, altered_table, old_table, user_table, ctx->drop_fk, ctx->num_to_drop_fk)) { @@ -3016,12 +2975,6 @@ prepare_inplace_alter_table_dict( } } - if (field->column_format() == - COLUMN_FORMAT_TYPE_COMPRESSED) { - field_type |= DATA_COMPRESSED; - } - - if (dict_col_name_is_reserved(field->field_name)) { dict_mem_table_free(ctx->new_table); my_error(ER_WRONG_COLUMN_NAME, MYF(0), @@ -3279,17 +3232,6 @@ op_ok: DBUG_ASSERT(error == DB_SUCCESS); -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - /* - Adding compression dictionary <-> compressed table column links - to the SYS_ZIP_DICT_COLS table. - */ - if (zip_dict_ids != 0) { - innobase_create_zip_dict_references(altered_table, - ctx->trx->table_id, zip_dict_ids, ctx->trx); - } -#endif - /* Commit the data dictionary transaction in order to release the table locks on the system tables. This means that if MySQL crashes while creating a new primary key inside diff --git a/storage/xtradb/handler/xtradb_i_s.cc b/storage/xtradb/handler/xtradb_i_s.cc index eb6637dad03..84c1e5852bc 100644 --- a/storage/xtradb/handler/xtradb_i_s.cc +++ b/storage/xtradb/handler/xtradb_i_s.cc @@ -2,6 +2,7 @@ Copyright (c) 2007, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2010-2012, Percona Inc. All Rights Reserved. +Copyright (c) 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 @@ -36,7 +37,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include /* btr_search_sys */ #include /* recv_sys */ #include -#include /* for ZIP_DICT_MAX_* constants */ /* for XTRADB_RSEG table */ #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */ @@ -629,331 +629,3 @@ UNIV_INTERN struct st_mysql_plugin i_s_xtradb_rseg = STRUCT_FLD(version_info, INNODB_VERSION_STR), STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; - - -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS -/************************************************************************/ -enum zip_dict_field_type -{ - zip_dict_field_id, - zip_dict_field_name, - zip_dict_field_zip_dict -}; - -static ST_FIELD_INFO xtradb_sys_zip_dict_fields_info[] = -{ - { STRUCT_FLD(field_name, "id"), - STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, - - { STRUCT_FLD(field_name, "name"), - STRUCT_FLD(field_length, ZIP_DICT_MAX_NAME_LENGTH), - STRUCT_FLD(field_type, MYSQL_TYPE_STRING), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, 0), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, - - { STRUCT_FLD(field_name, "zip_dict"), - STRUCT_FLD(field_length, ZIP_DICT_MAX_DATA_LENGTH), - STRUCT_FLD(field_type, MYSQL_TYPE_BLOB), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, 0), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, - - END_OF_ST_FIELD_INFO -}; - -/** Function to fill INFORMATION_SCHEMA.XTRADB_ZIP_DICT with information -collected by scanning SYS_ZIP_DICT table. -@return 0 on success */ -static -int -xtradb_i_s_dict_fill_sys_zip_dict( - THD* thd, /*!< in: thread */ - ulint id, /*!< in: dict ID */ - const char* name, /*!< in: dict name */ - const char* data, /*!< in: dict data */ - ulint data_len, /*!< in: dict data length */ - TABLE* table_to_fill) /*!< in/out: fill this table */ -{ - DBUG_ENTER("xtradb_i_s_dict_fill_sys_zip_dict"); - - Field** fields = table_to_fill->field; - - OK(field_store_ulint(fields[zip_dict_field_id], id)); - OK(field_store_string(fields[zip_dict_field_name], name)); - OK(field_store_blob(fields[zip_dict_field_zip_dict], data, - data_len)); - - OK(schema_table_store_record(thd, table_to_fill)); - - DBUG_RETURN(0); -} - -/** Function to populate INFORMATION_SCHEMA.XTRADB_ZIP_DICT table. -Loop through each record in SYS_ZIP_DICT, and extract the column -information and fill the INFORMATION_SCHEMA.XTRADB_ZIP_DICT table. -@return 0 on success */ -static -int -xtradb_i_s_sys_zip_dict_fill_table( - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ) /*!< in: condition (not used) */ -{ - btr_pcur_t pcur; - const rec_t* rec; - mem_heap_t* heap; - mtr_t mtr; - - DBUG_ENTER("xtradb_i_s_sys_zip_dict_fill_table"); - RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - - /* deny access to user without SUPER_ACL privilege */ - if (check_global_access(thd, SUPER_ACL)) { - DBUG_RETURN(0); - } - - heap = mem_heap_create(1000); - mutex_enter(&dict_sys->mutex); - mtr_start(&mtr); - - rec = dict_startscan_system(&pcur, &mtr, SYS_ZIP_DICT); - ulint zip_size = dict_table_zip_size(pcur.btr_cur.index->table); - - while (rec) { - const char* err_msg; - ulint id; - const char* name; - const char* data; - ulint data_len; - - /* Extract necessary information from a SYS_ZIP_DICT row */ - err_msg = dict_process_sys_zip_dict( - heap, zip_size, rec, &id, &name, &data, &data_len); - - mtr_commit(&mtr); - mutex_exit(&dict_sys->mutex); - - if (!err_msg) { - xtradb_i_s_dict_fill_sys_zip_dict( - thd, id, name, data, data_len, - tables->table); - } else { - push_warning_printf(thd, - Sql_condition::WARN_LEVEL_WARN, - ER_CANT_FIND_SYSTEM_REC, "%s", err_msg); - } - - mem_heap_empty(heap); - - /* Get the next record */ - mutex_enter(&dict_sys->mutex); - mtr_start(&mtr); - rec = dict_getnext_system(&pcur, &mtr); - } - - mtr_commit(&mtr); - mutex_exit(&dict_sys->mutex); - mem_heap_free(heap); - - DBUG_RETURN(0); -} - -static int i_s_xtradb_zip_dict_init(void* p) -{ - DBUG_ENTER("i_s_xtradb_zip_dict_init"); - - ST_SCHEMA_TABLE* schema = static_cast(p); - - schema->fields_info = xtradb_sys_zip_dict_fields_info; - schema->fill_table = xtradb_i_s_sys_zip_dict_fill_table; - - DBUG_RETURN(0); -} - -UNIV_INTERN struct st_mysql_plugin i_s_xtradb_zip_dict = -{ - STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), - STRUCT_FLD(info, &i_s_info), - STRUCT_FLD(name, "XTRADB_ZIP_DICT"), - STRUCT_FLD(author, PLUGIN_AUTHOR), - STRUCT_FLD(descr, "InnoDB compression dictionaries information"), - STRUCT_FLD(license, PLUGIN_LICENSE_GPL), - STRUCT_FLD(init, i_s_xtradb_zip_dict_init), - STRUCT_FLD(deinit, i_s_common_deinit), - STRUCT_FLD(version, INNODB_VERSION_SHORT), - STRUCT_FLD(status_vars, NULL), - STRUCT_FLD(system_vars, NULL), - STRUCT_FLD(__reserved1, NULL), - STRUCT_FLD(flags, 0UL), -}; - -enum zip_dict_cols_field_type -{ - zip_dict_cols_field_table_id, - zip_dict_cols_field_column_pos, - zip_dict_cols_field_dict_id -}; - -static ST_FIELD_INFO xtradb_sys_zip_dict_cols_fields_info[] = -{ - { STRUCT_FLD(field_name, "table_id"), - STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, - - { STRUCT_FLD(field_name, "column_pos"), - STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, - - { STRUCT_FLD(field_name, "dict_id"), - STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE) }, - - END_OF_ST_FIELD_INFO -}; - -/** Function to fill INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS with information -collected by scanning SYS_ZIP_DICT_COLS table. -@return 0 on success */ -static -int -xtradb_i_s_dict_fill_sys_zip_dict_cols( - THD* thd, /*!< in: thread */ - ulint table_id, /*!< in: table ID */ - ulint column_pos, /*!< in: column position */ - ulint dict_id, /*!< in: dict ID */ - TABLE* table_to_fill) /*!< in/out: fill this table */ -{ - DBUG_ENTER("xtradb_i_s_dict_fill_sys_zip_dict_cols"); - - Field** fields = table_to_fill->field; - - OK(field_store_ulint(fields[zip_dict_cols_field_table_id], - table_id)); - OK(field_store_ulint(fields[zip_dict_cols_field_column_pos], - column_pos)); - OK(field_store_ulint(fields[zip_dict_cols_field_dict_id], - dict_id)); - - OK(schema_table_store_record(thd, table_to_fill)); - - DBUG_RETURN(0); -} - -/** Function to populate INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS table. -Loop through each record in SYS_ZIP_DICT_COLS, and extract the column -information and fill the INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS table. -@return 0 on success */ -static -int -xtradb_i_s_sys_zip_dict_cols_fill_table( - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ) /*!< in: condition (not used) */ -{ - btr_pcur_t pcur; - const rec_t* rec; - mem_heap_t* heap; - mtr_t mtr; - - DBUG_ENTER("xtradb_i_s_sys_zip_dict_cols_fill_table"); - RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name); - - /* deny access to user without SUPER_ACL privilege */ - if (check_global_access(thd, SUPER_ACL)) { - DBUG_RETURN(0); - } - - heap = mem_heap_create(1000); - mutex_enter(&dict_sys->mutex); - mtr_start(&mtr); - - rec = dict_startscan_system(&pcur, &mtr, SYS_ZIP_DICT_COLS); - - while (rec) { - const char* err_msg; - ulint table_id; - ulint column_pos; - ulint dict_id; - - /* Extract necessary information from a SYS_ZIP_DICT_COLS - row */ - err_msg = dict_process_sys_zip_dict_cols( - heap, rec, &table_id, &column_pos, &dict_id); - - mtr_commit(&mtr); - mutex_exit(&dict_sys->mutex); - - if (!err_msg) { - xtradb_i_s_dict_fill_sys_zip_dict_cols( - thd, table_id, column_pos, dict_id, - tables->table); - } else { - push_warning_printf(thd, - Sql_condition::WARN_LEVEL_WARN, - ER_CANT_FIND_SYSTEM_REC, "%s", err_msg); - } - - mem_heap_empty(heap); - - /* Get the next record */ - mutex_enter(&dict_sys->mutex); - mtr_start(&mtr); - rec = dict_getnext_system(&pcur, &mtr); - } - - mtr_commit(&mtr); - mutex_exit(&dict_sys->mutex); - mem_heap_free(heap); - - DBUG_RETURN(0); -} - -static int i_s_xtradb_zip_dict_cols_init(void* p) -{ - DBUG_ENTER("i_s_xtradb_zip_dict_cols_init"); - - ST_SCHEMA_TABLE* schema = static_cast(p); - - schema->fields_info = xtradb_sys_zip_dict_cols_fields_info; - schema->fill_table = xtradb_i_s_sys_zip_dict_cols_fill_table; - - DBUG_RETURN(0); -} - -UNIV_INTERN struct st_mysql_plugin i_s_xtradb_zip_dict_cols = -{ - STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), - STRUCT_FLD(info, &i_s_info), - STRUCT_FLD(name, "XTRADB_ZIP_DICT_COLS"), - STRUCT_FLD(author, PLUGIN_AUTHOR), - STRUCT_FLD(descr, "InnoDB compressed columns information"), - STRUCT_FLD(license, PLUGIN_LICENSE_GPL), - STRUCT_FLD(init, i_s_xtradb_zip_dict_cols_init), - STRUCT_FLD(deinit, i_s_common_deinit), - STRUCT_FLD(version, INNODB_VERSION_SHORT), - STRUCT_FLD(status_vars, NULL), - STRUCT_FLD(system_vars, NULL), - STRUCT_FLD(__reserved1, NULL), - STRUCT_FLD(flags, 0UL), -}; -#endif diff --git a/storage/xtradb/handler/xtradb_i_s.h b/storage/xtradb/handler/xtradb_i_s.h index 905d84587af..994bc11c1b8 100644 --- a/storage/xtradb/handler/xtradb_i_s.h +++ b/storage/xtradb/handler/xtradb_i_s.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2010-2012, Percona Inc. All Rights Reserved. +Copyright (c) 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 @@ -22,7 +23,5 @@ this program; if not, write to the Free Software Foundation, Inc., extern struct st_mysql_plugin i_s_xtradb_read_view; extern struct st_mysql_plugin i_s_xtradb_internal_hash_tables; extern struct st_mysql_plugin i_s_xtradb_rseg; -extern struct st_mysql_plugin i_s_xtradb_zip_dict; -extern struct st_mysql_plugin i_s_xtradb_zip_dict_cols; #endif /* XTRADB_I_S_H */ diff --git a/storage/xtradb/include/data0type.h b/storage/xtradb/include/data0type.h index f269c266efb..df6b6a41c11 100644 --- a/storage/xtradb/include/data0type.h +++ b/storage/xtradb/include/data0type.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -170,9 +171,6 @@ be less than 256 */ type when the column is true VARCHAR where MySQL uses 2 bytes to store the data len; for shorter VARCHARs MySQL uses only 1 byte */ -#define DATA_COMPRESSED 16384 /* this is ORed to the precise data - type when the column has COLUMN_FORMAT = - COMPRESSED attribute*/ /*-------------------------------------------*/ /* This many bytes we need to store the type information affecting the @@ -503,17 +501,6 @@ dtype_print( /*========*/ const dtype_t* type); /*!< in: type */ -/** -Calculates the number of extra bytes needed for compression header -depending on precise column type. -@reval 0 if prtype does not include DATA_COMPRESSED flag -@reval ZIP_COLUMN_HEADER_LENGTH if prtype includes DATA_COMPRESSED flag -*/ -UNIV_INLINE -ulint -prtype_get_compression_extra( - ulint prtype); /*!< in: precise type */ - /* Structure for an SQL data type. If you add fields to this structure, be sure to initialize them everywhere. This structure is initialized in the following functions: diff --git a/storage/xtradb/include/data0type.ic b/storage/xtradb/include/data0type.ic index 29dc480a19c..555852474aa 100644 --- a/storage/xtradb/include/data0type.ic +++ b/storage/xtradb/include/data0type.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -710,18 +711,3 @@ dtype_get_sql_null_size( 0, 0)); #endif /* !UNIV_HOTBACKUP */ } - -/** -Calculates the number of extra bytes needed for compression header -depending on precise column type. -@reval 0 if prtype does not include DATA_COMPRESSED flag -@reval ZIP_COLUMN_HEADER_LENGTH if prtype includes DATA_COMPRESSED flag -*/ -UNIV_INLINE -ulint -prtype_get_compression_extra( - ulint prtype) /*!< in: precise type */ -{ - return (prtype & DATA_COMPRESSED) != 0 ? - ZIP_COLUMN_HEADER_LENGTH : 0; -} diff --git a/storage/xtradb/include/dict0boot.h b/storage/xtradb/include/dict0boot.h index d5bee886cbf..4fd9b0b7f98 100644 --- a/storage/xtradb/include/dict0boot.h +++ b/storage/xtradb/include/dict0boot.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -324,38 +325,6 @@ enum dict_fld_sys_datafiles_enum { DICT_FLD__SYS_DATAFILES__PATH = 3, DICT_NUM_FIELDS__SYS_DATAFILES = 4 }; -/* The columns in SYS_DICT */ -enum dict_col_sys_zip_dict_enum { - DICT_COL__SYS_ZIP_DICT__ID = 0, - DICT_COL__SYS_ZIP_DICT__NAME = 1, - DICT_COL__SYS_ZIP_DICT__DATA = 2, - DICT_NUM_COLS__SYS_ZIP_DICT = 3 -}; -/* The field numbers in the SYS_DICT clustered index */ -enum dict_fld_sys_zip_dict_enum { - DICT_FLD__SYS_ZIP_DICT__ID = 0, - DICT_FLD__SYS_ZIP_DICT__DB_TRX_ID = 1, - DICT_FLD__SYS_ZIP_DICT__DB_ROLL_PTR = 2, - DICT_FLD__SYS_ZIP_DICT__NAME = 3, - DICT_FLD__SYS_ZIP_DICT__DATA = 4, - DICT_NUM_FIELDS__SYS_ZIP_DICT = 5 -}; -/* The columns in SYS_DICT_COLS */ -enum dict_col_sys_zip_dict_cols_enum { - DICT_COL__SYS_ZIP_DICT_COLS__TABLE_ID = 0, - DICT_COL__SYS_ZIP_DICT_COLS__COLUMN_POS = 1, - DICT_COL__SYS_ZIP_DICT_COLS__DICT_ID = 2, - DICT_NUM_COLS__SYS_ZIP_DICT_COLS = 3 -}; -/* The field numbers in the SYS_DICT_COLS clustered index */ -enum dict_fld_sys_zip_dict_cols_enum { - DICT_FLD__SYS_ZIP_DICT_COLS__TABLE_ID = 0, - DICT_FLD__SYS_ZIP_DICT_COLS__COLUMN_POS = 1, - DICT_FLD__SYS_ZIP_DICT_COLS__DB_TRX_ID = 2, - DICT_FLD__SYS_ZIP_DICT_COLS__DB_ROLL_PTR = 3, - DICT_FLD__SYS_ZIP_DICT_COLS__DICT_ID = 4, - DICT_NUM_FIELDS__SYS_ZIP_DICT_COLS = 5 -}; /* A number of the columns above occur in multiple tables. These are the length of thos fields. */ diff --git a/storage/xtradb/include/dict0boot.ic b/storage/xtradb/include/dict0boot.ic index 2b156a4f672..42e91ee930e 100644 --- a/storage/xtradb/include/dict0boot.ic +++ b/storage/xtradb/include/dict0boot.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -92,5 +93,3 @@ dict_is_sys_table( { return(id < DICT_HDR_FIRST_ID); } - - diff --git a/storage/xtradb/include/dict0crea.h b/storage/xtradb/include/dict0crea.h index 686f56ad58c..e5977cbabf6 100644 --- a/storage/xtradb/include/dict0crea.h +++ b/storage/xtradb/include/dict0crea.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -164,18 +165,6 @@ dberr_t dict_create_or_check_sys_tablespace(void); /*=====================================*/ -#define ZIP_DICT_MAX_NAME_LENGTH 64 -/* Max window size (2^15) minus 262 */ -#define ZIP_DICT_MAX_DATA_LENGTH 32506 - -/** Creates the zip_dict system table inside InnoDB -at server bootstrap or server start if it is not found or is -not of the right form. -@return DB_SUCCESS or error code */ -UNIV_INTERN -dberr_t -dict_create_or_check_sys_zip_dict(void); - /********************************************************************//** Add a single tablespace definition to the data dictionary tables in the database. @@ -192,83 +181,6 @@ dict_create_add_tablespace_to_dictionary( bool commit); /*!< in: if true then commit the transaction */ -/** Add a single compression dictionary definition to the SYS_ZIP_DICT -InnoDB system table. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_add_zip_dict( - const char* name, /*!< in: dict name */ - ulint name_len, /*!< in: dict name length */ - const char* data, /*!< in: dict data */ - ulint data_len, /*!< in: dict data length */ - trx_t* trx); /*!< in/out: transaction */ - -/** Add a single compression dictionary reference to the SYS_ZIP_DICT_COLS -InnoDB system table. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_add_zip_dict_reference( - ulint table_id, /*!< in: table id */ - ulint column_pos, /*!< in: column position */ - ulint dict_id, /*!< in: dict id */ - trx_t* trx); /*!< in/out: transaction */ - -/** Get a single compression dictionary id for the given -(table id, column pos) pair. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_get_zip_dict_id_by_reference( - ulint table_id, /*!< in: table id */ - ulint column_pos, /*!< in: column position */ - ulint* dict_id, /*!< out: dict id */ - trx_t* trx); /*!< in/out: transaction */ - -/** Get compression dictionary id for the given name. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_get_zip_dict_id_by_name( - const char* dict_name, /*!< in: dict name */ - ulint dict_name_len, /*!< in: dict name length */ - ulint* dict_id, /*!< out: dict id */ - trx_t* trx); /*!< in/out: transaction */ - -/** Get compression dictionary info (name and data) for the given id. -Allocates memory for name and data on success. -Must be freed with mem_free(). -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_get_zip_dict_info_by_id( - ulint dict_id, /*!< in: dict id */ - char** name, /*!< out: dict name */ - ulint* name_len, /*!< out: dict name length */ - char** data, /*!< out: dict data */ - ulint* data_len, /*!< out: dict data length */ - trx_t* trx); /*!< in/out: transaction */ - -/** Remove a single compression dictionary from the data dictionary -tables in the database. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_remove_zip_dict( - const char* name, /*!< in: dict name */ - ulint name_len, /*!< in: dict name length */ - trx_t* trx); /*!< in/out: transaction */ - -/** Remove all compression dictionary references for the given table ID from -the data dictionary tables in the database. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -dict_create_remove_zip_dict_references_for_table( - ulint table_id, /*!< in: table id */ - trx_t* trx); /*!< in/out: transaction */ - /********************************************************************//** Add a foreign key definition to the data dictionary tables. @return error code or DB_SUCCESS */ diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h index 1b6110dd010..a85f6f1eef9 100644 --- a/storage/xtradb/include/dict0dict.h +++ b/storage/xtradb/include/dict0dict.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2015, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -1871,52 +1871,6 @@ dict_table_set_corrupt_by_space( ulint space_id, ibool need_mutex); -/** Insert a records into SYS_ZIP_DICT. -@retval DB_SUCCESS if OK -@retval dberr_t if the insert failed */ -UNIV_INTERN -dberr_t -dict_create_zip_dict( - const char* name, /*!< in: zip_dict name */ - ulint name_len, /*!< in: zip_dict name length*/ - const char* data, /*!< in: zip_dict data */ - ulint data_len); /*!< in: zip_dict data length */ - -/** Get single compression dictionary id for the given -(table id, column pos) pair. -@retval DB_SUCCESS if OK -@retval DB_RECORD_NOT_FOUND if not found */ -UNIV_INTERN -dberr_t -dict_get_dictionary_id_by_key( - ulint table_id, /*!< in: table id */ - ulint column_pos, /*!< in: column position */ - ulint* dict_id); /*!< out: zip_dict id */ - -/** Get compression dictionary info (name and data) for the given id. -Allocates memory in name->str and data->str on success. -Must be freed with mem_free(). -@retval DB_SUCCESS if OK -@retval DB_RECORD_NOT_FOUND if not found */ -UNIV_INTERN -dberr_t -dict_get_dictionary_info_by_id( - ulint dict_id, /*!< in: table name */ - char** name, /*!< out: dictionary name */ - ulint* name_len, /*!< out: dictionary name length*/ - char** data, /*!< out: dictionary data */ - ulint* data_len); /*!< out: dictionary data length*/ - -/** Delete a record in SYS_ZIP_DICT with the given name. -@retval DB_SUCCESS if OK -@retval DB_RECORD_NOT_FOUND if not found -@retval DB_ROW_IS_REFERENCED if in use */ -UNIV_INTERN -dberr_t -dict_drop_zip_dict( - const char* name, /*!< in: zip_dict name */ - ulint name_len); /*!< in: zip_dict name length*/ - #ifndef UNIV_NONINL #include "dict0dict.ic" #endif diff --git a/storage/xtradb/include/dict0load.h b/storage/xtradb/include/dict0load.h index 85e3e565637..1a720de5bb6 100644 --- a/storage/xtradb/include/dict0load.h +++ b/storage/xtradb/include/dict0load.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -44,8 +45,6 @@ enum dict_system_id_t { SYS_FOREIGN_COLS, SYS_TABLESPACES, SYS_DATAFILES, - SYS_ZIP_DICT, - SYS_ZIP_DICT_COLS, /* This must be last item. Defines the number of system tables. */ SYS_NUM_SYSTEM_TABLES @@ -389,32 +388,6 @@ dict_process_sys_datafiles( ulint* space, /*!< out: pace id */ const char** path); /*!< out: datafile path */ -/** This function parses a SYS_ZIP_DICT record, extracts necessary -information from the record and returns to caller. -@return error message, or NULL on success */ -UNIV_INTERN -const char* -dict_process_sys_zip_dict( - mem_heap_t* heap, /*!< in/out: heap memory */ - ulint zip_size, /*!< in: nonzero=compressed BLOB page size */ - const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */ - ulint* id, /*!< out: dict id */ - const char** name, /*!< out: dict name */ - const char** data, /*!< out: dict data */ - ulint* data_len); /*!< out: dict data length */ - -/** This function parses a SYS_ZIP_DICT_COLS record, extracts necessary -information from the record and returns to caller. -@return error message, or NULL on success */ -UNIV_INTERN -const char* -dict_process_sys_zip_dict_cols( - mem_heap_t* heap, /*!< in/out: heap memory */ - const rec_t* rec, /*!< in: current SYS_ZIP_DICT rec */ - ulint* table_id, /*!< out: table id */ - ulint* column_pos, /*!< out: column position */ - ulint* dict_id); /*!< out: dict id */ - /********************************************************************//** Get the filepath for a spaceid from SYS_DATAFILES. This function provides a temporary heap which is used for the table lookup, but not for the path. diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index 70da84640e5..e1148517d99 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -41,9 +42,6 @@ struct SysIndexCallback; extern ibool row_rollback_on_timeout; -extern uint srv_compressed_columns_zip_level; -extern ulong srv_compressed_columns_threshold; - struct row_prebuilt_t; /*******************************************************************//** @@ -55,48 +53,6 @@ row_mysql_prebuilt_free_blob_heap( row_prebuilt_t* prebuilt); /*!< in: prebuilt struct of a ha_innobase:: table handle */ -/** Frees the compress heap in prebuilt when no longer needed. */ -UNIV_INTERN -void -row_mysql_prebuilt_free_compress_heap( - row_prebuilt_t* prebuilt); /*!< in: prebuilt struct of a - ha_innobase:: table handle */ - -/** Uncompress blob/text/varchar column using zlib -@return pointer to the uncompressed data */ -const byte* -row_decompress_column( - const byte* data, /*!< in: data in innodb(compressed) format */ - ulint *len, /*!< in: data length; out: length of - decompressed data*/ - const byte* dict_data, - /*!< in: optional dictionary data used for - decompression */ - ulint dict_data_len, - /*!< in: optional dictionary data length */ - row_prebuilt_t* prebuilt); - /*!< in: use prebuilt->compress_heap only - here*/ - -/** Compress blob/text/varchar column using zlib -@return pointer to the compressed data */ -byte* -row_compress_column( - const byte* data, /*!< in: data in mysql(uncompressed) - format */ - ulint *len, /*!< in: data length; out: length of - compressed data*/ - ulint lenlen, /*!< in: bytes used to store the length of - data */ - const byte* dict_data, - /*!< in: optional dictionary data used for - compression */ - ulint dict_data_len, - /*!< in: optional dictionary data length */ - row_prebuilt_t* prebuilt); - /*!< in: use prebuilt->compress_heap only - here*/ - /*******************************************************************//** Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row format. @@ -135,21 +91,10 @@ row_mysql_store_blob_ref( to 4 bytes */ const void* data, /*!< in: BLOB data; if the value to store is SQL NULL this should be NULL pointer */ - ulint len, /*!< in: BLOB length; if the value to store + ulint len); /*!< in: BLOB length; if the value to store is SQL NULL this should be 0; remember also to set the NULL bit in the MySQL record header! */ - bool need_decompression, - /*!< in: if the data need to be compressed*/ - const byte* dict_data, - /*!< in: optional compression dictionary - data */ - ulint dict_data_len, - /*!< in: optional compression dictionary data - length */ - row_prebuilt_t* prebuilt); - /*compress_heap only - here */ /*******************************************************************//** Reads a reference to a BLOB in the MySQL format. @return pointer to BLOB data */ @@ -160,17 +105,8 @@ row_mysql_read_blob_ref( ulint* len, /*!< out: BLOB length */ const byte* ref, /*!< in: BLOB reference in the MySQL format */ - ulint col_len, /*!< in: BLOB reference length + ulint col_len); /*!< in: BLOB reference length (not BLOB length) */ - bool need_compression, - /*!< in: if the data need to be - compressed*/ - const byte* dict_data, /*!< in: optional compression - dictionary data */ - ulint dict_data_len, /*!< in: optional compression - dictionary data length */ - row_prebuilt_t* prebuilt); /*!< in: use prebuilt->compress_heap - only here */ /**************************************************************//** Pad a column with spaces. */ UNIV_INTERN @@ -218,16 +154,7 @@ row_mysql_store_col_in_innobase_format( necessarily the length of the actual payload data; if the column is a true VARCHAR then this is irrelevant */ - ulint comp, /*!< in: nonzero=compact format */ - bool need_compression, - /*!< in: if the data need to be - compressed */ - const byte* dict_data, /*!< in: optional compression - dictionary data */ - ulint dict_data_len, /*!< in: optional compression - dictionary data length */ - row_prebuilt_t* prebuilt); /*!< in: use prebuilt->compress_heap - only here */ + ulint comp); /*!< in: nonzero=compact format */ /****************************************************************//** Handles user errors and lock waits detected by the database engine. @return true if it was a lock wait and we should continue running the @@ -721,8 +648,6 @@ struct mysql_row_templ_t { ulint is_unsigned; /*!< if a column type is an integer type and this field is != 0, then it is an unsigned integer type */ - bool compressed; /*!< if column format is compressed */ - LEX_CSTRING zip_dict_data; /*!< associated compression dictionary */ }; #define MYSQL_FETCH_CACHE_SIZE 8 @@ -920,8 +845,6 @@ struct row_prebuilt_t { in fetch_cache */ mem_heap_t* blob_heap; /*!< in SELECTS BLOB fields are copied to this heap */ - mem_heap_t* compress_heap; /*!< memory heap used to compress - /decompress blob column*/ mem_heap_t* old_vers_heap; /*!< memory heap where a previous version is built in consistent read */ bool in_fts_query; /*!< Whether we are in a FTS query */ diff --git a/storage/xtradb/rem/rem0rec.cc b/storage/xtradb/rem/rem0rec.cc index 09cd810cd7b..6db11be18e9 100644 --- a/storage/xtradb/rem/rem0rec.cc +++ b/storage/xtradb/rem/rem0rec.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -320,8 +321,7 @@ rec_init_offsets_comp_ordinary( stored in one byte for 0..127. The length will be encoded in two bytes when it is 128 or more, or when the field is stored externally. */ - if (UNIV_UNLIKELY(col->len > 255 - - prtype_get_compression_extra(col->prtype)) + if (UNIV_UNLIKELY(col->len > 255) || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) { if (len & 0x80) { @@ -846,8 +846,7 @@ rec_get_converted_size_comp_prefix_low( ((col->mtype == DATA_VARCHAR || col->mtype == DATA_BINARY || col->mtype == DATA_VARMYSQL) && (col->len == 0 - || len <= col->len + - prtype_get_compression_extra(col->prtype)))); + || len <= col->len))); fixed_len = field->fixed_len; if (temp && fixed_len @@ -879,8 +878,7 @@ rec_get_converted_size_comp_prefix_low( ut_ad(col->len >= 256 || col->mtype == DATA_BLOB); extra_size += 2; } else if (len < 128 - || (col->len < 256 - - prtype_get_compression_extra(col->prtype) + || (col->len < 256 && col->mtype != DATA_BLOB)) { extra_size++; } else { @@ -1276,16 +1274,12 @@ rec_convert_dtuple_to_rec_comp( *lens-- = (byte) (len >> 8) | 0xc0; *lens-- = (byte) len; } else { - ut_ad(len <= dtype_get_len(type) + - prtype_get_compression_extra( - dtype_get_prtype(type)) + ut_ad(len <= dtype_get_len(type) || dtype_get_mtype(type) == DATA_BLOB || !strcmp(index->name, FTS_INDEX_TABLE_IND_NAME)); if (len < 128 - || (dtype_get_len(type) < 256 - - prtype_get_compression_extra( - dtype_get_prtype(type)) + || (dtype_get_len(type) < 256 && dtype_get_mtype(type) != DATA_BLOB)) { *lens-- = (byte) len; diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index e397053949e..c1436f9e1b7 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -529,8 +530,7 @@ row_merge_buf_add( ((col->mtype == DATA_VARCHAR || col->mtype == DATA_BINARY || col->mtype == DATA_VARMYSQL) && (col->len == 0 - || len <= col->len + - prtype_get_compression_extra(col->prtype)))); + || len <= col->len))); fixed_len = ifield->fixed_len; if (fixed_len && !dict_table_is_comp(index->table) @@ -559,8 +559,7 @@ row_merge_buf_add( } else if (dfield_is_ext(field)) { extra_size += 2; } else if (len < 128 - || (col->len < 256 - - prtype_get_compression_extra(col->prtype) + || (col->len < 256 && col->mtype != DATA_BLOB)) { extra_size++; } else { diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 46bf523750c..b366a55b2d9 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -69,48 +70,6 @@ Created 9/17/2000 Heikki Tuuri /** Provide optional 4.x backwards compatibility for 5.0 and above */ UNIV_INTERN ibool row_rollback_on_timeout = FALSE; -/** -Z_NO_COMPRESSION = 0 -Z_BEST_SPEED = 1 -Z_BEST_COMPRESSION = 9 -Z_DEFAULT_COMPRESSION = -1 -Compression level to be used by zlib for compressed-blob columns. -Settable by user. -*/ -UNIV_INTERN uint srv_compressed_columns_zip_level = DEFAULT_COMPRESSION_LEVEL; -/** -(Z_FILTERED | Z_HUFFMAN_ONLY | Z_RLE | Z_FIXED | Z_DEFAULT_STRATEGY) - -The strategy parameter is used to tune the compression algorithm. Use the -value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a -filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only -(no string match), or Z_RLE to limit match distances to one -(run-length encoding). Filtered data consists mostly of small values with a -somewhat random distribution. In this case, the compression algorithm is -tuned to compress them better. -The effect of Z_FILTERED is to force more Huffman coding and less string -matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and -Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, -but give better compression for PNG image data. The strategy parameter only -affects the compression ratio but not the correctness of the compressed -output even if it is not set appropriately. Z_FIXED prevents the use of -dynamic Huffman codes, allowing for a simpler decoder for special -applications. -*/ -const uint srv_compressed_columns_zlib_strategy = Z_DEFAULT_STRATEGY; -/** Compress the column if the data length exceeds this value. */ -UNIV_INTERN ulong srv_compressed_columns_threshold = 96; -/** -Determine if zlib needs to compute adler32 value for the compressed data. -This variables is similar to page_zip_zlib_wrap, but only used by -compressed blob columns. -*/ -const bool srv_compressed_columns_zlib_wrap = true; -/** -Determine if zlib will use custom memory allocation functions based on -InnoDB memory heap routines (mem_heap_t*). -*/ -const bool srv_compressed_columns_zlib_use_heap = false; /** Chain node of the list of tables to drop in the background. */ struct row_mysql_drop_t{ char* table_name; /*!< table name */ @@ -214,17 +173,6 @@ row_mysql_prebuilt_free_blob_heap( prebuilt->blob_heap = NULL; } -/** Frees the compress heap in prebuilt when no longer needed. */ -UNIV_INTERN -void -row_mysql_prebuilt_free_compress_heap( - row_prebuilt_t* prebuilt) /*!< in: prebuilt struct of a - ha_innobase:: table handle */ -{ - mem_heap_free(prebuilt->compress_heap); - prebuilt->compress_heap = NULL; -} - /*******************************************************************//** Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row format. @@ -281,425 +229,6 @@ row_mysql_read_true_varchar( return(field + 1); } -/** - Compressed BLOB header format: - --------------------------------------------------------------- - | reserved | wrap | algorithm | len-len | compressed | unused | - | [1] | [1] | [5] | [3] | [1] | [5] | - --------------------------------------------------------------- - | 0 0 | 1 1 | 2 6 | 7 9 | 10 10 | 11 15 | - --------------------------------------------------------------- - * 'reserved' bit is planned to be used in future versions of the BLOB - header. In this version it must always be - 'default_zip_column_reserved_value' (0). - * 'wrap' identifies if compression algorithm calculated a checksum - (adler32 in case of zlib) and appended it to the compressed data. - * 'algorithm' identifies which algoritm was used to compress this BLOB. - Currently, the only value 'default_zip_column_algorithm_value' (0) is - supported. - * 'len-len' field identifies the length of the column length data portion - followed by this header (see below). - * If 'compressed' bit is set to 1, then this header is immediately followed - by 1..8 bytes (depending on the value of 'len-len' bitfield) which - determine original (uncompressed) block size. These 'len-len' bytes are - followed by compressed representation of the original data. - * If 'compressed' bit is set to 0, every other bitfield ('wrap', - 'algorithm' and 'le-len') must be ignored. In this case the header is - immediately followed by uncompressed (original) data. -*/ - -/** - Currently the only supported value for the 'reserved' field is - false (0). -*/ -static const bool default_zip_column_reserved_value = false; - -/** - Currently the only supported value for the 'algorithm' field is 0, which - means 'zlib'. -*/ -static const uint default_zip_column_algorithm_value = 0; - -static const size_t zip_column_prefix_max_length = - ZIP_COLUMN_HEADER_LENGTH + 8; -static const size_t zip_column_header_length = ZIP_COLUMN_HEADER_LENGTH; - -/* 'reserved', bit 0 */ -static const uint zip_column_reserved = 0; -/* 0000 0000 0000 0001 */ -static const uint zip_column_reserved_mask = 0x0001; - -/* 'wrap', bit 1 */ -static const uint zip_column_wrap = 1; -/* 0000 0000 0000 0010 */ -static const uint zip_column_wrap_mask = 0x0002; - -/* 'algorithm', bit 2,3,4,5,6 */ -static const uint zip_column_algorithm = 2; -/* 0000 0000 0111 1100 */ -static const uint zip_column_algorithm_mask = 0x007C; - -/* 'len-len', bit 7,8,9 */ -static const uint zip_column_data_length = 7; -/* 0000 0011 1000 0000 */ -static const uint zip_column_data_length_mask = 0x0380; - -/* 'compressed', bit 10 */ -static const uint zip_column_compressed = 10; -/* 0000 0100 0000 0000 */ -static const uint zip_column_compressed_mask = 0x0400; - -/** Updates compressed block header with the given components */ -static void -column_set_compress_header( - byte* data, - bool compressed, - ulint lenlen, - uint alg, - bool wrap, - bool reserved) -{ - ulint header = 0; - header |= (compressed << zip_column_compressed); - header |= (lenlen << zip_column_data_length); - header |= (alg << zip_column_algorithm); - header |= (wrap << zip_column_wrap); - header |= (reserved << zip_column_reserved); - mach_write_to_2(data, header); -} - -/** Parse compressed block header into components */ -static void -column_get_compress_header( - const byte* data, - bool* compressed, - ulint* lenlen, - uint* alg, - bool* wrap, - bool* reserved -) -{ - ulint header = mach_read_from_2(data); - *compressed = ((header & zip_column_compressed_mask) >> - zip_column_compressed); - *lenlen = ((header & zip_column_data_length_mask) >> - zip_column_data_length); - *alg = ((header & zip_column_algorithm_mask) >> - zip_column_algorithm); - *wrap = ((header & zip_column_wrap_mask) >> - zip_column_wrap); - *reserved = ((header & zip_column_reserved_mask) >> - zip_column_reserved); -} - -/** Allocate memory for zlib. */ -static -void* -column_zip_zalloc( - void* opaque, /*!< in/out: memory heap */ - uInt items, /*!< in: number of items to allocate */ - uInt size) /*!< in: size of an item in bytes */ -{ - return(mem_heap_zalloc(static_cast(opaque), - items * size)); -} - -/** Deallocate memory for zlib. */ -static -void -column_zip_free( - void* opaque MY_ATTRIBUTE((unused)), /*!< in: memory heap */ - void* address MY_ATTRIBUTE((unused))) /*!< in: object to free */ -{ -} - -/** Configure the zlib allocator to use the given memory heap. */ -UNIV_INTERN -void -column_zip_set_alloc( - void* stream, /*!< in/out: zlib stream */ - mem_heap_t* heap) /*!< in: memory heap to use */ -{ - z_stream* strm = static_cast(stream); - - if (srv_compressed_columns_zlib_use_heap) { - strm->zalloc = column_zip_zalloc; - strm->zfree = column_zip_free; - strm->opaque = heap; - } else { - strm->zalloc = (alloc_func)0; - strm->zfree = (free_func)0; - strm->opaque = (voidpf)0; - } -} - -/** Compress blob/text/varchar column using zlib -@return pointer to the compressed data */ -byte* -row_compress_column( - const byte* data, /*!< in: data in mysql(uncompressed) - format */ - ulint *len, /*!< in: data length; out: length of - compressed data*/ - ulint lenlen, /*!< in: bytes used to store the length of - data */ - const byte* dict_data, - /*!< in: optional dictionary data used for - compression */ - ulint dict_data_len, - /*!< in: optional dictionary data length */ - row_prebuilt_t* prebuilt) - /*!< in: use prebuilt->compress_heap only - here*/ -{ - int err = 0; - ulint comp_len = *len; - ulint buf_len = *len + zip_column_prefix_max_length; - byte* buf; - byte* ptr; - z_stream c_stream; - bool wrap = srv_compressed_columns_zlib_wrap; - - int window_bits = wrap ? MAX_WBITS : -MAX_WBITS; - - if (!prebuilt->compress_heap) { - prebuilt->compress_heap = - mem_heap_create(max(UNIV_PAGE_SIZE, buf_len)); - } - - buf = static_cast(mem_heap_zalloc( - prebuilt->compress_heap,buf_len)); - - if (*len < srv_compressed_columns_threshold || - srv_compressed_columns_zip_level == Z_NO_COMPRESSION) - goto do_not_compress; - - ptr = buf + zip_column_header_length + lenlen; - - /*init deflate object*/ - c_stream.next_in = const_cast(data); - c_stream.avail_in = *len; - c_stream.next_out = ptr; - c_stream.avail_out = comp_len; - - column_zip_set_alloc(&c_stream, prebuilt->compress_heap); - - err = deflateInit2(&c_stream, srv_compressed_columns_zip_level, - Z_DEFLATED, window_bits, MAX_MEM_LEVEL, - srv_compressed_columns_zlib_strategy); - ut_a(err == Z_OK); - - if (dict_data != 0 && dict_data_len != 0) { - err = deflateSetDictionary(&c_stream, dict_data, - dict_data_len); - ut_a(err == Z_OK); - } - - err = deflate(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&c_stream); - if (err == Z_OK) - err = Z_BUF_ERROR; - } else { - comp_len = c_stream.total_out; - err = deflateEnd(&c_stream); - } - - switch (err) { - case Z_OK: - break; - case Z_BUF_ERROR: - /* data after compress is larger than uncompressed data*/ - break; - default: - ib_logf(IB_LOG_LEVEL_ERROR, - "failed to compress the column, error: %d\n", err); - } - - /* make sure the compressed data size is smaller than - uncompressed data */ - if (err == Z_OK && - *len > (comp_len + zip_column_header_length + lenlen)) { - column_set_compress_header(buf, true, lenlen - 1, - default_zip_column_algorithm_value, wrap, - default_zip_column_reserved_value); - ptr = buf + zip_column_header_length; - /*store the uncompressed data length*/ - switch (lenlen) { - case 1: - mach_write_to_1(ptr, *len); - break; - case 2: - mach_write_to_2(ptr, *len); - break; - case 3: - mach_write_to_3(ptr, *len); - break; - case 4: - mach_write_to_4(ptr, *len); - break; - default: - ut_error; - } - - *len = comp_len + zip_column_header_length + lenlen; - return buf; - } - -do_not_compress: - ptr = buf; - column_set_compress_header(ptr, false, 0, - default_zip_column_algorithm_value, false, - default_zip_column_reserved_value); - ptr += zip_column_header_length; - memcpy(ptr, data, *len); - *len += zip_column_header_length; - return buf; -} - -/** Uncompress blob/text/varchar column using zlib -@return pointer to the uncompressed data */ -const byte* -row_decompress_column( - const byte* data, /*!< in: data in innodb(compressed) format */ - ulint *len, /*!< in: data length; out: length of - decompressed data*/ - const byte* dict_data, - /*!< in: optional dictionary data used for - decompression */ - ulint dict_data_len, - /*!< in: optional dictionary data length */ - row_prebuilt_t* prebuilt) - /*!< in: use prebuilt->compress_heap only - here*/ -{ - ulint buf_len = 0; - byte* buf; - int err = 0; - int window_bits = 0; - z_stream d_stream; - bool is_compressed = false; - bool wrap = false; - bool reserved = false; - ulint lenlen = 0; - uint alg = 0; - - ut_ad(*len != ULINT_UNDEFINED); - ut_ad(*len >= zip_column_header_length); - - column_get_compress_header(data, &is_compressed, &lenlen, &alg, - &wrap, &reserved); - - if (reserved != default_zip_column_reserved_value) { - ib_logf(IB_LOG_LEVEL_FATAL, - "unsupported compressed BLOB header format\n"); - } - - if (alg != default_zip_column_algorithm_value) { - ib_logf(IB_LOG_LEVEL_FATAL, - "unsupported 'algorithm' value in the" - " compressed BLOB header\n"); - } - - ut_a(lenlen < 4); - - data += zip_column_header_length; - if (!is_compressed) { /* column not compressed */ - *len -= zip_column_header_length; - return data; - } - - lenlen++; - - ulint comp_len = *len - zip_column_header_length - lenlen; - - ulint uncomp_len = 0; - switch (lenlen) { - case 1: - uncomp_len = mach_read_from_1(data); - break; - case 2: - uncomp_len = mach_read_from_2(data); - break; - case 3: - uncomp_len = mach_read_from_3(data); - break; - case 4: - uncomp_len = mach_read_from_4(data); - break; - default: - ut_error; - } - - data += lenlen; - - /* data is compressed, decompress it*/ - if (!prebuilt->compress_heap) { - prebuilt->compress_heap = - mem_heap_create(max(UNIV_PAGE_SIZE, uncomp_len)); - } - - buf_len = uncomp_len; - buf = static_cast(mem_heap_zalloc( - prebuilt->compress_heap, buf_len)); - - /* init d_stream */ - d_stream.next_in = const_cast(data); - d_stream.avail_in = comp_len; - d_stream.next_out = buf; - d_stream.avail_out = buf_len; - - column_zip_set_alloc(&d_stream, prebuilt->compress_heap); - - window_bits = wrap ? MAX_WBITS : -MAX_WBITS; - err = inflateInit2(&d_stream, window_bits); - ut_a(err == Z_OK); - - err = inflate(&d_stream, Z_FINISH); - if (err == Z_NEED_DICT) { - ut_a(dict_data != 0 && dict_data_len != 0); - err = inflateSetDictionary(&d_stream, dict_data, - dict_data_len); - ut_a(err == Z_OK); - err = inflate(&d_stream, Z_FINISH); - } - - if (err != Z_STREAM_END) { - inflateEnd(&d_stream); - if (err == Z_BUF_ERROR && d_stream.avail_in == 0) - err = Z_DATA_ERROR; - } else { - buf_len = d_stream.total_out; - err = inflateEnd(&d_stream); - } - - switch (err) { - case Z_OK: - break; - case Z_BUF_ERROR: - ib_logf(IB_LOG_LEVEL_FATAL, - "zlib buf error, this shouldn't happen\n"); - break; - default: - ib_logf(IB_LOG_LEVEL_FATAL, - "failed to decompress column, error: %d\n", err); - } - - if (err == Z_OK) { - if (buf_len != uncomp_len) { - ib_logf(IB_LOG_LEVEL_FATAL, - "failed to decompress blob column, may" - " be corrupted\n"); - } - *len = buf_len; - return buf; - } - - *len -= (zip_column_header_length + lenlen); - return data; -} - - /*******************************************************************//** Stores a reference to a BLOB in the MySQL format. */ UNIV_INTERN @@ -713,21 +242,10 @@ row_mysql_store_blob_ref( to 4 bytes */ const void* data, /*!< in: BLOB data; if the value to store is SQL NULL this should be NULL pointer */ - ulint len, /*!< in: BLOB length; if the value to store + ulint len) /*!< in: BLOB length; if the value to store is SQL NULL this should be 0; remember also to set the NULL bit in the MySQL record header! */ - bool need_decompression, - /*!< in: if the data need to be compressed*/ - const byte* dict_data, - /*!< in: optional compression dictionary - data */ - ulint dict_data_len, - /*!< in: optional compression dictionary data - length */ - row_prebuilt_t* prebuilt) - /*compress_heap only - here */ { /* MySQL might assume the field is set to zero except the length and the pointer fields */ @@ -739,27 +257,11 @@ row_mysql_store_blob_ref( In 32-bit architectures we only use the first 4 bytes of the pointer slot. */ - ut_a(col_len - 8 > 1 || - len < 256 + - (need_decompression ? ZIP_COLUMN_HEADER_LENGTH : 0)); - ut_a(col_len - 8 > 2 || - len < 256 * 256 + - (need_decompression ? ZIP_COLUMN_HEADER_LENGTH : 0)); - ut_a(col_len - 8 > 3 || - len < 256 * 256 * 256 + - (need_decompression ? ZIP_COLUMN_HEADER_LENGTH : 0)); - - const byte *ptr = NULL; - - if (need_decompression) - ptr = row_decompress_column((const byte*)data, &len, - dict_data, dict_data_len, prebuilt); - - if (ptr) - memcpy(dest + col_len - 8, &ptr, sizeof ptr); - else - memcpy(dest + col_len - 8, &data, sizeof data); + ut_a(col_len - 8 > 1 || len < 256); + ut_a(col_len - 8 > 2 || len < 256 * 256); + ut_a(col_len - 8 > 3 || len < 256 * 256 * 256); + memcpy(dest + col_len - 8, &data, sizeof data); mach_write_to_n_little_endian(dest, col_len - 8, len); } @@ -773,32 +275,15 @@ row_mysql_read_blob_ref( ulint* len, /*!< out: BLOB length */ const byte* ref, /*!< in: BLOB reference in the MySQL format */ - ulint col_len, /*!< in: BLOB reference length + ulint col_len) /*!< in: BLOB reference length (not BLOB length) */ - bool need_compression, - /*!< in: if the data need to be - compressed*/ - const byte* dict_data, /*!< in: optional compression - dictionary data */ - ulint dict_data_len, /*!< in: optional compression - dictionary data length */ - row_prebuilt_t* prebuilt) /*!< in: use prebuilt->compress_heap - only here */ { byte* data = NULL; - byte* ptr = NULL; *len = mach_read_from_n_little_endian(ref, col_len - 8); memcpy(&data, ref + col_len - 8, sizeof data); - if (need_compression) { - ptr = row_compress_column(data, len, col_len - 8, dict_data, - dict_data_len, prebuilt); - if (ptr) - data = ptr; - } - return(data); } @@ -881,16 +366,7 @@ row_mysql_store_col_in_innobase_format( necessarily the length of the actual payload data; if the column is a true VARCHAR then this is irrelevant */ - ulint comp, /*!< in: nonzero=compact format */ - bool need_compression, - /*!< in: if the data need to be - compressed*/ - const byte* dict_data, /*!< in: optional compression - dictionary data */ - ulint dict_data_len, /*!< in: optional compression - dictionary data length */ - row_prebuilt_t* prebuilt) /*!< in: use prebuilt->compress_heap - only here */ + ulint comp) /*!< in: nonzero=compact format */ { const byte* ptr = mysql_data; const dtype_t* dtype; @@ -943,14 +419,8 @@ row_mysql_store_col_in_innobase_format( lenlen = 2; } - const byte* tmp_ptr = row_mysql_read_true_varchar( + ptr = row_mysql_read_true_varchar( &col_len, mysql_data, lenlen); - if (need_compression) - ptr = row_compress_column(tmp_ptr, &col_len, - lenlen, dict_data, dict_data_len, - prebuilt); - else - ptr = tmp_ptr; } else { /* Remove trailing spaces from old style VARCHAR columns. */ @@ -1032,9 +502,7 @@ row_mysql_store_col_in_innobase_format( } } else if (type == DATA_BLOB && row_format_col) { - ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len, - need_compression, dict_data, dict_data_len, - prebuilt); + ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len); } dfield_set_data(dfield, ptr, col_len); @@ -1092,11 +560,7 @@ row_mysql_convert_row_to_innobase( TRUE, /* MySQL row format data */ mysql_rec + templ->mysql_col_offset, templ->mysql_col_len, - dict_table_is_comp(prebuilt->table), - templ->compressed, - reinterpret_cast( - templ->zip_dict_data.str), - templ->zip_dict_data.length, prebuilt); + dict_table_is_comp(prebuilt->table)); next_column: ; } @@ -1442,10 +906,6 @@ row_prebuilt_free( mem_heap_free(prebuilt->blob_heap); } - if (prebuilt->compress_heap) { - mem_heap_free(prebuilt->compress_heap); - } - if (prebuilt->old_vers_heap) { mem_heap_free(prebuilt->old_vers_heap); } @@ -1875,9 +1335,6 @@ row_insert_for_mysql( return(DB_READ_ONLY); } - if (UNIV_LIKELY_NULL(prebuilt->compress_heap)) - mem_heap_empty(prebuilt->compress_heap); - trx->op_info = "inserting"; row_mysql_delay_if_needed(); @@ -3443,8 +2900,6 @@ row_mysql_table_id_reassign( " WHERE TABLE_ID = :old_id;\n" "UPDATE SYS_INDEXES SET TABLE_ID = :new_id\n" " WHERE TABLE_ID = :old_id;\n" - "UPDATE SYS_ZIP_DICT_COLS SET TABLE_ID = :new_id_narrow\n" - " WHERE TABLE_ID = :old_id_narrow;\n" "END;\n", FALSE, trx); return(err); @@ -4228,9 +3683,6 @@ next_rec: "UPDATE SYS_INDEXES" " SET TABLE_ID = :new_id, SPACE = :new_space\n" " WHERE TABLE_ID = :old_id;\n" - "UPDATE SYS_ZIP_DICT_COLS\n" - " SET TABLE_ID = :new_id_narrow\n" - " WHERE TABLE_ID = :old_id_narrow;\n" "END;\n" , FALSE, trx); @@ -4858,19 +4310,6 @@ row_drop_table_for_mysql( filepath = fil_make_ibd_name(tablename, false); } - /* Remove all compression dictionary references for the - table */ - err = dict_create_remove_zip_dict_references_for_table( - table->id, trx); - if (err != DB_SUCCESS) { - ib_logf(IB_LOG_LEVEL_ERROR, "Error: (%s) not " - "able to remove compression dictionary " - "references for table %s", ut_strerr(err), - tablename); - - goto funct_exit; - } - if (dict_table_has_fts_index(table) || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) { ut_ad(table->n_ref_count == 0); diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index ad1e9e2bf9d..fd23d83e0e5 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -2,6 +2,7 @@ Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -2459,8 +2460,7 @@ row_sel_convert_mysql_key_to_innobase( /* MySQL key value format col */ FALSE, key_ptr + data_offset, data_len, - dict_table_is_comp(index->table), - false, 0, 0 ,0); + dict_table_is_comp(index->table)); ut_a(buf <= original_buf + buf_len); } @@ -2554,15 +2554,15 @@ row_sel_store_row_id_to_prebuilt( #ifdef UNIV_DEBUG /** Convert a non-SQL-NULL field from Innobase format to MySQL format. */ # define row_sel_field_store_in_mysql_format( \ - dest,templ,idx,field,src,len,prebuilt) \ + dest,templ,idx,field,src,len) \ row_sel_field_store_in_mysql_format_func \ - (dest,templ,idx,field,src,len, prebuilt) + (dest,templ,idx,field,src,len) #else /* UNIV_DEBUG */ /** Convert a non-SQL-NULL field from Innobase format to MySQL format. */ # define row_sel_field_store_in_mysql_format( \ - dest,templ,idx,field,src,len,prebuilt) \ + dest,templ,idx,field,src,len) \ row_sel_field_store_in_mysql_format_func \ - (dest,templ,src,len, prebuilt) + (dest,templ,src,len) #endif /* UNIV_DEBUG */ /**************************************************************//** @@ -2592,10 +2592,7 @@ row_sel_field_store_in_mysql_format_func( templ->icp_rec_field_no */ #endif /* UNIV_DEBUG */ const byte* data, /*!< in: data to store */ - ulint len, /*!< in: length of the data */ - row_prebuilt_t* prebuilt) - /*!< in: use prebuilt->compress_heap - only here */ + ulint len) /*!< in: length of the data */ { byte* ptr; #ifdef UNIV_DEBUG @@ -2639,15 +2636,6 @@ row_sel_field_store_in_mysql_format_func( field_end = dest + templ->mysql_col_len; if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { - /* If this is a compressed column, - decompress it first */ - if (templ->compressed) - data = row_decompress_column(data, &len, - reinterpret_cast( - templ->zip_dict_data.str), - templ->zip_dict_data.length, - prebuilt); - /* This is a >= 5.0.3 type true VARCHAR. Store the length of the data to the first byte or the first two bytes of dest. */ @@ -2698,11 +2686,7 @@ row_sel_field_store_in_mysql_format_func( already copied to the buffer in row_sel_store_mysql_rec */ row_mysql_store_blob_ref(dest, templ->mysql_col_len, data, - len, templ->compressed, - reinterpret_cast( - templ->zip_dict_data.str), - templ->zip_dict_data.length, - prebuilt); + len); break; case DATA_MYSQL: @@ -2855,7 +2839,7 @@ row_sel_store_mysql_field_func( row_sel_field_store_in_mysql_format( mysql_rec + templ->mysql_col_offset, - templ, index, field_no, data, len, prebuilt); + templ, index, field_no, data, len); if (heap != prebuilt->blob_heap) { mem_heap_free(heap); @@ -2905,7 +2889,7 @@ row_sel_store_mysql_field_func( row_sel_field_store_in_mysql_format( mysql_rec + templ->mysql_col_offset, - templ, index, field_no, data, len, prebuilt); + templ, index, field_no, data, len); } ut_ad(len != UNIV_SQL_NULL); @@ -2953,9 +2937,6 @@ row_sel_store_mysql_rec( prebuilt->blob_heap = NULL; } - if (UNIV_LIKELY_NULL(prebuilt->compress_heap)) - mem_heap_empty(prebuilt->compress_heap); - for (i = 0; i < prebuilt->n_template; i++) { const mysql_row_templ_t*templ = &prebuilt->mysql_template[i]; const ulint field_no diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index cae3b71c2bb..9f426a8b513 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -3,6 +3,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -2776,12 +2777,6 @@ files_checked: } } - /* Create the SYS_ZIP_DICT system table */ - err = dict_create_or_check_sys_zip_dict(); - if (err != DB_SUCCESS) { - return(err); - } - srv_is_being_started = FALSE; ut_a(trx_purge_state() == PURGE_STATE_INIT); From bc4cac358ed0d08daaa3cb869b3ecc444afa09fa Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 4 Jan 2017 13:26:09 +0100 Subject: [PATCH 017/167] MDEV-10035: DBUG_ASSERT on CREATE VIEW v1 AS SELECT * FROM t1 FOR UPDATE Ability to print lock type added. Restoring correct lock type for CREATE VIEW added. --- mysql-test/r/view.result | 25 +++++++++++++++++++++++++ mysql-test/t/view.test | 22 ++++++++++++++++++++++ sql/sql_lex.cc | 1 + sql/sql_lex.h | 3 +++ sql/sql_select.cc | 6 ++++++ sql/sql_view.cc | 9 +++++++++ sql/sql_yacc.yy | 2 ++ 7 files changed, 68 insertions(+) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 924b3a11fef..6530fd10a6a 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -5799,6 +5799,31 @@ f1 f2 drop table t1, t2; SELECT 1 FROM (SELECT 1 as a) AS b HAVING (SELECT `SOME_GARBAGE`.b.a)=1; ERROR 42S22: Unknown column 'SOME_GARBAGE.b.a' in 'field list' +# +# MDEV-10035: DBUG_ASSERT on CREATE VIEW v1 AS SELECT * FROM t1 +# FOR UPDATE +# +CREATE TABLE t1 (a INT); +insert into t1 values (1),(2); +CREATE VIEW v1 AS SELECT * FROM t1 FOR UPDATE; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` for update latin1 latin1_swedish_ci +select * from v1; +a +1 +2 +DROP VIEW v1; +CREATE VIEW v1 AS SELECT * FROM t1 LOCK IN SHARE MODE; +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a` from `t1` lock in share mode latin1 latin1_swedish_ci +select * from v1; +a +1 +2 +DROP VIEW v1; +DROP TABLE t1; # ----------------------------------------------------------------- # -- End of 10.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 241b3b414f6..5ea97f6465e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -5694,6 +5694,28 @@ drop table t1, t2; --error ER_BAD_FIELD_ERROR SELECT 1 FROM (SELECT 1 as a) AS b HAVING (SELECT `SOME_GARBAGE`.b.a)=1; + +--echo # +--echo # MDEV-10035: DBUG_ASSERT on CREATE VIEW v1 AS SELECT * FROM t1 +--echo # FOR UPDATE +--echo # + +CREATE TABLE t1 (a INT); +insert into t1 values (1),(2); + +CREATE VIEW v1 AS SELECT * FROM t1 FOR UPDATE; +SHOW CREATE VIEW v1; +select * from v1; +DROP VIEW v1; + +CREATE VIEW v1 AS SELECT * FROM t1 LOCK IN SHARE MODE; +SHOW CREATE VIEW v1; +select * from v1; +DROP VIEW v1; + +DROP TABLE t1; + + --echo # ----------------------------------------------------------------- --echo # -- End of 10.0 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9d5f4cfcb5b..d20c5ae78af 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1943,6 +1943,7 @@ void st_select_lex::init_select() m_agg_func_used= false; name_visibility_map= 0; join= 0; + lock_type= TL_READ_DEFAULT; } /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 019231e2004..c4fd109009f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -846,6 +846,9 @@ public: /* namp of nesting SELECT visibility (for aggregate functions check) */ nesting_map name_visibility_map; + /* it is for correct printing SELECT options */ + thr_lock_type lock_type; + void init_query(); void init_select(); st_select_lex_unit* master_unit(); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f345d3c9687..09ceb16fcba 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -24592,6 +24592,12 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) // limit print_limit(thd, str, query_type); + // lock type + if (lock_type == TL_READ_WITH_SHARED_LOCKS) + str->append(" lock in share mode"); + else if (lock_type == TL_WRITE) + str->append(" for update"); + // PROCEDURE unsupported here } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index f3717e3ded2..9fe4dd4849d 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -430,6 +430,15 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, lex->link_first_table_back(view, link_to_local); view->open_type= OT_BASE_ONLY; + /* + ignore lock specs for CREATE statement + */ + if (lex->current_select->lock_type != TL_READ_DEFAULT) + { + lex->current_select->set_lock_for_tables(TL_READ_DEFAULT); + view->mdl_request.set_type(MDL_EXCLUSIVE); + } + if (open_temporary_tables(thd, lex->query_tables) || open_and_lock_tables(thd, lex->query_tables, TRUE, 0)) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c9fd000141a..bf354496433 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8491,12 +8491,14 @@ select_lock_type: | FOR_SYM UPDATE_SYM { LEX *lex=Lex; + lex->current_select->lock_type= TL_WRITE; lex->current_select->set_lock_for_tables(TL_WRITE); lex->safe_to_cache_query=0; } | LOCK_SYM IN_SYM SHARE_SYM MODE_SYM { LEX *lex=Lex; + lex->current_select->lock_type= TL_READ_WITH_SHARED_LOCKS; lex->current_select-> set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS); lex->safe_to_cache_query=0; From 9bf92706d19761722b46d66a671734466cb6e98e Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 1 Jan 2017 19:35:44 +0200 Subject: [PATCH 018/167] MDEV-8518 rpl.sec_behind_master-5114 fails sporadically in buildbot - fix the test to avoid false-negatives before MDEV-5114 patch; - fix the race condition which made the test fail on slow builders --- .../suite/rpl/r/sec_behind_master-5114.result | 3 +- .../suite/rpl/t/sec_behind_master-5114.test | 42 +++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/rpl/r/sec_behind_master-5114.result b/mysql-test/suite/rpl/r/sec_behind_master-5114.result index 5554b17347d..17f50f0b612 100644 --- a/mysql-test/suite/rpl/r/sec_behind_master-5114.result +++ b/mysql-test/suite/rpl/r/sec_behind_master-5114.result @@ -3,7 +3,8 @@ include/master-slave.inc call mtr.add_suppression("Unsafe statement written to the binary log"); CREATE TABLE t1 (a int); INSERT INTO t1 VALUES(SLEEP(2)); -Seconds_Behind_Master: 1 +Seconds_Behind_Master_is_less_than_100 +1 Warnings: Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. drop table t1; diff --git a/mysql-test/suite/rpl/t/sec_behind_master-5114.test b/mysql-test/suite/rpl/t/sec_behind_master-5114.test index 8c70da4f0a8..ff8cab54c4f 100644 --- a/mysql-test/suite/rpl/t/sec_behind_master-5114.test +++ b/mysql-test/suite/rpl/t/sec_behind_master-5114.test @@ -3,24 +3,60 @@ source include/have_binlog_format_statement.inc; call mtr.add_suppression("Unsafe statement written to the binary log"); + +# Make sure that the start time of the first event is certainly different +# from the next event +--let $timestamp= `SELECT @@timestamp` +--disable_query_log +eval SET TIMESTAMP= $timestamp-100; +--enable_query_log CREATE TABLE t1 (a int); + +# Make sure that the slave is done with the first event, and all checks +# that we'll perform later will be really against the second event +sync_slave_with_master; + +connection master; + +# Restore the timestamp now. It doesn't matter that it's not precise, +# it just needs to be very different from the earlier event +--disable_query_log +eval SET TIMESTAMP= $timestamp; +--enable_query_log + send INSERT INTO t1 VALUES(SLEEP(2)); connection slave; -let $run = 10; + +# When the slave starts executing the event, Seconds_Behind_Master +# should start growing steadilly. The bugfix ensures that they are +# calculated based on the start time of the current event, rather +# than the start time of the previous event. To check it, we only need +# the first non-zero value + +let $run = 20; while ($run) { dec $run; let $sbm=query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1); # for debugging uncomment echo and remove the if() - #echo Seconds_Behind_Master: $sbm; +# echo Seconds_Behind_Master: $sbm; if ($sbm) { let $run = 0; } sleep 0.5; } -echo Seconds_Behind_Master: $sbm; + +# Normally the first non-zero value should be 1. However, due to race +# conditions on slow servers, sometimes the check might miss the value 1, +# and only catch a higher one. It does not matter, we just need to make +# sure it didn't start with 100+, as it would have with bug MDEV-5114 + +--disable_query_log +eval SELECT $sbm > 0 and $sbm < 99 AS Seconds_Behind_Master_is_less_than_100; +--enable_query_log + connection master; reap; drop table t1; From 0f8e17af92cd0126aadf283e25edcd64872b2ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 4 Jan 2017 18:16:37 +0200 Subject: [PATCH 019/167] Part 1 of MDEV-8139 Fix scrubbing tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port a bug fix from MySQL 5.7, so that all undo log pages will be freed during a slow shutdown. We cannot scrub pages that are left allocated. commit 173e171c6fb55f064eea278c76fbb28e2b1c757b Author: Thirunarayanan Balathandayuthapani Date: Fri Sep 9 18:01:27 2016 +0530 Bug #24450908 UNDO LOG EXISTS AFTER SLOW SHUTDOWN Problem: ======== 1) cached undo segment is not removed from rollback segment history (RSEG_HISTORY) during slow shutdown. In other words, If the segment is not completely free, we are failing to remove an entry from the history list. While starting the server, we traverse all rollback segment slots history list and make it as list of undo logs to be purged in purge queue. In that case, purge queue will never be empty after slow shutdown. 2) Freeing of undo log segment is linked with removing undo log header from history. Fix: ==== 1) Have separate logic of removing the undo log header from history list from rollback segment slots and remove it from rollback segment history even though it is not completely free. Reviewed-by: Debarun Banerjee Reviewed-by: Marko Mäkelä RB:13672 --- storage/innobase/fut/fut0lst.cc | 98 ------------------------------ storage/innobase/include/fut0lst.h | 25 -------- storage/innobase/trx/trx0purge.cc | 67 ++++++++++---------- storage/xtradb/fut/fut0lst.cc | 98 ------------------------------ storage/xtradb/include/fut0lst.h | 25 -------- storage/xtradb/trx/trx0purge.cc | 67 ++++++++++---------- 6 files changed, 62 insertions(+), 318 deletions(-) diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index 8f96a6426d2..dd3fa1238d9 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -338,104 +338,6 @@ flst_remove( mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr); } -/********************************************************************//** -Cuts off the tail of the list, including the node given. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_cut_end( -/*=========*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node to remove */ - ulint n_nodes,/*!< in: number of nodes to remove, - must be >= 1 */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - ulint space; - flst_node_t* node1; - fil_addr_t node1_addr; - fil_addr_t node2_addr; - ulint len; - - ut_ad(mtr && node2 && base); - ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX)); - ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX)); - ut_ad(n_nodes > 0); - - buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - - node1_addr = flst_get_prev_addr(node2, mtr); - - if (!fil_addr_is_null(node1_addr)) { - - /* Update next field of node1 */ - - if (node1_addr.page == node2_addr.page) { - - node1 = page_align(node2) + node1_addr.boffset; - } else { - node1 = fut_get_ptr(space, - fil_space_get_zip_size(space), - node1_addr, RW_X_LATCH, mtr); - } - - flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr); - } else { - /* node2 was first in list: update the field in base */ - flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr); - } - - flst_write_addr(base + FLST_LAST, node1_addr, mtr); - - /* Update len of base node */ - len = flst_get_len(base, mtr); - ut_ad(len >= n_nodes); - - mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); -} - -/********************************************************************//** -Cuts off the tail of the list, not including the given node. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_truncate_end( -/*==============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node not to remove */ - ulint n_nodes,/*!< in: number of nodes to remove */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - fil_addr_t node2_addr; - ulint len; - ulint space; - - ut_ad(mtr && node2 && base); - ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX)); - ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX)); - if (n_nodes == 0) { - - ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr))); - - return; - } - - buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - - /* Update next field of node2 */ - flst_write_addr(node2 + FLST_NEXT, fil_addr_null, mtr); - - flst_write_addr(base + FLST_LAST, node2_addr, mtr); - - /* Update len of base node */ - len = flst_get_len(base, mtr); - ut_ad(len >= n_nodes); - - mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); -} - /********************************************************************//** Validates a file-based list. @return TRUE if ok */ diff --git a/storage/innobase/include/fut0lst.h b/storage/innobase/include/fut0lst.h index 90f9a65d4fa..8554cc60cdd 100644 --- a/storage/innobase/include/fut0lst.h +++ b/storage/innobase/include/fut0lst.h @@ -102,31 +102,6 @@ flst_remove( flst_node_t* node2, /*!< in: node to remove */ mtr_t* mtr); /*!< in: mini-transaction handle */ /********************************************************************//** -Cuts off the tail of the list, including the node given. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_cut_end( -/*=========*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node to remove */ - ulint n_nodes,/*!< in: number of nodes to remove, - must be >= 1 */ - mtr_t* mtr); /*!< in: mini-transaction handle */ -/********************************************************************//** -Cuts off the tail of the list, not including the given node. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_truncate_end( -/*==============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node not to remove */ - ulint n_nodes,/*!< in: number of nodes to remove */ - mtr_t* mtr); /*!< in: mini-transaction handle */ -/********************************************************************//** Gets list length. @return length */ UNIV_INLINE diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index efc600d16b1..42b94d9b6a3 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -281,18 +281,33 @@ trx_purge_add_update_undo_to_history( } } -/**********************************************************************//** -Frees an undo log segment which is in the history list. Cuts the end of the -history list at the youngest undo log in this segment. */ +/** Remove undo log header from the history list. +@param[in,out] rseg_hdr rollback segment header +@param[in] log_hdr undo log segment header +@param[in,out] mtr mini transaction. */ +static +void +trx_purge_remove_log_hdr( + trx_rsegf_t* rseg_hdr, + trx_ulogf_t* log_hdr, + mtr_t* mtr) +{ + flst_remove(rseg_hdr + TRX_RSEG_HISTORY, + log_hdr + TRX_UNDO_HISTORY_NODE, mtr); + + os_atomic_decrement_ulint(&trx_sys->rseg_history_len, 1); +} + +/** Frees an undo log segment which is in the history list. Removes the +undo log hdr from the history list. +@param[in,out] rseg rollback segment +@param[in] hdr_addr file address of log_hdr +@param[in] noredo skip redo logging. */ static void trx_purge_free_segment( -/*===================*/ - trx_rseg_t* rseg, /*!< in: rollback segment */ - fil_addr_t hdr_addr, /*!< in: the file address of log_hdr */ - ulint n_removed_logs) /*!< in: count of how many undo logs we - will cut off from the end of the - history list */ + trx_rseg_t* rseg, + fil_addr_t hdr_addr) { mtr_t mtr; trx_rsegf_t* rseg_hdr; @@ -356,16 +371,7 @@ trx_purge_free_segment( history list: otherwise, in case of a database crash, the segment could become inaccessible garbage in the file space. */ - flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY, - log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr); - -#ifdef HAVE_ATOMIC_BUILTINS - os_atomic_decrement_ulint(&trx_sys->rseg_history_len, n_removed_logs); -#else - mutex_enter(&trx_sys->mutex); - trx_sys->rseg_history_len -= n_removed_logs; - mutex_exit(&trx_sys->mutex); -#endif /* HAVE_ATOMIC_BUILTINS */ + trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr); do { @@ -407,7 +413,6 @@ trx_purge_truncate_rseg_history( page_t* undo_page; trx_ulogf_t* log_hdr; trx_usegf_t* seg_hdr; - ulint n_removed_logs = 0; mtr_t mtr; trx_id_t undo_trx_no; @@ -445,19 +450,6 @@ loop: hdr_addr.boffset, limit->undo_no); } -#ifdef HAVE_ATOMIC_BUILTINS - os_atomic_decrement_ulint( - &trx_sys->rseg_history_len, n_removed_logs); -#else - mutex_enter(&trx_sys->mutex); - trx_sys->rseg_history_len -= n_removed_logs; - mutex_exit(&trx_sys->mutex); -#endif /* HAVE_ATOMIC_BUILTINS */ - - flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY, - log_hdr + TRX_UNDO_HISTORY_NODE, - n_removed_logs, &mtr); - mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); @@ -466,7 +458,6 @@ loop: prev_hdr_addr = trx_purge_get_log_from_hist( flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, &mtr)); - n_removed_logs++; seg_hdr = undo_page + TRX_UNDO_SEG_HDR; @@ -478,10 +469,14 @@ loop: mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); - trx_purge_free_segment(rseg, hdr_addr, n_removed_logs); + /* calls the trx_purge_remove_log_hdr() + inside trx_purge_free_segment(). */ + trx_purge_free_segment(rseg, hdr_addr); - n_removed_logs = 0; } else { + /* Remove the log hdr from the rseg history. */ + trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); } diff --git a/storage/xtradb/fut/fut0lst.cc b/storage/xtradb/fut/fut0lst.cc index 8f96a6426d2..dd3fa1238d9 100644 --- a/storage/xtradb/fut/fut0lst.cc +++ b/storage/xtradb/fut/fut0lst.cc @@ -338,104 +338,6 @@ flst_remove( mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr); } -/********************************************************************//** -Cuts off the tail of the list, including the node given. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_cut_end( -/*=========*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node to remove */ - ulint n_nodes,/*!< in: number of nodes to remove, - must be >= 1 */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - ulint space; - flst_node_t* node1; - fil_addr_t node1_addr; - fil_addr_t node2_addr; - ulint len; - - ut_ad(mtr && node2 && base); - ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX)); - ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX)); - ut_ad(n_nodes > 0); - - buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - - node1_addr = flst_get_prev_addr(node2, mtr); - - if (!fil_addr_is_null(node1_addr)) { - - /* Update next field of node1 */ - - if (node1_addr.page == node2_addr.page) { - - node1 = page_align(node2) + node1_addr.boffset; - } else { - node1 = fut_get_ptr(space, - fil_space_get_zip_size(space), - node1_addr, RW_X_LATCH, mtr); - } - - flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr); - } else { - /* node2 was first in list: update the field in base */ - flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr); - } - - flst_write_addr(base + FLST_LAST, node1_addr, mtr); - - /* Update len of base node */ - len = flst_get_len(base, mtr); - ut_ad(len >= n_nodes); - - mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); -} - -/********************************************************************//** -Cuts off the tail of the list, not including the given node. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_truncate_end( -/*==============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node not to remove */ - ulint n_nodes,/*!< in: number of nodes to remove */ - mtr_t* mtr) /*!< in: mini-transaction handle */ -{ - fil_addr_t node2_addr; - ulint len; - ulint space; - - ut_ad(mtr && node2 && base); - ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX)); - ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX)); - if (n_nodes == 0) { - - ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr))); - - return; - } - - buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - - /* Update next field of node2 */ - flst_write_addr(node2 + FLST_NEXT, fil_addr_null, mtr); - - flst_write_addr(base + FLST_LAST, node2_addr, mtr); - - /* Update len of base node */ - len = flst_get_len(base, mtr); - ut_ad(len >= n_nodes); - - mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr); -} - /********************************************************************//** Validates a file-based list. @return TRUE if ok */ diff --git a/storage/xtradb/include/fut0lst.h b/storage/xtradb/include/fut0lst.h index 90f9a65d4fa..8554cc60cdd 100644 --- a/storage/xtradb/include/fut0lst.h +++ b/storage/xtradb/include/fut0lst.h @@ -102,31 +102,6 @@ flst_remove( flst_node_t* node2, /*!< in: node to remove */ mtr_t* mtr); /*!< in: mini-transaction handle */ /********************************************************************//** -Cuts off the tail of the list, including the node given. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_cut_end( -/*=========*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node to remove */ - ulint n_nodes,/*!< in: number of nodes to remove, - must be >= 1 */ - mtr_t* mtr); /*!< in: mini-transaction handle */ -/********************************************************************//** -Cuts off the tail of the list, not including the given node. The number of -nodes which will be removed must be provided by the caller, as this function -does not measure the length of the tail. */ -UNIV_INTERN -void -flst_truncate_end( -/*==============*/ - flst_base_node_t* base, /*!< in: pointer to base node of list */ - flst_node_t* node2, /*!< in: first node not to remove */ - ulint n_nodes,/*!< in: number of nodes to remove */ - mtr_t* mtr); /*!< in: mini-transaction handle */ -/********************************************************************//** Gets list length. @return length */ UNIV_INLINE diff --git a/storage/xtradb/trx/trx0purge.cc b/storage/xtradb/trx/trx0purge.cc index d9e40c5d6f5..57338a73450 100644 --- a/storage/xtradb/trx/trx0purge.cc +++ b/storage/xtradb/trx/trx0purge.cc @@ -285,18 +285,33 @@ trx_purge_add_update_undo_to_history( } } -/**********************************************************************//** -Frees an undo log segment which is in the history list. Cuts the end of the -history list at the youngest undo log in this segment. */ +/** Remove undo log header from the history list. +@param[in,out] rseg_hdr rollback segment header +@param[in] log_hdr undo log segment header +@param[in,out] mtr mini transaction. */ +static +void +trx_purge_remove_log_hdr( + trx_rsegf_t* rseg_hdr, + trx_ulogf_t* log_hdr, + mtr_t* mtr) +{ + flst_remove(rseg_hdr + TRX_RSEG_HISTORY, + log_hdr + TRX_UNDO_HISTORY_NODE, mtr); + + os_atomic_decrement_ulint(&trx_sys->rseg_history_len, 1); +} + +/** Frees an undo log segment which is in the history list. Removes the +undo log hdr from the history list. +@param[in,out] rseg rollback segment +@param[in] hdr_addr file address of log_hdr +@param[in] noredo skip redo logging. */ static void trx_purge_free_segment( -/*===================*/ - trx_rseg_t* rseg, /*!< in: rollback segment */ - fil_addr_t hdr_addr, /*!< in: the file address of log_hdr */ - ulint n_removed_logs) /*!< in: count of how many undo logs we - will cut off from the end of the - history list */ + trx_rseg_t* rseg, + fil_addr_t hdr_addr) { mtr_t mtr; trx_rsegf_t* rseg_hdr; @@ -360,16 +375,7 @@ trx_purge_free_segment( history list: otherwise, in case of a database crash, the segment could become inaccessible garbage in the file space. */ - flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY, - log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr); - -#ifdef HAVE_ATOMIC_BUILTINS - os_atomic_decrement_ulint(&trx_sys->rseg_history_len, n_removed_logs); -#else - mutex_enter(&trx_sys->mutex); - trx_sys->rseg_history_len -= n_removed_logs; - mutex_exit(&trx_sys->mutex); -#endif /* HAVE_ATOMIC_BUILTINS */ + trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr); do { @@ -411,7 +417,6 @@ trx_purge_truncate_rseg_history( page_t* undo_page; trx_ulogf_t* log_hdr; trx_usegf_t* seg_hdr; - ulint n_removed_logs = 0; mtr_t mtr; trx_id_t undo_trx_no; @@ -449,19 +454,6 @@ loop: hdr_addr.boffset, limit->undo_no); } -#ifdef HAVE_ATOMIC_BUILTINS - os_atomic_decrement_ulint( - &trx_sys->rseg_history_len, n_removed_logs); -#else - mutex_enter(&trx_sys->mutex); - trx_sys->rseg_history_len -= n_removed_logs; - mutex_exit(&trx_sys->mutex); -#endif /* HAVE_ATOMIC_BUILTINS */ - - flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY, - log_hdr + TRX_UNDO_HISTORY_NODE, - n_removed_logs, &mtr); - mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); @@ -470,7 +462,6 @@ loop: prev_hdr_addr = trx_purge_get_log_from_hist( flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE, &mtr)); - n_removed_logs++; seg_hdr = undo_page + TRX_UNDO_SEG_HDR; @@ -482,10 +473,14 @@ loop: mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); - trx_purge_free_segment(rseg, hdr_addr, n_removed_logs); + /* calls the trx_purge_remove_log_hdr() + inside trx_purge_free_segment(). */ + trx_purge_free_segment(rseg, hdr_addr); - n_removed_logs = 0; } else { + /* Remove the log hdr from the rseg history. */ + trx_purge_remove_log_hdr(rseg_hdr, log_hdr, &mtr); + mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); } From 719321e78e69249e796a907c17400dac14ef0921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 4 Jan 2017 18:43:32 +0200 Subject: [PATCH 020/167] MDEV-11638 Encryption causes race conditions in InnoDB shutdown InnoDB shutdown failed to properly take fil_crypt_thread() into account. The encryption threads were signalled to shut down together with other non-critical tasks. This could be much too early in case of slow shutdown, which could need minutes to complete the purge. Furthermore, InnoDB failed to wait for the fil_crypt_thread() to actually exit before proceeding to the final steps of shutdown, causing the race conditions. Furthermore, the log_scrub_thread() was shut down way too early. Also it should remain until the SRV_SHUTDOWN_FLUSH_PHASE. fil_crypt_threads_end(): Remove. This would cause the threads to be terminated way too early. srv_buf_dump_thread_active, srv_dict_stats_thread_active, lock_sys->timeout_thread_active, log_scrub_thread_active, srv_monitor_active, srv_error_monitor_active: Remove a race condition between startup and shutdown, by setting these in the startup thread that creates threads, not in each created thread. In this way, once the flag is cleared, it will remain cleared during shutdown. srv_n_fil_crypt_threads_started, fil_crypt_threads_event: Declare in global rather than static scope. log_scrub_event, srv_log_scrub_thread_active, log_scrub_thread(): Declare in static rather than global scope. Let these be created by log_init() and freed by log_shutdown(). rotate_thread_t::should_shutdown(): Do not shut down before the SRV_SHUTDOWN_FLUSH_PHASE. srv_any_background_threads_are_active(): Remove. These checks now exist in logs_empty_and_mark_files_at_shutdown(). logs_empty_and_mark_files_at_shutdown(): Shut down the threads in the proper order. Keep fil_crypt_thread() and log_scrub_thread() alive until SRV_SHUTDOWN_FLUSH_PHASE, and check that they actually terminate. --- storage/innobase/buf/buf0dump.cc | 10 +- storage/innobase/dict/dict0stats_bg.cc | 10 +- storage/innobase/fil/fil0crypt.cc | 35 ++-- storage/innobase/handler/ha_innodb.cc | 4 +- storage/innobase/include/fil0crypt.h | 12 +- storage/innobase/include/log0log.h | 14 +- storage/innobase/include/srv0srv.h | 24 +-- storage/innobase/lock/lock0wait.cc | 9 +- storage/innobase/log/log0log.cc | 259 ++++++++++++------------- storage/innobase/srv/srv0srv.cc | 71 +------ storage/innobase/srv/srv0start.cc | 29 +-- storage/xtradb/buf/buf0dump.cc | 10 +- storage/xtradb/dict/dict0stats_bg.cc | 10 +- storage/xtradb/fil/fil0crypt.cc | 35 ++-- storage/xtradb/handler/ha_innodb.cc | 2 - storage/xtradb/include/fil0crypt.h | 12 +- storage/xtradb/include/log0log.h | 14 +- storage/xtradb/include/srv0srv.h | 25 +-- storage/xtradb/lock/lock0wait.cc | 9 +- storage/xtradb/log/log0log.cc | 247 +++++++++++------------ storage/xtradb/srv/srv0srv.cc | 71 +------ storage/xtradb/srv/srv0start.cc | 29 +-- 22 files changed, 351 insertions(+), 590 deletions(-) diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 0abf7118b4f..934e47cea86 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -682,15 +683,10 @@ again. @return this function does not return, it calls os_thread_exit() */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(buf_dump_thread)( -/*============================*/ - void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter - required by os_thread_create */ +DECLARE_THREAD(buf_dump_thread)(void*) { ut_ad(!srv_read_only_mode); - srv_buf_dump_thread_active = TRUE; - buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) not yet started"); buf_load_status(STATUS_INFO, "Loading buffer pool(s) not yet started"); @@ -720,7 +716,7 @@ DECLARE_THREAD(buf_dump_thread)( keep going even if we are in a shutdown state */); } - srv_buf_dump_thread_active = FALSE; + srv_buf_dump_thread_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc index 7aefa6a1d4d..45fa0fc03f0 100644 --- a/storage/innobase/dict/dict0stats_bg.cc +++ b/storage/innobase/dict/dict0stats_bg.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -525,15 +526,10 @@ statistics. @return this function does not return, it calls os_thread_exit() */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(dict_stats_thread)( -/*==============================*/ - void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter - required by os_thread_create */ +DECLARE_THREAD(dict_stats_thread)(void*) { ut_a(!srv_read_only_mode); - srv_dict_stats_thread_active = TRUE; - while (!SHUTTING_DOWN()) { /* Wake up periodically even if not signaled. This is @@ -556,7 +552,7 @@ DECLARE_THREAD(dict_stats_thread)( os_event_reset(dict_stats_event); } - srv_dict_stats_thread_active = FALSE; + srv_dict_stats_thread_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit instead of return(). */ diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 1eaabf68678..2999bea2765 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -56,7 +56,7 @@ UNIV_INTERN ulong srv_encrypt_tables = 0; UNIV_INTERN uint srv_n_fil_crypt_threads = 0; /** No of key rotation threads started */ -static uint srv_n_fil_crypt_threads_started = 0; +UNIV_INTERN uint srv_n_fil_crypt_threads_started = 0; /** At this age or older a space/page will be rotated */ UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1; @@ -65,7 +65,7 @@ UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1; static os_event_t fil_crypt_event; /** Event to signal TO the key rotation threads. */ -static os_event_t fil_crypt_threads_event; +UNIV_INTERN os_event_t fil_crypt_threads_event; /** Event for waking up threads throttle */ static os_event_t fil_crypt_throttle_sleep_event; @@ -1303,10 +1303,20 @@ struct rotate_thread_t { btr_scrub_t scrub_data; /* thread local data used by btr_scrub-functions * when iterating pages of tablespace */ - /* check if this thread should shutdown */ + /** @return whether this thread should terminate */ bool should_shutdown() const { - return ! (srv_shutdown_state == SRV_SHUTDOWN_NONE && - thread_no < srv_n_fil_crypt_threads); + switch (srv_shutdown_state) { + case SRV_SHUTDOWN_NONE: + case SRV_SHUTDOWN_CLEANUP: + return thread_no >= srv_n_fil_crypt_threads; + case SRV_SHUTDOWN_FLUSH_PHASE: + return true; + case SRV_SHUTDOWN_LAST_PHASE: + case SRV_SHUTDOWN_EXIT_THREADS: + break; + } + ut_ad(0); + return true; } }; @@ -2458,18 +2468,6 @@ fil_crypt_threads_init() } } -/********************************************************************* -End threads for key rotation */ -UNIV_INTERN -void -fil_crypt_threads_end() -/*===================*/ -{ - if (fil_crypt_threads_inited) { - fil_crypt_set_thread_cnt(0); - } -} - /********************************************************************* Clean up key rotation threads resources */ UNIV_INTERN @@ -2480,6 +2478,7 @@ fil_crypt_threads_cleanup() if (!fil_crypt_threads_inited) { return; } + ut_a(!srv_n_fil_crypt_threads_started); os_event_free(fil_crypt_event); os_event_free(fil_crypt_threads_event); mutex_free(&fil_crypt_threads_mutex); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b283bbda7f4..625ae5f5d27 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1,10 +1,10 @@ /***************************************************************************** Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -73,7 +73,6 @@ MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[]; #include "srv0srv.h" #include "trx0roll.h" #include "trx0trx.h" - #include "trx0sys.h" #include "rem0types.h" #include "row0ins.h" @@ -248,7 +247,6 @@ static char* internal_innobase_data_file_path = NULL; static char* innodb_version_str = (char*) INNODB_VERSION_STR; -extern uint srv_n_fil_crypt_threads; extern uint srv_fil_crypt_rotate_key_age; extern uint srv_n_fil_crypt_iops; diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index 9a35f6591e7..42cdafde4d0 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (c) 2015, 2016, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -26,6 +26,8 @@ Created 04/01/2015 Jan Lindström #ifndef fil0crypt_h #define fil0crypt_h +#include "os0sync.h" + /** * Magic pattern in start of crypt data on page 0 */ @@ -45,6 +47,8 @@ typedef enum { FIL_SPACE_ENCRYPTION_OFF = 2 /* Tablespace is not encrypted */ } fil_encryption_t; +extern os_event_t fil_crypt_threads_event; + /** * CRYPT_SCHEME_UNENCRYPTED * @@ -391,12 +395,6 @@ fil_crypt_set_thread_cnt( /*=====================*/ uint new_cnt); /*!< in: requested #threads */ -/********************************************************************* -End threads for key rotation */ -UNIV_INTERN -void -fil_crypt_threads_end(); - /********************************************************************* Cleanup resources for threads for key rotation */ UNIV_INTERN diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 0015ea15c35..0f4cb611586 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -2,6 +2,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, Google Inc. +Copyright (c) 2017, MariaDB Corporation Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1013,22 +1014,9 @@ struct log_t{ /* @} */ #endif /* UNIV_LOG_ARCHIVE */ -extern os_event_t log_scrub_event; /* log scrubbing speed, in bytes/sec */ extern ulonglong innodb_scrub_log_speed; -/*****************************************************************//** -This is the main thread for log scrub. It waits for an event and -when waked up fills current log block with dummy records and -sleeps again. -@return this function does not return, it calls os_thread_exit() */ -extern "C" UNIV_INTERN -os_thread_ret_t -DECLARE_THREAD(log_scrub_thread)( -/*===============================*/ - void* arg); /*!< in: a dummy parameter - required by os_thread_create */ - #ifndef UNIV_NONINL #include "log0log.ic" #endif diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 905cc80f0df..1ba1e3ae9c6 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation +Copyright (c) 2013, 2017, MariaDB Corporation Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -328,6 +328,9 @@ extern char** srv_data_file_names; extern ulint* srv_data_file_sizes; extern ulint* srv_data_file_is_raw_partition; +extern uint srv_n_fil_crypt_threads; +extern uint srv_n_fil_crypt_threads_started; + extern ibool srv_auto_extend_last_data_file; extern ulint srv_last_file_size_max; extern char* srv_log_group_home_dir; @@ -478,19 +481,17 @@ extern ibool srv_print_verbose_log; "tables instead, see " REFMAN "innodb-i_s-tables.html" extern ibool srv_print_innodb_table_monitor; -extern ibool srv_monitor_active; -extern ibool srv_error_monitor_active; +extern bool srv_monitor_active; +extern bool srv_error_monitor_active; /* TRUE during the lifetime of the buffer pool dump/load thread */ -extern ibool srv_buf_dump_thread_active; +extern bool srv_buf_dump_thread_active; /* TRUE during the lifetime of the stats thread */ -extern ibool srv_dict_stats_thread_active; +extern bool srv_dict_stats_thread_active; /* TRUE if enable log scrubbing */ extern my_bool srv_scrub_log; -/* TRUE during the lifetime of the log scrub thread */ -extern ibool srv_log_scrub_thread_active; extern ulong srv_n_spin_wait_rounds; extern ulong srv_n_free_tickets_to_enter; @@ -899,15 +900,6 @@ srv_release_threads( enum srv_thread_type type, /*!< in: thread type */ ulint n); /*!< in: number of threads to release */ -/**********************************************************************//** -Check whether any background thread are active. If so print which thread -is active. Send the threads wakeup signal. -@return name of thread that is active or NULL */ -UNIV_INTERN -const char* -srv_any_background_threads_are_active(void); -/*=======================================*/ - /**********************************************************************//** Wakeup the purge threads. */ UNIV_INTERN diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index c7bd223c491..8f9ea7e10aa 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -510,11 +511,7 @@ A thread which wakes up threads whose lock wait may have lasted too long. @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(lock_wait_timeout_thread)( -/*=====================================*/ - void* arg MY_ATTRIBUTE((unused))) - /* in: a dummy parameter required by - os_thread_create */ +DECLARE_THREAD(lock_wait_timeout_thread)(void*) { ib_int64_t sig_count = 0; os_event_t event = lock_sys->timeout_event; @@ -525,8 +522,6 @@ DECLARE_THREAD(lock_wait_timeout_thread)( pfs_register_thread(srv_lock_timeout_thread_key); #endif /* UNIV_PFS_THREAD */ - lock_sys->timeout_thread_active = true; - do { srv_slot_t* slot; diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index a8326571366..3c44baaf1de 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -42,10 +42,11 @@ Created 12/9/1995 Heikki Tuuri #include "buf0buf.h" #include "buf0flu.h" #include "srv0srv.h" +#include "lock0lock.h" #include "log0recv.h" #include "fil0fil.h" #include "dict0boot.h" -#include "srv0srv.h" +#include "dict0stats_bg.h" /* dict_stats_event */ #include "srv0start.h" #include "trx0sys.h" #include "trx0trx.h" @@ -154,6 +155,15 @@ the previous */ #define LOG_ARCHIVE_READ 1 #define LOG_ARCHIVE_WRITE 2 +/** Event to wake up the log scrub thread */ +static os_event_t log_scrub_event; + +static bool log_scrub_thread_active; + +extern "C" UNIV_INTERN +os_thread_ret_t +DECLARE_THREAD(log_scrub_thread)(void*); + /******************************************************//** Completes a checkpoint write i/o to a log file. */ static @@ -943,6 +953,12 @@ log_init(void) mutex_exit(&(log_sys->mutex)); + log_scrub_thread_active = !srv_read_only_mode && srv_scrub_log; + if (log_scrub_thread_active) { + log_scrub_event = os_event_create(); + os_thread_create(log_scrub_thread, NULL, NULL); + } + #ifdef UNIV_LOG_DEBUG recv_sys_create(); recv_sys_init(buf_pool_get_curr_size()); @@ -3232,8 +3248,6 @@ logs_empty_and_mark_files_at_shutdown(void) ulint count = 0; ulint total_trx; ulint pending_io; - enum srv_thread_type active_thd; - const char* thread_name; ibool server_busy; ib_logf(IB_LOG_LEVEL_INFO, "Starting shutdown..."); @@ -3249,29 +3263,17 @@ logs_empty_and_mark_files_at_shutdown(void) srv_shutdown_state = SRV_SHUTDOWN_CLEANUP; loop: + if (!srv_read_only_mode) { + os_event_set(srv_error_event); + os_event_set(srv_monitor_event); + os_event_set(srv_buf_dump_event); + os_event_set(lock_sys->timeout_event); + os_event_set(dict_stats_event); + } os_thread_sleep(100000); count++; - /* We need the monitor threads to stop before we proceed with - a shutdown. */ - - thread_name = srv_any_background_threads_are_active(); - - if (thread_name != NULL) { - /* Print a message every 60 seconds if we are waiting - for the monitor thread to exit. Master and worker - threads check will be done later. */ - - if (srv_print_verbose_log && count > 600) { - ib_logf(IB_LOG_LEVEL_INFO, - "Waiting for %s to exit", thread_name); - count = 0; - } - - goto loop; - } - /* Check that there are no longer transactions, except for PREPARED ones. We need this wait even for the 'very fast' shutdown, because the InnoDB layer may have committed or @@ -3292,55 +3294,61 @@ loop: goto loop; } - /* Check that the background threads are suspended */ + /* We need these threads to stop early in shutdown. */ + const char* thread_name; - active_thd = srv_get_active_thread_type(); + if (srv_error_monitor_active) { + thread_name = "srv_error_monitor_thread"; + } else if (srv_monitor_active) { + thread_name = "srv_monitor_thread"; + } else if (srv_dict_stats_thread_active) { + thread_name = "dict_stats_thread"; + } else if (lock_sys->timeout_thread_active) { + thread_name = "lock_wait_timeout_thread"; + } else if (srv_buf_dump_thread_active) { + thread_name = "buf_dump_thread"; + } else { + thread_name = NULL; + } - if (active_thd != SRV_NONE) { - - if (active_thd == SRV_PURGE) { - srv_purge_wakeup(); - } - - /* The srv_lock_timeout_thread, srv_error_monitor_thread - and srv_monitor_thread should already exit by now. The - only threads to be suspended are the master threads - and worker threads (purge threads). Print the thread - type if any of such threads not in suspended mode */ + if (thread_name) { + ut_ad(!srv_read_only_mode); +wait_suspend_loop: if (srv_print_verbose_log && count > 600) { - const char* thread_type = ""; - - switch (active_thd) { - case SRV_NONE: - /* This shouldn't happen because we've - already checked for this case before - entering the if(). We handle it here - to avoid a compiler warning. */ - ut_error; - case SRV_WORKER: - thread_type = "worker threads"; - break; - case SRV_MASTER: - thread_type = "master thread"; - break; - case SRV_PURGE: - thread_type = "purge thread"; - break; - } - ib_logf(IB_LOG_LEVEL_INFO, - "Waiting for %s to be suspended", - thread_type); + "Waiting for %s to exit", thread_name); count = 0; } - goto loop; } + /* Check that the background threads are suspended */ + + switch (srv_get_active_thread_type()) { + case SRV_NONE: + srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE; + if (!srv_n_fil_crypt_threads_started) { + break; + } + os_event_set(fil_crypt_threads_event); + thread_name = "fil_crypt_thread"; + goto wait_suspend_loop; + case SRV_PURGE: + srv_purge_wakeup(); + thread_name = "purge thread"; + goto wait_suspend_loop; + case SRV_MASTER: + thread_name = "master thread"; + goto wait_suspend_loop; + case SRV_WORKER: + thread_name = "worker threads"; + goto wait_suspend_loop; + } + /* At this point only page_cleaner should be active. We wait here to let it complete the flushing of the buffer pools before proceeding further. */ - srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE; + count = 0; while (buf_page_cleaner_is_active) { ++count; @@ -3353,8 +3361,14 @@ loop: } } + if (log_scrub_thread_active) { + ut_ad(!srv_read_only_mode); + os_event_set(log_scrub_event); + } + mutex_enter(&log_sys->mutex); - server_busy = log_sys->n_pending_checkpoint_writes + server_busy = log_scrub_thread_active + || log_sys->n_pending_checkpoint_writes #ifdef UNIV_LOG_ARCHIVE || log_sys->n_pending_archive_ios #endif /* UNIV_LOG_ARCHIVE */ @@ -3373,6 +3387,8 @@ loop: goto loop; } + ut_ad(!log_scrub_thread_active); + pending_io = buf_pool_check_no_pending_io(); if (pending_io) { @@ -3408,93 +3424,67 @@ loop: from the stamps if the previous shutdown was clean. */ log_buffer_flush_to_disk(); - - /* Check that the background threads stay suspended */ - thread_name = srv_any_background_threads_are_active(); - - if (thread_name != NULL) { - ib_logf(IB_LOG_LEVEL_WARN, - "Background thread %s woke up " - "during shutdown", thread_name); - goto loop; - } } srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; fil_close_all_files(); - - thread_name = srv_any_background_threads_are_active(); - - ut_a(!thread_name); - return; } if (!srv_read_only_mode) { log_make_checkpoint_at(LSN_MAX, TRUE); - } - mutex_enter(&log_sys->mutex); + mutex_enter(&log_sys->mutex); - lsn = log_sys->lsn; + lsn = log_sys->lsn; - if (lsn != log_sys->last_checkpoint_lsn + if (lsn != log_sys->last_checkpoint_lsn #ifdef UNIV_LOG_ARCHIVE - || (srv_log_archive_on - && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE) + || (srv_log_archive_on + && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE) +#endif /* UNIV_LOG_ARCHIVE */ + ) { + + mutex_exit(&log_sys->mutex); + + goto loop; + } + + arch_log_no = 0; + +#ifdef UNIV_LOG_ARCHIVE + UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no; + + if (!UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) { + + arch_log_no--; + } + + log_archive_close_groups(TRUE); #endif /* UNIV_LOG_ARCHIVE */ - ) { mutex_exit(&log_sys->mutex); - goto loop; - } - - arch_log_no = 0; - -#ifdef UNIV_LOG_ARCHIVE - UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no; - - if (0 == UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) { - - arch_log_no--; - } - - log_archive_close_groups(TRUE); -#endif /* UNIV_LOG_ARCHIVE */ - - mutex_exit(&log_sys->mutex); - - /* Check that the background threads stay suspended */ - thread_name = srv_any_background_threads_are_active(); - if (thread_name != NULL) { - ib_logf(IB_LOG_LEVEL_WARN, - "Background thread %s woke up during shutdown", - thread_name); - - goto loop; - } - - if (!srv_read_only_mode) { fil_flush_file_spaces(FIL_TABLESPACE); fil_flush_file_spaces(FIL_LOG); - } - /* The call fil_write_flushed_lsn_to_data_files() will pass the buffer - pool: therefore it is essential that the buffer pool has been - completely flushed to disk! (We do not call fil_write... if the - 'very fast' shutdown is enabled.) */ + /* The call fil_write_flushed_lsn_to_data_files() will + bypass the buffer pool: therefore it is essential that + the buffer pool has been completely flushed to disk! */ - if (!buf_all_freed()) { + if (!buf_all_freed()) { + if (srv_print_verbose_log && count > 600) { + ib_logf(IB_LOG_LEVEL_INFO, + "Waiting for dirty buffer pages" + " to be flushed"); + count = 0; + } - if (srv_print_verbose_log && count > 600) { - ib_logf(IB_LOG_LEVEL_INFO, - "Waiting for dirty buffer pages to be flushed"); - count = 0; + goto loop; } - - goto loop; + } else { + lsn = srv_start_lsn; } srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; @@ -3739,6 +3729,10 @@ log_shutdown(void) mutex_free(&log_sys->mutex); + if (!srv_read_only_mode && srv_scrub_log) { + os_event_free(log_scrub_event); + } + #ifdef UNIV_LOG_ARCHIVE rw_lock_free(&log_sys->archive_lock); os_event_create(); @@ -3766,11 +3760,6 @@ log_mem_free(void) } } -/** Event to wake up the log scrub thread */ -UNIV_INTERN os_event_t log_scrub_event = NULL; - -UNIV_INTERN ibool srv_log_scrub_thread_active = FALSE; - /*****************************************************************//* If no log record has been written for a while, fill current log block with dummy records. */ @@ -3797,17 +3786,11 @@ sleeps again. @return this function does not return, it calls os_thread_exit() */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(log_scrub_thread)( -/*===============================*/ - void* arg __attribute__((unused))) /*!< in: a dummy parameter - required by os_thread_create */ +DECLARE_THREAD(log_scrub_thread)(void*) { ut_ad(!srv_read_only_mode); - srv_log_scrub_thread_active = TRUE; - - while(srv_shutdown_state == SRV_SHUTDOWN_NONE) - { + while (srv_shutdown_state < SRV_SHUTDOWN_FLUSH_PHASE) { /* log scrubbing interval in µs. */ ulonglong interval = 1000*1000*512/innodb_scrub_log_speed; @@ -3818,7 +3801,7 @@ DECLARE_THREAD(log_scrub_thread)( os_event_reset(log_scrub_event); } - srv_log_scrub_thread_active = FALSE; + log_scrub_thread_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 1e323625b13..bf2a0a7fa36 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -60,7 +60,6 @@ Created 10/8/1995 Heikki Tuuri #include "btr0sea.h" #include "dict0load.h" #include "dict0boot.h" -#include "dict0stats_bg.h" /* dict_stats_event */ #include "srv0start.h" #include "row0mysql.h" #include "row0log.h" @@ -89,15 +88,14 @@ UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPH in microseconds, in order to reduce the lagging of the purge thread. */ UNIV_INTERN ulint srv_dml_needed_delay = 0; -UNIV_INTERN ibool srv_monitor_active = FALSE; -UNIV_INTERN ibool srv_error_monitor_active = FALSE; +UNIV_INTERN bool srv_monitor_active; +UNIV_INTERN bool srv_error_monitor_active; -UNIV_INTERN ibool srv_buf_dump_thread_active = FALSE; +UNIV_INTERN bool srv_buf_dump_thread_active; -UNIV_INTERN ibool srv_dict_stats_thread_active = FALSE; +UNIV_INTERN bool srv_dict_stats_thread_active; -UNIV_INTERN ibool srv_log_scrub_active = FALSE; -UNIV_INTERN my_bool srv_scrub_log = FALSE; +UNIV_INTERN my_bool srv_scrub_log; UNIV_INTERN const char* srv_main_thread_op_info = ""; @@ -1687,11 +1685,7 @@ A thread which prints the info output by various InnoDB monitors. @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(srv_monitor_thread)( -/*===============================*/ - void* arg MY_ATTRIBUTE((unused))) - /*!< in: a dummy parameter required by - os_thread_create */ +DECLARE_THREAD(srv_monitor_thread)(void*) { ib_int64_t sig_count; double time_elapsed; @@ -1712,9 +1706,7 @@ DECLARE_THREAD(srv_monitor_thread)( #ifdef UNIV_PFS_THREAD pfs_register_thread(srv_monitor_thread_key); #endif /* UNIV_PFS_THREAD */ - srv_monitor_active = TRUE; - UT_NOT_USED(arg); srv_last_monitor_time = ut_time(); last_table_monitor_time = ut_time(); last_tablespace_monitor_time = ut_time(); @@ -1846,7 +1838,7 @@ loop: goto loop; exit_func: - srv_monitor_active = FALSE; + srv_monitor_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ @@ -1864,11 +1856,7 @@ we should avoid waiting any mutexes in this function! @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(srv_error_monitor_thread)( -/*=====================================*/ - void* arg MY_ATTRIBUTE((unused))) - /*!< in: a dummy parameter required by - os_thread_create */ +DECLARE_THREAD(srv_error_monitor_thread)(void*) { /* number of successive fatal timeouts observed */ ulint fatal_cnt = 0; @@ -1894,7 +1882,6 @@ DECLARE_THREAD(srv_error_monitor_thread)( #ifdef UNIV_PFS_THREAD pfs_register_thread(srv_error_monitor_thread_key); #endif /* UNIV_PFS_THREAD */ - srv_error_monitor_active = TRUE; loop: /* Try to track a strange bug reported by Harald Fuchs and others, @@ -1980,7 +1967,7 @@ loop: goto loop; } - srv_error_monitor_active = FALSE; + srv_error_monitor_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ @@ -2039,44 +2026,6 @@ srv_get_active_thread_type(void) return(ret); } -/**********************************************************************//** -Check whether any background thread are active. If so print which thread -is active. Send the threads wakeup signal. -@return name of thread that is active or NULL */ -UNIV_INTERN -const char* -srv_any_background_threads_are_active(void) -/*=======================================*/ -{ - const char* thread_active = NULL; - - if (srv_read_only_mode) { - return(NULL); - } else if (srv_error_monitor_active) { - thread_active = "srv_error_monitor_thread"; - } else if (lock_sys->timeout_thread_active) { - thread_active = "srv_lock_timeout thread"; - } else if (srv_monitor_active) { - thread_active = "srv_monitor_thread"; - } else if (srv_buf_dump_thread_active) { - thread_active = "buf_dump_thread"; - } else if (srv_dict_stats_thread_active) { - thread_active = "dict_stats_thread"; - } else if (srv_scrub_log && srv_log_scrub_thread_active) { - thread_active = "log_scrub_thread"; - } - - os_event_set(srv_error_event); - os_event_set(srv_monitor_event); - os_event_set(srv_buf_dump_event); - os_event_set(lock_sys->timeout_event); - os_event_set(dict_stats_event); - if (srv_scrub_log) - os_event_set(log_scrub_event); - - return(thread_active); -} - /*******************************************************************//** Tells the InnoDB server that there has been activity in the database and wakes up the master thread if it is suspended (not sleeping). Used diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index acfce274992..ffd97b61091 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2356,11 +2356,6 @@ files_checked: dict_stats_thread_init(); } - if (!srv_read_only_mode && srv_scrub_log) { - /* TODO(minliz): have/use log_scrub_thread_init() instead? */ - log_scrub_event = os_event_create(); - } - trx_sys_file_format_init(); trx_sys_create(); @@ -2725,14 +2720,17 @@ files_checked: lock_wait_timeout_thread, NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); thread_started[2 + SRV_MAX_N_IO_THREADS] = true; + lock_sys->timeout_thread_active = true; /* Create the thread which warns of long semaphore waits */ + srv_error_monitor_active = true; thread_handles[3 + SRV_MAX_N_IO_THREADS] = os_thread_create( srv_error_monitor_thread, NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); thread_started[3 + SRV_MAX_N_IO_THREADS] = true; /* Create the thread which prints InnoDB monitor info */ + srv_monitor_active = true; thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create( srv_monitor_thread, NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); @@ -2965,6 +2963,8 @@ files_checked: /* Create the buffer pool dump/load thread */ buf_dump_thread_handle= os_thread_create(buf_dump_thread, NULL, NULL); + + srv_buf_dump_thread_active = true; buf_dump_thread_started = true; #ifdef WITH_WSREP } else { @@ -2975,7 +2975,9 @@ files_checked: #endif /* WITH_WSREP */ /* Create the dict stats gathering thread */ - dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL); + dict_stats_thread_handle = os_thread_create( + dict_stats_thread, NULL, NULL); + srv_dict_stats_thread_active = true; dict_stats_thread_started = true; /* Create the thread that will optimize the FTS sub-system. */ @@ -2985,10 +2987,6 @@ files_checked: fil_system_enter(); fil_crypt_threads_init(); fil_system_exit(); - - /* Create the log scrub thread */ - if (srv_scrub_log) - os_thread_create(log_scrub_thread, NULL, NULL); } /* Init data for datafile scrub threads */ @@ -3057,9 +3055,6 @@ innobase_shutdown_for_mysql(void) fts_optimize_start_shutdown(); fts_optimize_end(); - - /* Shutdown key rotation threads */ - fil_crypt_threads_end(); } /* 1. Flush the buffer pool to disk, write the current lsn to @@ -3168,14 +3163,6 @@ innobase_shutdown_for_mysql(void) if (!srv_read_only_mode) { dict_stats_thread_deinit(); - if (srv_scrub_log) { - /* TODO(minliz): have/use log_scrub_thread_deinit() instead? */ - os_event_free(log_scrub_event); - log_scrub_event = NULL; - } - } - - if (!srv_read_only_mode) { fil_crypt_threads_cleanup(); } diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc index 114c96cec98..6abf7375775 100644 --- a/storage/xtradb/buf/buf0dump.cc +++ b/storage/xtradb/buf/buf0dump.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -682,15 +683,10 @@ again. @return this function does not return, it calls os_thread_exit() */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(buf_dump_thread)( -/*============================*/ - void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter - required by os_thread_create */ +DECLARE_THREAD(buf_dump_thread)(void*) { ut_ad(!srv_read_only_mode); - srv_buf_dump_thread_active = TRUE; - buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) not yet started"); buf_load_status(STATUS_INFO, "Loading buffer pool(s) not yet started"); @@ -720,7 +716,7 @@ DECLARE_THREAD(buf_dump_thread)( keep going even if we are in a shutdown state */); } - srv_buf_dump_thread_active = FALSE; + srv_buf_dump_thread_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc index 5f24bb2b742..c2265d6abd6 100644 --- a/storage/xtradb/dict/dict0stats_bg.cc +++ b/storage/xtradb/dict/dict0stats_bg.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -526,15 +527,10 @@ statistics. @return this function does not return, it calls os_thread_exit() */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(dict_stats_thread)( -/*==============================*/ - void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter - required by os_thread_create */ +DECLARE_THREAD(dict_stats_thread)(void*) { ut_a(!srv_read_only_mode); - srv_dict_stats_thread_active = TRUE; - while (!SHUTTING_DOWN()) { /* Wake up periodically even if not signaled. This is @@ -557,7 +553,7 @@ DECLARE_THREAD(dict_stats_thread)( os_event_reset(dict_stats_event); } - srv_dict_stats_thread_active = FALSE; + srv_dict_stats_thread_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit instead of return(). */ diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc index 1eaabf68678..2999bea2765 100644 --- a/storage/xtradb/fil/fil0crypt.cc +++ b/storage/xtradb/fil/fil0crypt.cc @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -56,7 +56,7 @@ UNIV_INTERN ulong srv_encrypt_tables = 0; UNIV_INTERN uint srv_n_fil_crypt_threads = 0; /** No of key rotation threads started */ -static uint srv_n_fil_crypt_threads_started = 0; +UNIV_INTERN uint srv_n_fil_crypt_threads_started = 0; /** At this age or older a space/page will be rotated */ UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1; @@ -65,7 +65,7 @@ UNIV_INTERN uint srv_fil_crypt_rotate_key_age = 1; static os_event_t fil_crypt_event; /** Event to signal TO the key rotation threads. */ -static os_event_t fil_crypt_threads_event; +UNIV_INTERN os_event_t fil_crypt_threads_event; /** Event for waking up threads throttle */ static os_event_t fil_crypt_throttle_sleep_event; @@ -1303,10 +1303,20 @@ struct rotate_thread_t { btr_scrub_t scrub_data; /* thread local data used by btr_scrub-functions * when iterating pages of tablespace */ - /* check if this thread should shutdown */ + /** @return whether this thread should terminate */ bool should_shutdown() const { - return ! (srv_shutdown_state == SRV_SHUTDOWN_NONE && - thread_no < srv_n_fil_crypt_threads); + switch (srv_shutdown_state) { + case SRV_SHUTDOWN_NONE: + case SRV_SHUTDOWN_CLEANUP: + return thread_no >= srv_n_fil_crypt_threads; + case SRV_SHUTDOWN_FLUSH_PHASE: + return true; + case SRV_SHUTDOWN_LAST_PHASE: + case SRV_SHUTDOWN_EXIT_THREADS: + break; + } + ut_ad(0); + return true; } }; @@ -2458,18 +2468,6 @@ fil_crypt_threads_init() } } -/********************************************************************* -End threads for key rotation */ -UNIV_INTERN -void -fil_crypt_threads_end() -/*===================*/ -{ - if (fil_crypt_threads_inited) { - fil_crypt_set_thread_cnt(0); - } -} - /********************************************************************* Clean up key rotation threads resources */ UNIV_INTERN @@ -2480,6 +2478,7 @@ fil_crypt_threads_cleanup() if (!fil_crypt_threads_inited) { return; } + ut_a(!srv_n_fil_crypt_threads_started); os_event_free(fil_crypt_event); os_event_free(fil_crypt_threads_event); mutex_free(&fil_crypt_threads_mutex); diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 6db23a3af2a..a361ab17a7c 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -68,7 +68,6 @@ this program; if not, write to the Free Software Foundation, Inc., #include "srv0srv.h" #include "trx0roll.h" #include "trx0trx.h" - #include "trx0sys.h" #include "rem0types.h" #include "row0ins.h" @@ -252,7 +251,6 @@ static char* internal_innobase_data_file_path = NULL; static char* innodb_version_str = (char*) INNODB_VERSION_STR; -extern uint srv_n_fil_crypt_threads; extern uint srv_fil_crypt_rotate_key_age; extern uint srv_n_fil_crypt_iops; diff --git a/storage/xtradb/include/fil0crypt.h b/storage/xtradb/include/fil0crypt.h index 9a35f6591e7..42cdafde4d0 100644 --- a/storage/xtradb/include/fil0crypt.h +++ b/storage/xtradb/include/fil0crypt.h @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (c) 2015, 2016, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -26,6 +26,8 @@ Created 04/01/2015 Jan Lindström #ifndef fil0crypt_h #define fil0crypt_h +#include "os0sync.h" + /** * Magic pattern in start of crypt data on page 0 */ @@ -45,6 +47,8 @@ typedef enum { FIL_SPACE_ENCRYPTION_OFF = 2 /* Tablespace is not encrypted */ } fil_encryption_t; +extern os_event_t fil_crypt_threads_event; + /** * CRYPT_SCHEME_UNENCRYPTED * @@ -391,12 +395,6 @@ fil_crypt_set_thread_cnt( /*=====================*/ uint new_cnt); /*!< in: requested #threads */ -/********************************************************************* -End threads for key rotation */ -UNIV_INTERN -void -fil_crypt_threads_end(); - /********************************************************************* Cleanup resources for threads for key rotation */ UNIV_INTERN diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h index 470274761fc..ec3ecbd1d66 100644 --- a/storage/xtradb/include/log0log.h +++ b/storage/xtradb/include/log0log.h @@ -2,6 +2,7 @@ Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, Google Inc. +Copyright (c) 2017, MariaDB Corporation Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1070,22 +1071,9 @@ struct log_t{ /* @} */ #endif /* UNIV_LOG_ARCHIVE */ -extern os_event_t log_scrub_event; /* log scrubbing speed, in bytes/sec */ extern ulonglong innodb_scrub_log_speed; -/*****************************************************************//** -This is the main thread for log scrub. It waits for an event and -when waked up fills current log block with dummy records and -sleeps again. -@return this function does not return, it calls os_thread_exit() */ -extern "C" UNIV_INTERN -os_thread_ret_t -DECLARE_THREAD(log_scrub_thread)( -/*===============================*/ - void* arg); /*!< in: a dummy parameter - required by os_thread_create */ - #ifndef UNIV_NONINL #include "log0log.ic" #endif diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index e2d141b4140..f3b6098a875 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -3,7 +3,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, 2009, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation +Copyright (c) 2013, 2017, MariaDB Corporation Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -349,7 +349,6 @@ extern char** srv_data_file_names; extern ulint* srv_data_file_sizes; extern ulint* srv_data_file_is_raw_partition; - /** Whether the redo log tracking is currently enabled. Note that it is possible for the log tracker thread to be running and the tracking to be disabled */ @@ -359,6 +358,9 @@ extern ulonglong srv_max_bitmap_file_size; extern ulonglong srv_max_changed_pages; +extern uint srv_n_fil_crypt_threads; +extern uint srv_n_fil_crypt_threads_started; + extern ibool srv_auto_extend_last_data_file; extern ulint srv_last_file_size_max; extern char* srv_log_group_home_dir; @@ -577,19 +579,17 @@ extern ibool srv_print_verbose_log; "tables instead, see " REFMAN "innodb-i_s-tables.html" extern ibool srv_print_innodb_table_monitor; -extern ibool srv_monitor_active; -extern ibool srv_error_monitor_active; +extern bool srv_monitor_active; +extern bool srv_error_monitor_active; /* TRUE during the lifetime of the buffer pool dump/load thread */ -extern ibool srv_buf_dump_thread_active; +extern bool srv_buf_dump_thread_active; /* TRUE during the lifetime of the stats thread */ -extern ibool srv_dict_stats_thread_active; +extern bool srv_dict_stats_thread_active; /* TRUE if enable log scrubbing */ extern my_bool srv_scrub_log; -/* TRUE during the lifetime of the log scrub thread */ -extern ibool srv_log_scrub_thread_active; extern ulong srv_n_spin_wait_rounds; extern ulong srv_n_free_tickets_to_enter; @@ -1085,15 +1085,6 @@ srv_release_threads( enum srv_thread_type type, /*!< in: thread type */ ulint n); /*!< in: number of threads to release */ -/**********************************************************************//** -Check whether any background thread are active. If so print which thread -is active. Send the threads wakeup signal. -@return name of thread that is active or NULL */ -UNIV_INTERN -const char* -srv_any_background_threads_are_active(void); -/*=======================================*/ - /**********************************************************************//** Wakeup the purge threads. */ UNIV_INTERN diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index c7bd223c491..8f9ea7e10aa 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -510,11 +511,7 @@ A thread which wakes up threads whose lock wait may have lasted too long. @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(lock_wait_timeout_thread)( -/*=====================================*/ - void* arg MY_ATTRIBUTE((unused))) - /* in: a dummy parameter required by - os_thread_create */ +DECLARE_THREAD(lock_wait_timeout_thread)(void*) { ib_int64_t sig_count = 0; os_event_t event = lock_sys->timeout_event; @@ -525,8 +522,6 @@ DECLARE_THREAD(lock_wait_timeout_thread)( pfs_register_thread(srv_lock_timeout_thread_key); #endif /* UNIV_PFS_THREAD */ - lock_sys->timeout_thread_active = true; - do { srv_slot_t* slot; diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc index f3a3486017c..9245ae160e6 100644 --- a/storage/xtradb/log/log0log.cc +++ b/storage/xtradb/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (C) 2014, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -52,9 +52,11 @@ Created 12/9/1995 Heikki Tuuri #include "buf0buf.h" #include "buf0flu.h" #include "srv0srv.h" +#include "lock0lock.h" #include "log0recv.h" #include "fil0fil.h" #include "dict0boot.h" +#include "dict0stats_bg.h" /* dict_stats_event */ #include "srv0srv.h" #include "srv0start.h" #include "trx0sys.h" @@ -95,6 +97,10 @@ UNIV_INTERN log_t* log_sys = NULL; UNIV_INTERN log_checksum_func_t log_checksum_algorithm_ptr = log_block_calc_checksum_innodb; +extern "C" UNIV_INTERN +os_thread_ret_t +DECLARE_THREAD(log_scrub_thread)(void*); + /* Next log block number to do dummy record filling if no log records written for a while */ static ulint next_lbn_to_pad = 0; @@ -167,6 +173,11 @@ the previous */ #define LOG_ARCHIVE_READ 1 #define LOG_ARCHIVE_WRITE 2 +/** Event to wake up the log scrub thread */ +static os_event_t log_scrub_event; + +static bool log_scrub_thread_active; + /******************************************************//** Completes a checkpoint write i/o to a log file. */ static @@ -1049,6 +1060,12 @@ log_init(void) mutex_exit(&(log_sys->mutex)); + log_scrub_thread_active = !srv_read_only_mode && srv_scrub_log; + if (log_scrub_thread_active) { + log_scrub_event = os_event_create(); + os_thread_create(log_scrub_thread, NULL, NULL); + } + #ifdef UNIV_LOG_DEBUG recv_sys_create(); recv_sys_init(buf_pool_get_curr_size()); @@ -3545,8 +3562,6 @@ logs_empty_and_mark_files_at_shutdown(void) ulint count = 0; ulint total_trx; ulint pending_io; - enum srv_thread_type active_thd; - const char* thread_name; ibool server_busy; ib_logf(IB_LOG_LEVEL_INFO, "Starting shutdown..."); @@ -3566,29 +3581,17 @@ logs_empty_and_mark_files_at_shutdown(void) srv_shutdown_state = SRV_SHUTDOWN_CLEANUP; loop: + if (!srv_read_only_mode) { + os_event_set(srv_error_event); + os_event_set(srv_monitor_event); + os_event_set(srv_buf_dump_event); + os_event_set(lock_sys->timeout_event); + os_event_set(dict_stats_event); + } os_thread_sleep(100000); count++; - /* We need the monitor threads to stop before we proceed with - a shutdown. */ - - thread_name = srv_any_background_threads_are_active(); - - if (thread_name != NULL) { - /* Print a message every 60 seconds if we are waiting - for the monitor thread to exit. Master and worker - threads check will be done later. */ - - if (srv_print_verbose_log && count > 600) { - ib_logf(IB_LOG_LEVEL_INFO, - "Waiting for %s to exit", thread_name); - count = 0; - } - - goto loop; - } - /* Check that there are no longer transactions, except for PREPARED ones. We need this wait even for the 'very fast' shutdown, because the InnoDB layer may have committed or @@ -3609,55 +3612,61 @@ loop: goto loop; } - /* Check that the background threads are suspended */ + /* We need these threads to stop early in shutdown. */ + const char* thread_name; - active_thd = srv_get_active_thread_type(); + if (srv_error_monitor_active) { + thread_name = "srv_error_monitor_thread"; + } else if (srv_monitor_active) { + thread_name = "srv_monitor_thread"; + } else if (srv_dict_stats_thread_active) { + thread_name = "dict_stats_thread"; + } else if (lock_sys->timeout_thread_active) { + thread_name = "lock_wait_timeout_thread"; + } else if (srv_buf_dump_thread_active) { + thread_name = "buf_dump_thread"; + } else { + thread_name = NULL; + } - if (active_thd != SRV_NONE) { - - if (active_thd == SRV_PURGE) { - srv_purge_wakeup(); - } - - /* The srv_lock_timeout_thread, srv_error_monitor_thread - and srv_monitor_thread should already exit by now. The - only threads to be suspended are the master threads - and worker threads (purge threads). Print the thread - type if any of such threads not in suspended mode */ + if (thread_name) { + ut_ad(!srv_read_only_mode); +wait_suspend_loop: if (srv_print_verbose_log && count > 600) { - const char* thread_type = ""; - - switch (active_thd) { - case SRV_NONE: - /* This shouldn't happen because we've - already checked for this case before - entering the if(). We handle it here - to avoid a compiler warning. */ - ut_error; - case SRV_WORKER: - thread_type = "worker threads"; - break; - case SRV_MASTER: - thread_type = "master thread"; - break; - case SRV_PURGE: - thread_type = "purge thread"; - break; - } - ib_logf(IB_LOG_LEVEL_INFO, - "Waiting for %s to be suspended", - thread_type); + "Waiting for %s to exit", thread_name); count = 0; } - goto loop; } + /* Check that the background threads are suspended */ + + switch (srv_get_active_thread_type()) { + case SRV_NONE: + srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE; + if (!srv_n_fil_crypt_threads_started) { + break; + } + os_event_set(fil_crypt_threads_event); + thread_name = "fil_crypt_thread"; + goto wait_suspend_loop; + case SRV_PURGE: + srv_purge_wakeup(); + thread_name = "purge thread"; + goto wait_suspend_loop; + case SRV_MASTER: + thread_name = "master thread"; + goto wait_suspend_loop; + case SRV_WORKER: + thread_name = "worker threads"; + goto wait_suspend_loop; + } + /* At this point only page_cleaner should be active. We wait here to let it complete the flushing of the buffer pools before proceeding further. */ - srv_shutdown_state = SRV_SHUTDOWN_FLUSH_PHASE; + count = 0; while (buf_page_cleaner_is_active || buf_lru_manager_is_active) { if (srv_print_verbose_log && count == 0) { @@ -3672,8 +3681,14 @@ loop: } } + if (log_scrub_thread_active) { + ut_ad(!srv_read_only_mode); + os_event_set(log_scrub_event); + } + mutex_enter(&log_sys->mutex); - server_busy = log_sys->n_pending_checkpoint_writes + server_busy = log_scrub_thread_active + || log_sys->n_pending_checkpoint_writes #ifdef UNIV_LOG_ARCHIVE || log_sys->n_pending_archive_ios #endif /* UNIV_LOG_ARCHIVE */ @@ -3692,6 +3707,8 @@ loop: goto loop; } + ut_ad(!log_scrub_thread_active); + pending_io = buf_pool_check_no_pending_io(); if (pending_io) { @@ -3727,16 +3744,6 @@ loop: from the stamps if the previous shutdown was clean. */ log_buffer_flush_to_disk(); - - /* Check that the background threads stay suspended */ - thread_name = srv_any_background_threads_are_active(); - - if (thread_name != NULL) { - ib_logf(IB_LOG_LEVEL_WARN, - "Background thread %s woke up " - "during shutdown", thread_name); - goto loop; - } } srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; @@ -3749,74 +3756,57 @@ loop: } fil_close_all_files(); - - thread_name = srv_any_background_threads_are_active(); - - ut_a(!thread_name); - return; } if (!srv_read_only_mode) { log_make_checkpoint_at(LSN_MAX, TRUE); - } - mutex_enter(&log_sys->mutex); + mutex_enter(&log_sys->mutex); - tracked_lsn = log_get_tracked_lsn(); + tracked_lsn = log_get_tracked_lsn(); - lsn = log_sys->lsn; + lsn = log_sys->lsn; - if (lsn != log_sys->last_checkpoint_lsn - || (srv_track_changed_pages - && (tracked_lsn != log_sys->last_checkpoint_lsn)) + if (lsn != log_sys->last_checkpoint_lsn + || (srv_track_changed_pages + && (tracked_lsn != log_sys->last_checkpoint_lsn)) #ifdef UNIV_LOG_ARCHIVE - || (srv_log_archive_on - && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE) + || (srv_log_archive_on + && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE) +#endif /* UNIV_LOG_ARCHIVE */ + ) { + + mutex_exit(&log_sys->mutex); + + goto loop; + } + +#ifdef UNIV_LOG_ARCHIVE + log_archive_close_groups(TRUE); #endif /* UNIV_LOG_ARCHIVE */ - ) { mutex_exit(&log_sys->mutex); - goto loop; - } - -#ifdef UNIV_LOG_ARCHIVE - - log_archive_close_groups(TRUE); -#endif /* UNIV_LOG_ARCHIVE */ - - mutex_exit(&log_sys->mutex); - - /* Check that the background threads stay suspended */ - thread_name = srv_any_background_threads_are_active(); - if (thread_name != NULL) { - ib_logf(IB_LOG_LEVEL_WARN, - "Background thread %s woke up during shutdown", - thread_name); - - goto loop; - } - - if (!srv_read_only_mode) { fil_flush_file_spaces(FIL_TABLESPACE); fil_flush_file_spaces(FIL_LOG); - } - /* The call fil_write_flushed_lsn_to_data_files() will pass the buffer - pool: therefore it is essential that the buffer pool has been - completely flushed to disk! (We do not call fil_write... if the - 'very fast' shutdown is enabled.) */ + /* The call fil_write_flushed_lsn_to_data_files() will + bypass the buffer pool: therefore it is essential that + the buffer pool has been completely flushed to disk! */ - if (!buf_all_freed()) { + if (!buf_all_freed()) { + if (srv_print_verbose_log && count > 600) { + ib_logf(IB_LOG_LEVEL_INFO, + "Waiting for dirty buffer pages" + " to be flushed"); + count = 0; + } - if (srv_print_verbose_log && count > 600) { - ib_logf(IB_LOG_LEVEL_INFO, - "Waiting for dirty buffer pages to be flushed"); - count = 0; + goto loop; } - - goto loop; + } else { + lsn = srv_start_lsn; } srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; @@ -4094,6 +4084,10 @@ log_shutdown(void) mutex_free(&log_sys->mutex); mutex_free(&log_sys->log_flush_order_mutex); + if (!srv_read_only_mode && srv_scrub_log) { + os_event_free(log_scrub_event); + } + #ifdef UNIV_LOG_ARCHIVE rw_lock_free(&log_sys->archive_lock); os_event_free(log_sys->archiving_on); @@ -4121,11 +4115,6 @@ log_mem_free(void) } } -/** Event to wake up the log scrub thread */ -UNIV_INTERN os_event_t log_scrub_event = NULL; - -UNIV_INTERN ibool srv_log_scrub_thread_active = FALSE; - /*****************************************************************//* If no log record has been written for a while, fill current log block with dummy records. */ @@ -4152,17 +4141,11 @@ sleeps again. @return this function does not return, it calls os_thread_exit() */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(log_scrub_thread)( -/*===============================*/ - void* arg __attribute__((unused))) /*!< in: a dummy parameter - required by os_thread_create */ +DECLARE_THREAD(log_scrub_thread)(void*) { ut_ad(!srv_read_only_mode); - srv_log_scrub_thread_active = TRUE; - - while(srv_shutdown_state == SRV_SHUTDOWN_NONE) - { + while (srv_shutdown_state < SRV_SHUTDOWN_FLUSH_PHASE) { /* log scrubbing interval in µs. */ ulonglong interval = 1000*1000*512/innodb_scrub_log_speed; @@ -4173,7 +4156,7 @@ DECLARE_THREAD(log_scrub_thread)( os_event_reset(log_scrub_event); } - srv_log_scrub_thread_active = FALSE; + log_scrub_thread_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index eff680a4ef0..bc222b864ef 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -3,7 +3,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -61,7 +61,6 @@ Created 10/8/1995 Heikki Tuuri #include "btr0sea.h" #include "dict0load.h" #include "dict0boot.h" -#include "dict0stats_bg.h" /* dict_stats_event */ #include "srv0start.h" #include "row0mysql.h" #include "row0log.h" @@ -107,15 +106,14 @@ UNIV_INTERN long long srv_kill_idle_transaction = 0; in microseconds, in order to reduce the lagging of the purge thread. */ UNIV_INTERN ulint srv_dml_needed_delay = 0; -UNIV_INTERN ibool srv_monitor_active = FALSE; -UNIV_INTERN ibool srv_error_monitor_active = FALSE; +UNIV_INTERN bool srv_monitor_active; +UNIV_INTERN bool srv_error_monitor_active; -UNIV_INTERN ibool srv_buf_dump_thread_active = FALSE; +UNIV_INTERN bool srv_buf_dump_thread_active; -UNIV_INTERN ibool srv_dict_stats_thread_active = FALSE; +UNIV_INTERN bool srv_dict_stats_thread_active; -UNIV_INTERN ibool srv_log_scrub_active = FALSE; -UNIV_INTERN my_bool srv_scrub_log = FALSE; +UNIV_INTERN my_bool srv_scrub_log; UNIV_INTERN const char* srv_main_thread_op_info = ""; @@ -2100,11 +2098,7 @@ A thread which prints the info output by various InnoDB monitors. @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(srv_monitor_thread)( -/*===============================*/ - void* arg MY_ATTRIBUTE((unused))) - /*!< in: a dummy parameter required by - os_thread_create */ +DECLARE_THREAD(srv_monitor_thread)(void*) { ib_int64_t sig_count; double time_elapsed; @@ -2125,9 +2119,7 @@ DECLARE_THREAD(srv_monitor_thread)( #ifdef UNIV_PFS_THREAD pfs_register_thread(srv_monitor_thread_key); #endif /* UNIV_PFS_THREAD */ - srv_monitor_active = TRUE; - UT_NOT_USED(arg); srv_last_monitor_time = ut_time(); last_table_monitor_time = ut_time(); last_tablespace_monitor_time = ut_time(); @@ -2259,7 +2251,7 @@ loop: goto loop; exit_func: - srv_monitor_active = FALSE; + srv_monitor_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ @@ -2277,11 +2269,7 @@ we should avoid waiting any mutexes in this function! @return a dummy parameter */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(srv_error_monitor_thread)( -/*=====================================*/ - void* arg MY_ATTRIBUTE((unused))) - /*!< in: a dummy parameter required by - os_thread_create */ +DECLARE_THREAD(srv_error_monitor_thread)(void*) { /* number of successive fatal timeouts observed */ ulint fatal_cnt = 0; @@ -2307,7 +2295,6 @@ DECLARE_THREAD(srv_error_monitor_thread)( #ifdef UNIV_PFS_THREAD pfs_register_thread(srv_error_monitor_thread_key); #endif /* UNIV_PFS_THREAD */ - srv_error_monitor_active = TRUE; loop: /* Try to track a strange bug reported by Harald Fuchs and others, @@ -2423,7 +2410,7 @@ rescan_idle: goto loop; } - srv_error_monitor_active = FALSE; + srv_error_monitor_active = false; /* We count the number of threads in os_thread_exit(). A created thread should always use that to exit and not use return() to exit. */ @@ -2487,44 +2474,6 @@ srv_get_active_thread_type(void) return(ret); } -/**********************************************************************//** -Check whether any background thread are active. If so print which thread -is active. Send the threads wakeup signal. -@return name of thread that is active or NULL */ -UNIV_INTERN -const char* -srv_any_background_threads_are_active(void) -/*=======================================*/ -{ - const char* thread_active = NULL; - - if (srv_read_only_mode) { - return(NULL); - } else if (srv_error_monitor_active) { - thread_active = "srv_error_monitor_thread"; - } else if (lock_sys->timeout_thread_active) { - thread_active = "srv_lock_timeout thread"; - } else if (srv_monitor_active) { - thread_active = "srv_monitor_thread"; - } else if (srv_buf_dump_thread_active) { - thread_active = "buf_dump_thread"; - } else if (srv_dict_stats_thread_active) { - thread_active = "dict_stats_thread"; - } else if (srv_scrub_log && srv_log_scrub_thread_active) { - thread_active = "log_scrub_thread"; - } - - os_event_set(srv_error_event); - os_event_set(srv_monitor_event); - os_event_set(srv_buf_dump_event); - os_event_set(lock_sys->timeout_event); - os_event_set(dict_stats_event); - if (srv_scrub_log) - os_event_set(log_scrub_event); - - return(thread_active); -} - /******************************************************************//** A thread which follows the redo log and outputs the changed page bitmap. @return a dummy value */ diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 8f8cf265041..31421c7a605 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -2435,11 +2435,6 @@ files_checked: dict_stats_thread_init(); } - if (!srv_read_only_mode && srv_scrub_log) { - /* TODO(minliz): have/use log_scrub_thread_init() instead? */ - log_scrub_event = os_event_create(); - } - trx_sys_file_format_init(); trx_sys_create(); @@ -2782,14 +2777,17 @@ files_checked: lock_wait_timeout_thread, NULL, thread_ids + 2 + SRV_MAX_N_IO_THREADS); thread_started[2 + SRV_MAX_N_IO_THREADS] = true; + lock_sys->timeout_thread_active = true; /* Create the thread which warns of long semaphore waits */ + srv_error_monitor_active = true; thread_handles[3 + SRV_MAX_N_IO_THREADS] = os_thread_create( srv_error_monitor_thread, NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); thread_started[3 + SRV_MAX_N_IO_THREADS] = true; /* Create the thread which prints InnoDB monitor info */ + srv_monitor_active = true; thread_handles[4 + SRV_MAX_N_IO_THREADS] = os_thread_create( srv_monitor_thread, NULL, thread_ids + 4 + SRV_MAX_N_IO_THREADS); @@ -3033,6 +3031,8 @@ files_checked: /* Create the buffer pool dump/load thread */ buf_dump_thread_handle= os_thread_create(buf_dump_thread, NULL, NULL); + + srv_buf_dump_thread_active = true; buf_dump_thread_started = true; #ifdef WITH_WSREP } else { @@ -3043,7 +3043,9 @@ files_checked: #endif /* WITH_WSREP */ /* Create the dict stats gathering thread */ - dict_stats_thread_handle = os_thread_create(dict_stats_thread, NULL, NULL); + dict_stats_thread_handle = os_thread_create( + dict_stats_thread, NULL, NULL); + srv_dict_stats_thread_active = true; dict_stats_thread_started = true; /* Create the thread that will optimize the FTS sub-system. */ @@ -3053,10 +3055,6 @@ files_checked: fil_system_enter(); fil_crypt_threads_init(); fil_system_exit(); - - /* Create the log scrub thread */ - if (srv_scrub_log) - os_thread_create(log_scrub_thread, NULL, NULL); } /* Init data for datafile scrub threads */ @@ -3125,9 +3123,6 @@ innobase_shutdown_for_mysql(void) fts_optimize_start_shutdown(); fts_optimize_end(); - - /* Shutdown key rotation threads */ - fil_crypt_threads_end(); } /* 1. Flush the buffer pool to disk, write the current lsn to @@ -3230,14 +3225,6 @@ innobase_shutdown_for_mysql(void) if (!srv_read_only_mode) { dict_stats_thread_deinit(); - if (srv_scrub_log) { - /* TODO(minliz): have/use log_scrub_thread_deinit() instead? */ - os_event_free(log_scrub_event); - log_scrub_event = NULL; - } - } - - if (!srv_read_only_mode) { fil_crypt_threads_cleanup(); } From ffb38c9771bc7248482dc6a3d2f26ca10fe09a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 4 Jan 2017 20:49:13 +0200 Subject: [PATCH 021/167] MDEV-8139 Fix scrubbing tests encryption.innodb_scrub: Clean up. Make it also cover ROW_FORMAT=COMPRESSED, removing the need for encryption.innodb_scrub_compressed. Add a FIXME comment saying that we should create a secondary index, to demonstrate that also undo log pages get scrubbed. Currently that is not working! Also clean up encryption.innodb_scrub_background, but keep it disabled, because the background scrubbing does not work reliably. Fix both tests so that if something is not scrubbed, the test will be aborted, so that the data files will be preserved. Allow the tests to run on Windows as well. --- mysql-test/include/search_pattern_in_file.inc | 6 + mysql-test/suite/encryption/disabled.def | 6 +- .../suite/encryption/r/innodb_scrub.result | 238 ++++++------------ .../r/innodb_scrub_background.result | 169 +++++++++---- .../r/innodb_scrub_compressed.result | 71 ------ .../suite/encryption/t/innodb_scrub.test | 233 +++++++++-------- .../encryption/t/innodb_scrub_background.test | 152 +++++------ .../encryption/t/innodb_scrub_compressed.opt | 9 - .../encryption/t/innodb_scrub_compressed.test | 161 ------------ 9 files changed, 398 insertions(+), 647 deletions(-) delete mode 100644 mysql-test/suite/encryption/r/innodb_scrub_compressed.result delete mode 100644 mysql-test/suite/encryption/t/innodb_scrub_compressed.opt delete mode 100644 mysql-test/suite/encryption/t/innodb_scrub_compressed.test diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index 3280dbfd574..f77a7c60916 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -82,8 +82,14 @@ perl; } $ENV{'SEARCH_FILE'} =~ s{^.*?([^/\\]+)$}{$1}; if ($content =~ m{$search_pattern}) { + die "FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n" + if $ENV{SEARCH_ABORT} eq 'FOUND'; print "FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n" + unless defined $ENV{SEARCH_ABORT}; } else { + die "NOT FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n" + if $ENV{SEARCH_ABORT} eq 'NOT FOUND'; print "NOT FOUND /$search_pattern/ in $ENV{'SEARCH_FILE'}\n" + unless defined $ENV{SEARCH_ABORT}; } EOF diff --git a/mysql-test/suite/encryption/disabled.def b/mysql-test/suite/encryption/disabled.def index 8c0d47983fd..348e4c979ea 100644 --- a/mysql-test/suite/encryption/disabled.def +++ b/mysql-test/suite/encryption/disabled.def @@ -10,8 +10,4 @@ # ############################################################################## -innodb_scrub : MDEV-8139 -innodb_scrub_compressed : MDEV-8139 -innodb_scrub_background : MDEV-8139 -innodb_encryption-page-compression : Fails with lost connection at line 156 - +innodb_scrub_background : MDEV-8139 background scrubbing does not work reliably diff --git a/mysql-test/suite/encryption/r/innodb_scrub.result b/mysql-test/suite/encryption/r/innodb_scrub.result index 95f0aed3226..6e8febc762d 100644 --- a/mysql-test/suite/encryption/r/innodb_scrub.result +++ b/mysql-test/suite/encryption/r/innodb_scrub.result @@ -1,207 +1,121 @@ create table snapshot_status engine = myisam select * from information_schema.global_status where variable_name like 'innodb_scrub%'; -# -# Test delete of records -# -create table t1 ( +# MDEV-8139 Fix scrubbing tests +# FIXME: Add index(b) to each table; ensure that undo logs are scrubbed. +create table delete_3 ( +a int auto_increment primary key, +b varchar(256), +c text) engine = innodb row_format=compressed; +delete from delete_3; +create table delete_rollback_delete_3 ( +a int auto_increment primary key, +b varchar(256), +c text) engine = innodb row_format=compressed; +begin; +delete from delete_rollback_delete_3; +rollback; +delete from delete_rollback_delete_3; +create table insert_rollback_3 ( +a int auto_increment primary key, +b varchar(256), +c text) engine = innodb row_format=compressed; +begin; +rollback; +create table delete_2 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=compact; -# Populate table with rows -delete from t1; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# compact: delete from: grep -c bicycle t1.ibd -0 -# compact: delete from: grep -c bicycle ibdata1 -0 -# compact: delete from: grep -c repairman t1.ibd -0 -# compact: delete from: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test delete+rollback+delete -# -create table t1 ( +delete from delete_2; +create table delete_rollback_delete_2 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=compact; -# Populate table with rows begin; -delete from t1; +delete from delete_rollback_delete_2; rollback; -delete from t1; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# compact: delete rollback: grep -c bicycle t1.ibd -0 -# compact: delete rollback: grep -c bicycle ibdata1 -0 -# compact: delete rollback: grep -c repairman t1.ibd -0 -# compact: delete rollback: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test insert+rollback -# -create table t1 ( +delete from delete_rollback_delete_2; +create table insert_rollback_2 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=compact; -# Populate table with rows begin; rollback; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# compact: insert rollback: grep -c bicycle t1.ibd -0 -# compact: insert rollback: grep -c bicycle ibdata1 -0 -# compact: insert rollback: grep -c repairman t1.ibd -0 -# compact: insert rollback: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test delete of records -# -create table t1 ( +create table delete_1 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=redundant; -# Populate table with rows -delete from t1; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# redundant: delete from: grep -c bicycle t1.ibd -0 -# redundant: delete from: grep -c bicycle ibdata1 -0 -# redundant: delete from: grep -c repairman t1.ibd -0 -# redundant: delete from: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test delete+rollback+delete -# -create table t1 ( +delete from delete_1; +create table delete_rollback_delete_1 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=redundant; -# Populate table with rows begin; -delete from t1; +delete from delete_rollback_delete_1; rollback; -delete from t1; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# redundant: delete rollback: grep -c bicycle t1.ibd -0 -# redundant: delete rollback: grep -c bicycle ibdata1 -0 -# redundant: delete rollback: grep -c repairman t1.ibd -0 -# redundant: delete rollback: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test insert+rollback -# -create table t1 ( +delete from delete_rollback_delete_1; +create table insert_rollback_1 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=redundant; -# Populate table with rows begin; rollback; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# redundant: insert rollback: grep -c bicycle t1.ibd -0 -# redundant: insert rollback: grep -c bicycle ibdata1 -0 -# redundant: insert rollback: grep -c repairman t1.ibd -0 -# redundant: insert rollback: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test delete of records -# -create table t1 ( +create table delete_0 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=dynamic; -# Populate table with rows -delete from t1; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# dynamic: delete from: grep -c bicycle t1.ibd -0 -# dynamic: delete from: grep -c bicycle ibdata1 -0 -# dynamic: delete from: grep -c repairman t1.ibd -0 -# dynamic: delete from: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test delete+rollback+delete -# -create table t1 ( +delete from delete_0; +create table delete_rollback_delete_0 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=dynamic; -# Populate table with rows begin; -delete from t1; +delete from delete_rollback_delete_0; rollback; -delete from t1; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# dynamic: delete rollback: grep -c bicycle t1.ibd -0 -# dynamic: delete rollback: grep -c bicycle ibdata1 -0 -# dynamic: delete rollback: grep -c repairman t1.ibd -0 -# dynamic: delete rollback: grep -c repairman ibdata1 -0 -drop table t1; -# -# Test insert+rollback -# -create table t1 ( +delete from delete_rollback_delete_0; +create table insert_rollback_0 ( a int auto_increment primary key, b varchar(256), c text) engine = innodb row_format=dynamic; -# Populate table with rows begin; rollback; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# dynamic: insert rollback: grep -c bicycle t1.ibd -0 -# dynamic: insert rollback: grep -c bicycle ibdata1 -0 -# dynamic: insert rollback: grep -c repairman t1.ibd -0 -# dynamic: insert rollback: grep -c repairman ibdata1 -0 -drop table t1; +SET GLOBAL innodb_fast_shutdown=0; +# delete_3.ibd +# delete_rollback_delete_3.ibd +# insert_rollback_3.ibd +# delete_2.ibd +# delete_rollback_delete_2.ibd +# insert_rollback_2.ibd +# delete_1.ibd +# delete_rollback_delete_1.ibd +# insert_rollback_1.ibd +# delete_0.ibd +# delete_rollback_delete_0.ibd +# insert_rollback_0.ibd +check table delete_3, delete_rollback_delete_3, insert_rollback_3; +Table Op Msg_type Msg_text +test.delete_3 check status OK +test.delete_rollback_delete_3 check status OK +test.insert_rollback_3 check status OK +drop table delete_3, delete_rollback_delete_3, insert_rollback_3; +check table delete_2, delete_rollback_delete_2, insert_rollback_2; +Table Op Msg_type Msg_text +test.delete_2 check status OK +test.delete_rollback_delete_2 check status OK +test.insert_rollback_2 check status OK +drop table delete_2, delete_rollback_delete_2, insert_rollback_2; +check table delete_1, delete_rollback_delete_1, insert_rollback_1; +Table Op Msg_type Msg_text +test.delete_1 check status OK +test.delete_rollback_delete_1 check status OK +test.insert_rollback_1 check status OK +drop table delete_1, delete_rollback_delete_1, insert_rollback_1; +check table delete_0, delete_rollback_delete_0, insert_rollback_0; +Table Op Msg_type Msg_text +test.delete_0 check status OK +test.delete_rollback_delete_0 check status OK +test.insert_rollback_0 check status OK +drop table delete_0, delete_rollback_delete_0, insert_rollback_0; show variables like 'innodb_%scrub_data%'; Variable_name Value innodb_background_scrub_data_check_interval 3600 diff --git a/mysql-test/suite/encryption/r/innodb_scrub_background.result b/mysql-test/suite/encryption/r/innodb_scrub_background.result index 1ff6c0bda98..6a2f263d0a1 100644 --- a/mysql-test/suite/encryption/r/innodb_scrub_background.result +++ b/mysql-test/suite/encryption/r/innodb_scrub_background.result @@ -11,66 +11,146 @@ innodb_background_scrub_data_uncompressed ON innodb_immediate_scrub_data_uncompressed OFF # make sure spaces are checked quickly SET GLOBAL innodb_background_scrub_data_check_interval=1; -create table snapshot_status engine = myisam -select * from information_schema.global_status -where variable_name like 'innodb_scrub%'; -truncate table snapshot_status; -insert into snapshot_status -select * from information_schema.global_status -where variable_name like 'innodb_scrub%'; -# -# Test delete of records -# -create table t1 ( +create table delete_3 ( a int auto_increment primary key, b varchar(256), -c text, index(b)) engine = innodb row_format=dynamic; +c text, +index(b)) engine = innodb row_format=compressed; # Populate table with rows -delete from t1; -# -# Test delete+rollback+delete -# -create table t2 ( +delete from delete_3; +create table delete_rollback_delete_3 ( a int auto_increment primary key, b varchar(256), -c text, index(b)) engine = innodb row_format=dynamic; +c text, +index(b)) engine = innodb row_format=compressed; # Populate table with rows begin; -delete from t2; +delete from delete_rollback_delete_3; rollback; -delete from t2; -# -# Test insert+rollback -# -create table t3 ( +delete from delete_rollback_delete_3; +create table insert_rollback_3 ( a int auto_increment primary key, b varchar(256), -c text, index(b)) engine = innodb row_format=dynamic; +c text, +index(b)) engine = innodb row_format=compressed; +# Populate table with rows +begin; +rollback; +create table delete_2 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=compact; +# Populate table with rows +delete from delete_2; +create table delete_rollback_delete_2 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=compact; +# Populate table with rows +begin; +delete from delete_rollback_delete_2; +rollback; +delete from delete_rollback_delete_2; +create table insert_rollback_2 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=compact; +# Populate table with rows +begin; +rollback; +create table delete_1 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=redundant; +# Populate table with rows +delete from delete_1; +create table delete_rollback_delete_1 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=redundant; +# Populate table with rows +begin; +delete from delete_rollback_delete_1; +rollback; +delete from delete_rollback_delete_1; +create table insert_rollback_1 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=redundant; +# Populate table with rows +begin; +rollback; +create table delete_0 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=dynamic; +# Populate table with rows +delete from delete_0; +create table delete_rollback_delete_0 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=dynamic; +# Populate table with rows +begin; +delete from delete_rollback_delete_0; +rollback; +delete from delete_rollback_delete_0; +create table insert_rollback_0 ( +a int auto_increment primary key, +b varchar(256), +c text, +index(b)) engine = innodb row_format=dynamic; # Populate table with rows begin; rollback; # start scrubbing threads SET GLOBAL innodb_encryption_threads=5; # Wait max 10 min for scrubbing -# Success! -# stop scrubbing threads -SET GLOBAL innodb_encryption_threads=0; -# restart mysqld so that all pages are flushed -# read all rows from table -select * from t1; -# dynamic: delete: grep -c bicycle t1.ibd -0 -# dynamic: delete: grep -c repairman t1.ibd -0 -# dynamic: delete rollback: grep -c bicycle t2.ibd -0 -# dynamic: delete rollback: grep -c repairman t2.ibd -0 -# dynamic: insert rollback: grep -c bicycle t3.ibd -0 -# dynamic: insert rollback: grep -c repairman t3.ibd -0 -drop table t1, t2, t3; +SET GLOBAL innodb_fast_shutdown=0; +# delete_3.ibd +# delete_rollback_delete_3.ibd +# insert_rollback_3.ibd +# delete_2.ibd +# delete_rollback_delete_2.ibd +# insert_rollback_2.ibd +# delete_1.ibd +# delete_rollback_delete_1.ibd +# insert_rollback_1.ibd +# delete_0.ibd +# delete_rollback_delete_0.ibd +# insert_rollback_0.ibd +check table delete_3, delete_rollback_delete_3, insert_rollback_3; +Table Op Msg_type Msg_text +test.delete_3 check status OK +test.delete_rollback_delete_3 check status OK +test.insert_rollback_3 check status OK +drop table delete_3, delete_rollback_delete_3, insert_rollback_3; +check table delete_2, delete_rollback_delete_2, insert_rollback_2; +Table Op Msg_type Msg_text +test.delete_2 check status OK +test.delete_rollback_delete_2 check status OK +test.insert_rollback_2 check status OK +drop table delete_2, delete_rollback_delete_2, insert_rollback_2; +check table delete_1, delete_rollback_delete_1, insert_rollback_1; +Table Op Msg_type Msg_text +test.delete_1 check status OK +test.delete_rollback_delete_1 check status OK +test.insert_rollback_1 check status OK +drop table delete_1, delete_rollback_delete_1, insert_rollback_1; +check table delete_0, delete_rollback_delete_0, insert_rollback_0; +Table Op Msg_type Msg_text +test.delete_0 check status OK +test.delete_rollback_delete_0 check status OK +test.insert_rollback_0 check status OK +drop table delete_0, delete_rollback_delete_0, insert_rollback_0; show variables like 'innodb_%scrub_data%'; Variable_name Value innodb_background_scrub_data_check_interval 3600 @@ -78,4 +158,3 @@ innodb_background_scrub_data_compressed ON innodb_background_scrub_data_interval 604800 innodb_background_scrub_data_uncompressed ON innodb_immediate_scrub_data_uncompressed OFF -drop table snapshot_status; diff --git a/mysql-test/suite/encryption/r/innodb_scrub_compressed.result b/mysql-test/suite/encryption/r/innodb_scrub_compressed.result deleted file mode 100644 index 0b5e9f11a05..00000000000 --- a/mysql-test/suite/encryption/r/innodb_scrub_compressed.result +++ /dev/null @@ -1,71 +0,0 @@ -# make sure spaces are checked quickly -SET GLOBAL innodb_background_scrub_data_check_interval=1; -# -# Test delete of records -# -create table t1 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compressed; -# Populate table with rows -delete from t1; -# -# Test delete+rollback+delete -# -create table t2 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compressed; -# Populate table with rows -begin; -delete from t2; -rollback; -delete from t2; -# -# Test insert+rollback -# -create table t3 ( -a int auto_increment primary key, -b varchar(256), -c text) engine = innodb row_format=compressed; -# Populate table with rows -begin; -rollback; -# start scrubbing threads -SET GLOBAL innodb_encryption_threads=5; -# Wait max 10 min for scrubbing of this table -# Success! -# stop scrubbing threads -SET GLOBAL innodb_encryption_threads=0; -# Now there should be background scrubs -# restart mysqld so that all pages are flushed (encryption off) -# so that grep will find stuff -# read all rows from table -select * from t1; -select * from t2; -select * from t3; -# grep -c bicycle t1.ibd -0 -# grep -c bicycle ibdata1 -0 -# grep -c repairman t1.ibd -0 -# grep -c repairman ibdata1 -0 -# grep -c boondoggle t2.ibd -0 -# grep -c boondoggle ibdata1 -0 -# grep -c waste t2.ibd -0 -# grep -c waste ibdata1 -0 -# grep -c keso t3.ibd -0 -# grep -c keso ibdata1 -0 -# grep -c kent t3.ibd -0 -# grep -c kent ibdata1 -0 -drop table t1, t2, t3; diff --git a/mysql-test/suite/encryption/t/innodb_scrub.test b/mysql-test/suite/encryption/t/innodb_scrub.test index 32170567b4c..6cb48530f86 100644 --- a/mysql-test/suite/encryption/t/innodb_scrub.test +++ b/mysql-test/suite/encryption/t/innodb_scrub.test @@ -1,147 +1,138 @@ -- source include/have_innodb.inc -- source include/not_embedded.inc -- source include/have_example_key_management_plugin.inc --- source include/not_windows.inc let $MYSQLD_DATADIR=`select @@datadir`; -let ib1_IBD = $MYSQLD_DATADIR/ibdata1; -let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd; +let INNODB_PAGE_SIZE= `select @@innodb_page_size`; create table snapshot_status engine = myisam select * from information_schema.global_status where variable_name like 'innodb_scrub%'; let $rowcount=500; -let $formatno = 3; +let $maxformatno= 4; +let $formatno= $maxformatno; + +--echo # MDEV-8139 Fix scrubbing tests +--echo # FIXME: Add index(b) to each table; ensure that undo logs are scrubbed. +let $tableformat= ( + a int auto_increment primary key, + b varchar(256), + c text) engine = innodb row_format; + while ($formatno) { +dec $formatno; let $format = `select case $formatno - when 1 then 'dynamic' - when 2 then 'redundant' - when 3 then 'compact' + when 0 then 'dynamic' + when 1 then 'redundant' + when 2 then 'compact' + when 3 then 'compressed' end`; + +let $t= delete_$formatno; +eval create table $t $tableformat=$format; + +let $numinserts = $rowcount; +--disable_query_log +begin; +while ($numinserts) +{ + dec $numinserts; + eval insert into $t(b,c) values ('repairman', repeat('unicycle', 1000)); +} +commit; +--enable_query_log + +eval delete from $t; + +let $t= delete_rollback_delete_$formatno; +eval create table $t $tableformat=$format; + +let $numinserts = $rowcount; +--disable_query_log +begin; +while ($numinserts) +{ + dec $numinserts; + eval insert into $t(b,c) values ('breakhuman', repeat('bicycle', 1000)); +} +commit; +--enable_query_log + +begin; +eval delete from $t; +rollback; +eval delete from $t; + +let $t= insert_rollback_$formatno; + +eval create table $t $tableformat=$format; + +let $numinserts = $rowcount; +begin; +--disable_query_log +while ($numinserts) +{ + dec $numinserts; + eval insert into $t(b,c) values ('wonderwoman', repeat('tricycle', 1000)); +} +--enable_query_log + +rollback; +} + +SET GLOBAL innodb_fast_shutdown=0; +-- source include/shutdown_mysqld.inc + +let SEARCH_ABORT= FOUND; +let SEARCH_PATTERN= (un|b|tr)icycle|(repair|breakhu|wonderwo)man; +let SEARCH_RANGE= 12582912; +let SEARCH_FILE= $MYSQLD_DATADIR/ibdata1; + +# We may randomly find copies of unscrubbed pages in the doublewrite buffer. +# Let us scrub the doublewrite buffer ourselves. +perl; +use Fcntl 'SEEK_SET'; +my $page_size = $ENV{INNODB_PAGE_SIZE}; +open(FILE, "+<", "$ENV{SEARCH_FILE}") or die "cannot open: $!\n"; +seek(FILE, $page_size * 64, SEEK_SET) or die "cannot seek: $!\n"; +print(FILE chr(0) x ($page_size * 128)) or die "cannot write: $!\n"; +close FILE or die "cannot close: $!\n";; +EOF + +-- source include/search_pattern_in_file.inc + +let $formatno= $maxformatno; +while ($formatno) +{ dec $formatno; --- echo # --- echo # Test delete of records --- echo # - -eval create table t1 ( - a int auto_increment primary key, - b varchar(256), - c text) engine = innodb row_format=$format; - -let $numinserts = $rowcount; --- echo # Populate table with rows ---disable_query_log -while ($numinserts) -{ - dec $numinserts; - insert into t1(b,c) values ('bicycle', repeat('repairman', 1000)); +let $t= delete_$formatno.ibd; +let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; +-- echo # $t +-- source include/search_pattern_in_file.inc +let $t= delete_rollback_delete_$formatno.ibd; +let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; +-- echo # $t +-- source include/search_pattern_in_file.inc +let $t= insert_rollback_$formatno.ibd; +let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; +-- echo # $t +-- source include/search_pattern_in_file.inc } ---enable_query_log -delete from t1; +-- source include/start_mysqld.inc --- echo # restart mysqld so that all pages are flushed --- source include/restart_mysqld.inc --- echo # read all rows from table --- disable_result_log -select * from t1; --- enable_result_log - --- echo # $format: delete from: grep -c bicycle t1.ibd --- exec grep -c bicycle $t1_IBD || true --- echo # $format: delete from: grep -c bicycle ibdata1 --- exec grep -c bicycle $ib1_IBD || true --- echo # $format: delete from: grep -c repairman t1.ibd --- exec grep -c repairman $t1_IBD || true --- echo # $format: delete from: grep -c repairman ibdata1 --- exec grep -c repairman $ib1_IBD || true - -drop table t1; - --- echo # --- echo # Test delete+rollback+delete --- echo # - -eval create table t1 ( - a int auto_increment primary key, - b varchar(256), - c text) engine = innodb row_format=$format; - -let $numinserts = $rowcount; --- echo # Populate table with rows ---disable_query_log -while ($numinserts) +let $formatno= $maxformatno; +while ($formatno) { - dec $numinserts; - insert into t1(b,c) values ('bicycle', repeat('repairman', 1000)); -} ---enable_query_log +dec $formatno; -begin; -delete from t1; -rollback; -delete from t1; +let $t= delete_$formatno, delete_rollback_delete_$formatno, insert_rollback_$formatno; --- echo # restart mysqld so that all pages are flushed --- source include/restart_mysqld.inc --- echo # read all rows from table --- disable_result_log -select * from t1; --- enable_result_log - --- echo # $format: delete rollback: grep -c bicycle t1.ibd --- exec grep -c bicycle $t1_IBD || true --- echo # $format: delete rollback: grep -c bicycle ibdata1 --- exec grep -c bicycle $ib1_IBD || true --- echo # $format: delete rollback: grep -c repairman t1.ibd --- exec grep -c repairman $t1_IBD || true --- echo # $format: delete rollback: grep -c repairman ibdata1 --- exec grep -c repairman $ib1_IBD || true - -drop table t1; - --- echo # --- echo # Test insert+rollback --- echo # - -eval create table t1 ( - a int auto_increment primary key, - b varchar(256), - c text) engine = innodb row_format=$format; - -let $numinserts = $rowcount; --- echo # Populate table with rows -begin; ---disable_query_log -while ($numinserts) -{ - dec $numinserts; - insert into t1(b,c) values ('bicycle', repeat('repairman', 1000)); -} ---enable_query_log - -rollback; - --- echo # restart mysqld so that all pages are flushed --- source include/restart_mysqld.inc --- echo # read all rows from table --- disable_result_log -select * from t1; --- enable_result_log - --- echo # $format: insert rollback: grep -c bicycle t1.ibd --- exec grep -c bicycle $t1_IBD || true --- echo # $format: insert rollback: grep -c bicycle ibdata1 --- exec grep -c bicycle $ib1_IBD || true --- echo # $format: insert rollback: grep -c repairman t1.ibd --- exec grep -c repairman $t1_IBD || true --- echo # $format: insert rollback: grep -c repairman ibdata1 --- exec grep -c repairman $ib1_IBD || true - -drop table t1; +eval check table $t; +eval drop table $t; } show variables like 'innodb_%scrub_data%'; diff --git a/mysql-test/suite/encryption/t/innodb_scrub_background.test b/mysql-test/suite/encryption/t/innodb_scrub_background.test index 19e56683117..c705ee51006 100644 --- a/mysql-test/suite/encryption/t/innodb_scrub_background.test +++ b/mysql-test/suite/encryption/t/innodb_scrub_background.test @@ -1,13 +1,9 @@ -- source include/have_innodb.inc -- source include/not_embedded.inc -- source include/have_example_key_management_plugin.inc --- source include/not_windows.inc let $MYSQLD_DATADIR=`select @@datadir`; -let ib1_IBD = $MYSQLD_DATADIR/ibdata1; -let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd; -let t2_IBD = $MYSQLD_DATADIR/test/t2.ibd; -let t3_IBD = $MYSQLD_DATADIR/test/t3.ibd; +let INNODB_PAGE_SIZE= `select @@innodb_page_size`; --echo # --echo # immediate scrubbing is off @@ -18,80 +14,67 @@ show variables like 'innodb_%scrub_data%'; -- echo # make sure spaces are checked quickly SET GLOBAL innodb_background_scrub_data_check_interval=1; -create table snapshot_status engine = myisam -select * from information_schema.global_status -where variable_name like 'innodb_scrub%'; - let $rowcount=500; -let $formatno = 1; +let $maxformatno= 4; +let $formatno= $maxformatno; + +let $tableformat= ( + a int auto_increment primary key, + b varchar(256), + c text, + index(b)) engine = innodb row_format; + while ($formatno) { -let $format = `select case $formatno - when 1 then 'dynamic' - when 2 then 'redundant' - when 3 then 'compact' - when 4 then 'compressed' - end`; dec $formatno; +let $format = `select case $formatno + when 0 then 'dynamic' + when 1 then 'redundant' + when 2 then 'compact' + when 3 then 'compressed' + end`; -truncate table snapshot_status; -insert into snapshot_status -select * from information_schema.global_status -where variable_name like 'innodb_scrub%'; - --- echo # --- echo # Test delete of records --- echo # - -eval create table t1 ( - a int auto_increment primary key, - b varchar(256), - c text, index(b)) engine = innodb row_format=$format; +let $t= delete_$formatno; +eval create table $t $tableformat=$format; let $numinserts = $rowcount; -- echo # Populate table with rows --disable_query_log +begin; while ($numinserts) { dec $numinserts; - insert into t1(b,c) values ('bicycle', repeat('repairman', 1000)); + eval insert into $t(b,c) values ('unicycle', repeat('wonderwoman', 1000)); } +commit; --enable_query_log -delete from t1; +eval delete from $t; --- echo # --- echo # Test delete+rollback+delete --- echo # +let $t= delete_rollback_delete_$formatno; -eval create table t2 ( - a int auto_increment primary key, - b varchar(256), - c text, index(b)) engine = innodb row_format=$format; +eval create table $t $tableformat=$format; let $numinserts = $rowcount; -- echo # Populate table with rows --disable_query_log +begin; while ($numinserts) { dec $numinserts; - insert into t2(b,c) values ('bicycle', repeat('repairman', 1000)); + eval insert into $t(b,c) values ('bicycle', repeat('repairman', 1000)); } +commit; --enable_query_log begin; -delete from t2; +eval delete from $t; rollback; -delete from t2; +eval delete from $t; --- echo # --- echo # Test insert+rollback --- echo # +let $t= insert_rollback_$formatno; -eval create table t3 ( - a int auto_increment primary key, - b varchar(256), - c text, index(b)) engine = innodb row_format=$format; +eval create table $t $tableformat=$format; let $numinserts = $rowcount; -- echo # Populate table with rows @@ -100,11 +83,12 @@ begin; while ($numinserts) { dec $numinserts; - insert into t3(b,c) values ('bicycle', repeat('repairman', 1000)); + eval insert into $t(b,c) values ('tricycle', repeat('superhuman', 1000)); } --enable_query_log rollback; +} -- echo # start scrubbing threads SET GLOBAL innodb_encryption_threads=5; @@ -130,35 +114,57 @@ if (!$success) -- die Timeout waiting for background threads } --- echo # Success! --- echo # stop scrubbing threads -SET GLOBAL innodb_encryption_threads=0; +SET GLOBAL innodb_fast_shutdown=0; +-- source include/shutdown_mysqld.inc --- echo # restart mysqld so that all pages are flushed --- source include/restart_mysqld.inc --- echo # read all rows from table --- disable_result_log -select * from t1; --- enable_result_log +let SEARCH_ABORT= FOUND; +let SEARCH_PATTERN= (un|b|tr)icycle|(repair|breakhu|wonderwo)man; +let SEARCH_RANGE= 12582912; +let SEARCH_FILE= $MYSQLD_DATADIR/ibdata1; --- echo # $format: delete: grep -c bicycle t1.ibd --- exec grep -c bicycle $t1_IBD || true --- echo # $format: delete: grep -c repairman t1.ibd --- exec grep -c repairman $t1_IBD || true +# We may randomly find copies of unscrubbed pages in the doublewrite buffer. +# Let us scrub the doublewrite buffer ourselves. +perl; +use Fcntl 'SEEK_SET'; +my $page_size = $ENV{INNODB_PAGE_SIZE}; +open(FILE, "+<", "$ENV{SEARCH_FILE}") or die "cannot open: $!\n"; +seek(FILE, $page_size * 64, SEEK_SET) or die "cannot seek: $!\n"; +print(FILE chr(0) x ($page_size * 128)) or die "cannot write: $!\n"; +close FILE or die "cannot close: $!\n";; +EOF --- echo # $format: delete rollback: grep -c bicycle t2.ibd --- exec grep -c bicycle $t2_IBD || true --- echo # $format: delete rollback: grep -c repairman t2.ibd --- exec grep -c repairman $t2_IBD || true +-- source include/search_pattern_in_file.inc --- echo # $format: insert rollback: grep -c bicycle t3.ibd --- exec grep -c bicycle $t3_IBD || true --- echo # $format: insert rollback: grep -c repairman t3.ibd --- exec grep -c repairman $t3_IBD || true +let $formatno= $maxformatno; +while ($formatno) +{ +dec $formatno; -drop table t1, t2, t3; +let $t= delete_$formatno.ibd; +let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; +-- echo # $t +-- source include/search_pattern_in_file.inc +let $t= delete_rollback_delete_$formatno.ibd; +let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; +-- echo # $t +-- source include/search_pattern_in_file.inc +let $t= insert_rollback_$formatno.ibd; +let SEARCH_FILE= $MYSQLD_DATADIR/test/$t; +-- echo # $t +-- source include/search_pattern_in_file.inc +} + +-- source include/start_mysqld.inc + +let $formatno= $maxformatno; +while ($formatno) +{ +dec $formatno; + +let $t= delete_$formatno, delete_rollback_delete_$formatno, insert_rollback_$formatno; + +eval check table $t; +eval drop table $t; } show variables like 'innodb_%scrub_data%'; - -drop table snapshot_status; diff --git a/mysql-test/suite/encryption/t/innodb_scrub_compressed.opt b/mysql-test/suite/encryption/t/innodb_scrub_compressed.opt deleted file mode 100644 index 48b04fa7049..00000000000 --- a/mysql-test/suite/encryption/t/innodb_scrub_compressed.opt +++ /dev/null @@ -1,9 +0,0 @@ ---innodb-file-per-table=1 ---innodb-file-format=Barracuda ---innodb-immediate-scrub-data-uncompressed=ON ---innodb-background-scrub-data-uncompressed=ON ---innodb-background-scrub-data-compressed=ON ---loose-innodb-debug-force-scrubbing=ON ---innodb-encrypt-tables=OFF ---innodb-encrypt-log=OFF ---innodb-tablespaces-scrubbing diff --git a/mysql-test/suite/encryption/t/innodb_scrub_compressed.test b/mysql-test/suite/encryption/t/innodb_scrub_compressed.test deleted file mode 100644 index d41edac7494..00000000000 --- a/mysql-test/suite/encryption/t/innodb_scrub_compressed.test +++ /dev/null @@ -1,161 +0,0 @@ --- source include/have_innodb.inc --- source include/not_embedded.inc --- source include/have_example_key_management_plugin.inc --- source include/not_windows.inc - -let $MYSQLD_DATADIR=`select @@datadir`; -let ib1_IBD = $MYSQLD_DATADIR/ibdata1; -let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd; -let t2_IBD = $MYSQLD_DATADIR/test/t2.ibd; -let t3_IBD = $MYSQLD_DATADIR/test/t3.ibd; - -let $rowcount=500; - --- echo # make sure spaces are checked quickly -SET GLOBAL innodb_background_scrub_data_check_interval=1; - --- echo # --- echo # Test delete of records --- echo # - -eval create table t1 ( - a int auto_increment primary key, - b varchar(256), - c text) engine = innodb row_format=compressed; - -let $numinserts = $rowcount; --- echo # Populate table with rows ---disable_query_log -while ($numinserts) -{ - dec $numinserts; - insert into t1(b,c) values ('bicycle', repeat('repairman', 1000)); -} ---enable_query_log - -delete from t1; - --- echo # --- echo # Test delete+rollback+delete --- echo # - -eval create table t2 ( - a int auto_increment primary key, - b varchar(256), - c text) engine = innodb row_format=compressed; - -let $numinserts = $rowcount; --- echo # Populate table with rows ---disable_query_log -while ($numinserts) -{ - dec $numinserts; - insert into t2(b,c) values ('boondoggle', repeat('waste of time', 1000)); -} ---enable_query_log - -begin; -delete from t2; -rollback; -delete from t2; - --- echo # --- echo # Test insert+rollback --- echo # - -eval create table t3 ( - a int auto_increment primary key, - b varchar(256), - c text) engine = innodb row_format=compressed; - -let $numinserts = $rowcount; --- echo # Populate table with rows -begin; ---disable_query_log -while ($numinserts) -{ - dec $numinserts; - insert into t3(b,c) values ('keso', repeat('kent', 1000)); -} ---enable_query_log - -rollback; - --- echo # start scrubbing threads -SET GLOBAL innodb_encryption_threads=5; --- echo # Wait max 10 min for scrubbing of this table -let $cnt=600; -while ($cnt) -{ - let $success=`SELECT COUNT(*) = 0 -FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING -WHERE LAST_SCRUB_COMPLETED IS NULL AND ( NAME like 'test/%' OR SPACE = 0 )`; - - if ($success) - { - let $cnt=0; - } - if (!$success) - { - real_sleep 1; - dec $cnt; - } -} -if (!$success) -{ - SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_SCRUBBING; - SHOW STATUS LIKE 'innodb_%scrub%'; - -- die Timeout waiting for background threads -} --- echo # Success! --- echo # stop scrubbing threads -SET GLOBAL innodb_encryption_threads=0; - ---echo # Now there should be background scrubs -let $success=`select sum(variable_value) > 0 -from information_schema.global_status -where variable_name in ('innodb_scrub_background_page_reorganizations', -'innodb_scrub_background_page_splits')`; - -if (!$success) { - show status like 'innodb_scrub%'; -} - --- echo # restart mysqld so that all pages are flushed (encryption off) --- echo # so that grep will find stuff --- source include/restart_mysqld.inc --- echo # read all rows from table --- disable_result_log -select * from t1; -select * from t2; -select * from t3; --- enable_result_log - --- echo # grep -c bicycle t1.ibd --- exec grep -c bicycle $t1_IBD || true --- echo # grep -c bicycle ibdata1 --- exec grep -c bicycle $ib1_IBD || true --- echo # grep -c repairman t1.ibd --- exec grep -c repairman $t1_IBD || true --- echo # grep -c repairman ibdata1 --- exec grep -c repairman $ib1_IBD || true - --- echo # grep -c boondoggle t2.ibd --- exec grep -c boondoggle $t2_IBD || true --- echo # grep -c boondoggle ibdata1 --- exec grep -c boondoggle $ib1_IBD || true --- echo # grep -c waste t2.ibd --- exec grep -c waste $t2_IBD || true --- echo # grep -c waste ibdata1 --- exec grep -c waste $ib1_IBD || true - --- echo # grep -c keso t3.ibd --- exec grep -c keso $t3_IBD || true --- echo # grep -c keso ibdata1 --- exec grep -c keso $ib1_IBD || true --- echo # grep -c kent t3.ibd --- exec grep -c kent $t3_IBD || true --- echo # grep -c kent ibdata1 --- exec grep -c kent $ib1_IBD || true - -drop table t1, t2, t3; From 348ccb6f038a6c108ab9b6a01bdc356cefecd3d4 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 4 Jan 2017 14:33:24 -0800 Subject: [PATCH 022/167] Fixed bug mdev-11674. 1. The rows of a recursive CTE at some point may overflow the HEAP temporary table containing them. At this point the table is converted to a MyISAM temporary table and the new added rows are placed into this MyISAM table. A bug in the of select_union_recursive::send_data prevented the server from writing the row that caused the overflow into the temporary table used for the result of the iteration steps. This could lead, in particular,to a premature end of the iterations. 2. The method TABLE::insert_all_rows_into() that was used to copy all rows of one temporary table into another did not take into account that the destination temporary table must be converted to a MyISAM table at some point. This patch fixed this problem. It also renamed the method into TABLE::insert_all_rows_into_tmp_table() and added an extra parameter needed for the conversion. --- mysql-test/r/cte_recursive.result | 16 +++++++++++++++ mysql-test/t/cte_recursive.test | 21 +++++++++++++++++++ sql/sql_derived.cc | 5 ++++- sql/sql_union.cc | 7 +++++-- sql/table.cc | 34 +++++++++++++++++++++---------- sql/table.h | 6 +++++- 6 files changed, 74 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index 0cc88d27e23..d5476aec1c4 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -2327,3 +2327,19 @@ a b dist 7 6 3 DROP VIEW edges2; DROP TABLE edges; +# +# MDEV-11674: recursive CTE table that cannot be stored +# in a heap table +# +create table t1 (id int, test_data varchar(36)); +insert into t1(id, test_data) +select id, test_data +from ( +with recursive data_generator(id, test_data) as ( +select 1 as id, uuid() as test_data +union all +select id + 1, uuid() from data_generator where id < 150000 +) +select * from data_generator +) as a; +drop table t1; diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index 63bcfbffeb9..ea0f73be259 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -1484,3 +1484,24 @@ ORDER BY a, dist, b; DROP VIEW edges2; DROP TABLE edges; + + +--echo # +--echo # MDEV-11674: recursive CTE table that cannot be stored +--echo # in a heap table +--echo # + +create table t1 (id int, test_data varchar(36)); + +insert into t1(id, test_data) +select id, test_data + from ( + with recursive data_generator(id, test_data) as ( + select 1 as id, uuid() as test_data + union all + select id + 1, uuid() from data_generator where id < 150000 + ) + select * from data_generator + ) as a; + +drop table t1; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index daac90d56f6..898b6336ae5 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -969,7 +969,10 @@ bool TABLE_LIST::fill_recursive(THD *thd) if (!rc) { TABLE *src= with->rec_result->table; - rc =src->insert_all_rows_into(thd, table, true); + rc =src->insert_all_rows_into_tmp_table(thd, + table, + &with->rec_result->tmp_table_param, + true); } return rc; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index aad3701cca2..b30b5528741 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -105,7 +105,7 @@ int select_union_recursive::send_data(List &values) { int rc= select_union::send_data(values); - if (!write_err) + if (write_err != HA_ERR_FOUND_DUPP_KEY) { int err; if ((err= incr_table->file->ha_write_tmp_row(table->record[0]))) @@ -1192,6 +1192,7 @@ bool st_select_lex_unit::exec_recursive() st_select_lex *end= NULL; bool is_unrestricted= with_element->is_unrestricted(); List_iterator_fast li(with_element->rec_result->rec_tables); + TMP_TABLE_PARAM *tmp_table_param= &with_element->rec_result->tmp_table_param; ha_rows examined_rows= 0; bool was_executed= executed; TABLE *rec_table; @@ -1247,7 +1248,9 @@ bool st_select_lex_unit::exec_recursive() while ((rec_table= li++)) { saved_error= - incr_table->insert_all_rows_into(thd, rec_table, !is_unrestricted); + incr_table->insert_all_rows_into_tmp_table(thd, rec_table, + tmp_table_param, + !is_unrestricted); if (!with_element->rec_result->first_rec_table_to_update) with_element->rec_result->first_rec_table_to_update= rec_table; if (with_element->level == 1) diff --git a/sql/table.cc b/sql/table.cc index 4688b77ecd7..6d11ac3d3eb 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -7573,46 +7573,58 @@ bool TABLE::validate_default_values_of_unset_fields(THD *thd) const } -bool TABLE::insert_all_rows_into(THD *thd, TABLE *dest, bool with_cleanup) +bool TABLE::insert_all_rows_into_tmp_table(THD *thd, + TABLE *tmp_table, + TMP_TABLE_PARAM *tmp_table_param, + bool with_cleanup) { int write_err= 0; - DBUG_ENTER("TABLE::insert_all_rows_into"); + DBUG_ENTER("TABLE::insert_all_rows_into_tmp_table"); if (with_cleanup) { - if ((write_err= dest->file->ha_delete_all_rows())) + if ((write_err= tmp_table->file->ha_delete_all_rows())) goto err; } if (file->indexes_are_disabled()) - dest->file->ha_disable_indexes(HA_KEY_SWITCH_ALL); + tmp_table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL); file->ha_index_or_rnd_end(); if (file->ha_rnd_init_with_error(1)) DBUG_RETURN(1); - if (dest->no_rows) - dest->file->extra(HA_EXTRA_NO_ROWS); + if (tmp_table->no_rows) + tmp_table->file->extra(HA_EXTRA_NO_ROWS); else { /* update table->file->stats.records */ file->info(HA_STATUS_VARIABLE); - dest->file->ha_start_bulk_insert(file->stats.records); + tmp_table->file->ha_start_bulk_insert(file->stats.records); } - while (!file->ha_rnd_next(dest->record[1])) + while (!file->ha_rnd_next(tmp_table->record[0])) { - write_err= dest->file->ha_write_tmp_row(dest->record[1]); + write_err= tmp_table->file->ha_write_tmp_row(tmp_table->record[0]); if (write_err) - goto err; + { + bool is_duplicate; + if (tmp_table->file->is_fatal_error(write_err, HA_CHECK_DUP) && + create_internal_tmp_table_from_heap(thd, tmp_table, + tmp_table_param->start_recinfo, + &tmp_table_param->recinfo, + write_err, 1, &is_duplicate)) + DBUG_RETURN(1); + + } if (thd->check_killed()) { thd->send_kill_message(); goto err_killed; } } - if (!dest->no_rows && dest->file->ha_end_bulk_insert()) + if (!tmp_table->no_rows && tmp_table->file->ha_end_bulk_insert()) goto err; DBUG_RETURN(0); diff --git a/sql/table.h b/sql/table.h index 6552a8e13da..b2d5599b740 100644 --- a/sql/table.h +++ b/sql/table.h @@ -53,6 +53,7 @@ class With_element; struct TDC_element; class Virtual_column_info; class Table_triggers_list; +class TMP_TABLE_PARAM; /* Used to identify NESTED_JOIN structures within a join (applicable only to @@ -1447,7 +1448,10 @@ public: inline Field **field_to_fill(); bool validate_default_values_of_unset_fields(THD *thd) const; - bool insert_all_rows_into(THD *thd, TABLE *dest, bool with_cleanup); + bool insert_all_rows_into_tmp_table(THD *thd, + TABLE *tmp_table, + TMP_TABLE_PARAM *tmp_table_param, + bool with_cleanup); }; From 758af98ff7c47cc1fb5debdc138312fa389d528f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 5 Jan 2017 10:42:19 +0200 Subject: [PATCH 023/167] Post-push fix for Part 1 of MDEV-8139 Fix scrubbing tests In the backport of Bug#24450908 UNDO LOG EXISTS AFTER SLOW SHUTDOWN from MySQL 5.7 to the MySQL 5.6 based MariaDB Server 10.1, we must use a mutex when HAVE_ATOMIC_BUILTINS is not defined. Also, correct a function comment. In MySQL 5.6 and MariaDB Server 10.1, also temporary InnoDB tables are redo-logged. --- storage/innobase/trx/trx0purge.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 42b94d9b6a3..b3d16546a63 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -294,15 +294,19 @@ trx_purge_remove_log_hdr( { flst_remove(rseg_hdr + TRX_RSEG_HISTORY, log_hdr + TRX_UNDO_HISTORY_NODE, mtr); - +#ifdef HAVE_ATOMIC_BUILTINS os_atomic_decrement_ulint(&trx_sys->rseg_history_len, 1); +#else + mutex_enter(&trx_sys->mutex); + --trx_sys->rseg_history_len; + mutex_exit(&trx_sys->mutex); +#endif } /** Frees an undo log segment which is in the history list. Removes the undo log hdr from the history list. @param[in,out] rseg rollback segment -@param[in] hdr_addr file address of log_hdr -@param[in] noredo skip redo logging. */ +@param[in] hdr_addr file address of log_hdr */ static void trx_purge_free_segment( From bf35deda09f18f5c7f3179ace731a2a186e05445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 3 Jan 2017 15:38:09 +0200 Subject: [PATCH 024/167] MDEV-11713 Optimize DBUG_PRINT and introduce DBUG_LOG MariaDB Server is unnecessarily evaluating the arguments of DBUG_PRINT() macros when the label is not defined. The macro DBUG_LOG() for C++ operator<< output which was added for InnoDB diagnostics in MySQL 5.7 is missing from MariaDB. Unlike the MySQL 5.7 implementation, MariaDB will avoid allocating and initializing the output string when the label is not defined. Introduce DBUG_OUT("crypt") and DBUG_OUT("checksum") for some InnoDB diagnostics, replacing some use of ib::info(). --- dbug/dbug.c | 35 +++++++++---------- include/my_dbug.h | 18 +++++++--- storage/innobase/buf/buf0buf.cc | 62 ++++++++++++++------------------- storage/innobase/fil/fil0fil.cc | 28 +++++++-------- storage/innobase/fsp/fsp0fsp.cc | 6 ++++ storage/innobase/row/row0upd.cc | 16 ++------- 6 files changed, 77 insertions(+), 88 deletions(-) diff --git a/dbug/dbug.c b/dbug/dbug.c index b2b298beb09..048e4803b1a 100644 --- a/dbug/dbug.c +++ b/dbug/dbug.c @@ -1213,7 +1213,7 @@ void _db_return_(struct _db_stack_frame_ *_stack_frame_) * * SYNOPSIS * - * VOID _db_pargs_(_line_, keyword) + * int _db_pargs_(_line_, keyword) * int _line_; * char *keyword; * @@ -1226,12 +1226,14 @@ void _db_return_(struct _db_stack_frame_ *_stack_frame_) * */ -void _db_pargs_(uint _line_, const char *keyword) +int _db_pargs_(uint _line_, const char *keyword) { CODE_STATE *cs; - get_code_state_or_return; + get_code_state_or_return 0; cs->u_line= _line_; cs->u_keyword= keyword; + + return DEBUGGING && _db_keyword_(cs, cs->u_keyword, 0); } @@ -1265,27 +1267,24 @@ void _db_doprnt_(const char *format,...) { va_list args; CODE_STATE *cs; + int save_errno; + get_code_state_or_return; va_start(args,format); if (!cs->locked) pthread_mutex_lock(&THR_LOCK_dbug); - if (_db_keyword_(cs, cs->u_keyword, 0)) - { - int save_errno=errno; - DoPrefix(cs, cs->u_line); - if (TRACING) - Indent(cs, cs->level + 1); - else - (void) fprintf(cs->stack->out_file->file, "%s: ", cs->func); - (void) fprintf(cs->stack->out_file->file, "%s: ", cs->u_keyword); - DbugVfprintf(cs->stack->out_file->file, format, args); - DbugFlush(cs); - errno=save_errno; - } - else if (!cs->locked) - pthread_mutex_unlock(&THR_LOCK_dbug); + save_errno=errno; + DoPrefix(cs, cs->u_line); + if (TRACING) + Indent(cs, cs->level + 1); + else + (void) fprintf(cs->stack->out_file->file, "%s: ", cs->func); + (void) fprintf(cs->stack->out_file->file, "%s: ", cs->u_keyword); + DbugVfprintf(cs->stack->out_file->file, format, args); + DbugFlush(cs); + errno=save_errno; va_end(args); } diff --git a/include/my_dbug.h b/include/my_dbug.h index d56033ab025..ba9e8a025d7 100644 --- a/include/my_dbug.h +++ b/include/my_dbug.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. - Copyright (C) 2000-2011 Monty Program Ab + Copyright (C) 2000, 2017, MariaDB Corporation Ab 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 @@ -50,7 +50,7 @@ extern void _db_set_init_(const char *control); extern void _db_enter_(const char *_func_, const char *_file_, uint _line_, struct _db_stack_frame_ *_stack_frame_); extern void _db_return_(struct _db_stack_frame_ *_stack_frame_); -extern void _db_pargs_(uint _line_,const char *keyword); +extern int _db_pargs_(uint _line_,const char *keyword); extern void _db_doprnt_(const char *format,...) ATTRIBUTE_FORMAT(printf, 1, 2); extern void _db_dump_(uint _line_,const char *keyword, @@ -91,7 +91,7 @@ extern const char* _db_get_func_(void); #define DBUG_EVALUATE_IF(keyword,a1,a2) \ (_db_keyword_(0,(keyword), 1) ? (a1) : (a2)) #define DBUG_PRINT(keyword,arglist) \ - do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0) + do if (_db_pargs_(__LINE__,keyword)) _db_doprnt_ arglist; while(0) #define DBUG_PUSH(a1) _db_push_ (a1) #define DBUG_POP() _db_pop_ () #define DBUG_SET(a1) _db_set_ (a1) @@ -193,8 +193,18 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); #define DBUG_SYNC_POINT(lock_name,lock_timeout) #endif /* EXTRA_DEBUG */ -#ifdef __cplusplus +#ifdef __cplusplus } +# ifdef DBUG_OFF +# define DBUG_LOG(keyword, v) do {} while (0) +# else +# include +# define DBUG_LOG(keyword, v) do { \ + if (_db_pargs_(__LINE__, keyword)) { \ + std::ostringstream _db_s; _db_s << v; \ + _db_doprnt_("%s", _db_s.str().c_str()); \ + }} while (0) +# endif #endif #endif /* _my_dbug_h */ diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index eeb851462b5..2f4edfb5014 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -128,11 +128,6 @@ struct set_numa_interleave_t #define NUMA_MEMPOLICY_INTERLEAVE_IN_SCOPE #endif /* HAVE_LIBNUMA */ -/* Enable this for checksum error messages. */ -//#ifdef UNIV_DEBUG -//#define UNIV_DEBUG_LEVEL2 1 -//#endif - /* IMPLEMENTATION OF THE BUFFER POOL ================================= @@ -661,12 +656,10 @@ buf_page_is_checksum_valid_crc32( } invalid: -#ifdef UNIV_DEBUG_LEVEL2 - ib::info() << "Page checksum crc32 not valid" + DBUG_LOG("checksum", "Page checksum crc32 not valid" << " field1 " << checksum_field1 << " field2 " << checksum_field2 - << " crc32 " << crc32; -#endif + << " crc32 " << crc32); return(false); } @@ -738,13 +731,13 @@ buf_page_is_checksum_valid_innodb( if (checksum_field2 != mach_read_from_4(read_buf + FIL_PAGE_LSN) && checksum_field2 != old_checksum) { -#ifdef UNIV_DEBUG_LEVEL2 - ib::info() << "Page checksum crc32 not valid" - << " field1 " << checksum_field1 - << " field2 " << checksum_field2 - << " crc32 " << buf_calc_page_old_checksum(read_buf) - << " lsn " << mach_read_from_4(read_buf + FIL_PAGE_LSN); -#endif + DBUG_LOG("checksum", + "Page checksum crc32 not valid" + << " field1 " << checksum_field1 + << " field2 " << checksum_field2 + << " crc32 " << buf_calc_page_old_checksum(read_buf) + << " lsn " << mach_read_from_4( + read_buf + FIL_PAGE_LSN)); return(false); } @@ -754,13 +747,13 @@ buf_page_is_checksum_valid_innodb( (always equal to 0), to FIL_PAGE_SPACE_OR_CHKSUM */ if (checksum_field1 != 0 && checksum_field1 != new_checksum) { -#ifdef UNIV_DEBUG_LEVEL2 - ib::info() << "Page checksum crc32 not valid" - << " field1 " << checksum_field1 - << " field2 " << checksum_field2 - << " crc32 " << buf_calc_page_new_checksum(read_buf) - << " lsn " << mach_read_from_4(read_buf + FIL_PAGE_LSN); -#endif + DBUG_LOG("checksum", + "Page checksum crc32 not valid" + << " field1 " << checksum_field1 + << " field2 " << checksum_field2 + << " crc32 " << buf_calc_page_new_checksum(read_buf) + << " lsn " << mach_read_from_4( + read_buf + FIL_PAGE_LSN)); return(false); } @@ -790,13 +783,16 @@ buf_page_is_checksum_valid_none( #endif /* UNIV_INNOCHECKSUM */ ) { -#ifdef UNIV_DEBUG_LEVEL2 - if (!(checksum_field1 == checksum_field2 || checksum_field1 == BUF_NO_CHECKSUM_MAGIC)) { - ib::info() << "Page checksum crc32 not valid" - << " field1 " << checksum_field1 - << " field2 " << checksum_field2 - << " crc32 " << BUF_NO_CHECKSUM_MAGIC - << " lsn " << mach_read_from_4(read_buf + FIL_PAGE_LSN); +#ifndef DBUG_OFF + if (checksum_field1 != checksum_field2 + && checksum_field1 != BUF_NO_CHECKSUM_MAGIC) { + DBUG_LOG("checksum", + "Page checksum crc32 not valid" + << " field1 " << checksum_field1 + << " field2 " << checksum_field2 + << " crc32 " << BUF_NO_CHECKSUM_MAGIC + << " lsn " << mach_read_from_4(read_buf + + FIL_PAGE_LSN)); } #endif @@ -3467,12 +3463,6 @@ page_found: buf_pool->watch[]. However, it is not in the critical code path as this function will be called only by the purge thread. */ -/* Enable this for checksum error messages. Currently on by -default on UNIV_DEBUG for encryption bugs. */ -#ifdef UNIV_DEBUG -#define UNIV_DEBUG_LEVEL2 1 -#endif - /* To obey latching order first release the hash_lock. */ rw_lock_x_unlock(*hash_lock); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 43b31002306..19318358dc4 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1691,12 +1691,17 @@ fil_space_create( space->page_0_crypt_read = true; } -#ifdef UNIV_DEBUG - ib::info() << "Created tablespace for space " << space->id - << " name " << space->name - << " key_id " << (space->crypt_data ? space->crypt_data->key_id : 0) - << " encryption " << (space->crypt_data ? space->crypt_data->encryption : 0); -#endif + DBUG_LOG("tablespace", + "Tablespace for space " << id << " name " << name + << create_table ? " created" : " opened"); + if (crypt_data) { + DBUG_LOG("crypt", + "Tablespace " << id << " name " << name + << " encryption " << crypt_data->encryption + << " key id " << crypt_data->key_id + << ":" << fil_crypt_get_mode(crypt_data) + << " " << fil_crypt_get_type(crypt_data)); + } space->encryption_type = Encryption::NONE; @@ -1718,15 +1723,6 @@ fil_space_create( fil_system->max_assigned_id = id; } -#ifdef UNIV_DEBUG - if (crypt_data) { - /* If table could be encrypted print info */ - ib::info() << "Tablespace ID " << id << " name " << space->name - << ":" << fil_crypt_get_mode(crypt_data) - << " " << fil_crypt_get_type(crypt_data); - } -#endif - mutex_exit(&fil_system->mutex); return(space); @@ -7735,4 +7731,4 @@ fil_system_exit(void) { ut_ad(mutex_own(&fil_system->mutex)); mutex_exit(&fil_system->mutex); -} +} \ No newline at end of file diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index fe272accd5a..54070c12406 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -3730,11 +3730,15 @@ fseg_free_page( the adaptive hash index */ mtr_t* mtr) /*!< in/out: mini-transaction */ { + DBUG_ENTER("fseg_free_page"); fseg_inode_t* seg_inode; buf_block_t* iblock; const fil_space_t* space = mtr_x_lock_space(space_id, mtr); const page_size_t page_size(space->flags); + DBUG_LOG("fseg_free_page", "space_id: " << space_id + << ", page_no: " << page); + seg_inode = fseg_inode_get(seg_header, space_id, page_size, mtr, &iblock); fil_block_check_type(iblock, FIL_PAGE_INODE, mtr); @@ -3744,6 +3748,8 @@ fseg_free_page( fseg_free_page_low(seg_inode, page_id, page_size, ahi, mtr); ut_d(buf_page_set_file_page_was_freed(page_id)); + + DBUG_VOID_RETURN; } /**********************************************************************//** diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 3f7c795230a..048f75e413f 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -3473,26 +3473,14 @@ void upd_node_t::dbug_trace() for (upd_cascade_t::const_iterator i = cascade_upd_nodes->begin(); i != cascade_upd_nodes->end(); ++i) { - - const upd_node_t* update_node = *i; - ib::info() << "cascade_upd_nodes: Cascade to table: " << - update_node->table->name; - /* JAN: TODO: MySQL 5.7 DBUG_LOG("upd_node_t", "cascade_upd_nodes: Cascade to table: " - << update_node->table->name); - */ + << (*i)->table->name); } for (upd_cascade_t::const_iterator j = new_upd_nodes->begin(); j != new_upd_nodes->end(); ++j) { - - const upd_node_t* update_node = *j; - ib::info() << "cascade_upd_nodes: Cascade to table: " << - update_node->table->name; - /* JAN: TODO: MySQL 5.7 DBUG_LOG("upd_node_t", "new_upd_nodes: Cascade to table: " - << update_node->table->name); - */ + << (*j)->table->name); } DBUG_VOID_RETURN; From a8ac6dc5065a82b11b3f1a699be87aabc95d7a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 5 Jan 2017 11:49:00 +0200 Subject: [PATCH 025/167] Fix InnoDB compilation warnings. Most of them are trivial, except for the thread_sync_t refactoring. We must not invoke memset() on non-POD objects. mtflush_work_initialized: Remove. Refer to mtflush_ctx != NULL instead. thread_sync_t::thread_sync_t(): Refactored from buf_mtflu_handler_init(). thread_sync_t::~thread_sync_t(): Refactored from buf_mtflu_io_thread_exit(). --- storage/innobase/buf/buf0lru.cc | 4 - storage/innobase/buf/buf0mtflu.cc | 148 +++++++++++++---------------- storage/innobase/fil/fil0fil.cc | 4 +- storage/innobase/row/row0ftsort.cc | 1 - 4 files changed, 66 insertions(+), 91 deletions(-) diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 6a57e6746ff..0169a63e972 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -79,10 +79,6 @@ static const ulint BUF_LRU_DROP_SEARCH_SIZE = 1024; during LRU eviction. */ static const ulint BUF_LRU_SEARCH_SCAN_THRESHOLD = 100; -/** We scan these many blocks when looking for a clean page to evict -during LRU eviction. */ -#define BUF_LRU_SEARCH_SCAN_THRESHOLD 100 - /** If we switch on the InnoDB monitor because there are too few available frames in the buffer pool, we set this to TRUE */ static bool buf_lru_switched_on_innodb_mon = false; diff --git a/storage/innobase/buf/buf0mtflu.cc b/storage/innobase/buf/buf0mtflu.cc index 117de5cc948..7c15b12950e 100644 --- a/storage/innobase/buf/buf0mtflu.cc +++ b/storage/innobase/buf/buf0mtflu.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (C) 2013, 2014, Fusion-io. All Rights Reserved. -Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -118,15 +118,65 @@ typedef struct wrk_itm mem_heap_t *rheap; } wrk_t; -typedef struct thread_data +struct thread_data_t { os_thread_id_t wthread_id; /*!< Identifier */ wthr_status_t wt_status; /*!< Worker thread status */ -} thread_data_t; +}; -/* Thread syncronization data */ -typedef struct thread_sync +/** Flush dirty pages when multi-threaded flush is used. */ +extern "C" UNIV_INTERN +os_thread_ret_t +DECLARE_THREAD(mtflush_io_thread)(void* arg); + +/** Thread syncronization data */ +struct thread_sync_t { + /** Constructor */ + thread_sync_t(ulint n_threads, mem_heap_t* wheap, mem_heap_t* rheap) : + thread_global_mtx(), n_threads(n_threads), + wq(ib_wqueue_create()), + wr_cq(ib_wqueue_create()), + rd_cq(ib_wqueue_create()), + wheap(wheap), rheap(rheap), gwt_status(), + thread_data(static_cast( + mem_heap_zalloc(wheap, n_threads + * sizeof *thread_data))) + { + ut_a(wq); + ut_a(wr_cq); + ut_a(rd_cq); + ut_a(thread_data); + + mutex_create(LATCH_ID_MTFLUSH_THREAD_MUTEX, + &thread_global_mtx); + + /* Create threads for page-compression-flush */ + for(ulint i = 0; i < n_threads; i++) { + thread_data[i].wt_status = WTHR_INITIALIZED; + os_thread_create(mtflush_io_thread, this, + &thread_data[i].wthread_id); + } + } + + /** Destructor */ + ~thread_sync_t() + { + ut_a(ib_wqueue_is_empty(wq)); + ut_a(ib_wqueue_is_empty(wr_cq)); + ut_a(ib_wqueue_is_empty(rd_cq)); + + /* Free all queues */ + ib_wqueue_free(wq); + ib_wqueue_free(wr_cq); + ib_wqueue_free(rd_cq); + + mutex_free(&thread_global_mtx); + + mem_heap_free(rheap); + mem_heap_free(wheap); + } + /* Global variables used by all threads */ ib_mutex_t thread_global_mtx; /*!< Mutex used protecting below variables */ @@ -142,23 +192,11 @@ typedef struct thread_sync /* Variables used by only one thread at a time */ thread_data_t* thread_data; /*!< Thread specific data */ +}; -} thread_sync_t; - -static int mtflush_work_initialized = -1; -static thread_sync_t* mtflush_ctx=NULL; +static thread_sync_t* mtflush_ctx; static ib_mutex_t mtflush_mtx; -/******************************************************************//** -Set multi-threaded flush work initialized. */ -static inline -void -buf_mtflu_work_init(void) -/*=====================*/ -{ - mtflush_work_initialized = 1; -} - /******************************************************************//** Return true if multi-threaded flush is initialized @return true if initialized */ @@ -166,7 +204,7 @@ bool buf_mtflu_init_done(void) /*=====================*/ { - return(mtflush_work_initialized == 1); + return(mtflush_ctx != NULL); } /******************************************************************//** @@ -307,15 +345,10 @@ mtflush_service_io( } } -/******************************************************************//** -Thead used to flush dirty pages when multi-threaded flush is -used. -@return a dummy parameter*/ +/** Flush dirty pages when multi-threaded flush is used. */ extern "C" UNIV_INTERN os_thread_ret_t -DECLARE_THREAD(mtflush_io_thread)( -/*==============================*/ - void * arg) +DECLARE_THREAD(mtflush_io_thread)(void* arg) { thread_sync_t *mtflush_io = ((thread_sync_t *)arg); thread_data_t *this_thread_data = NULL; @@ -438,29 +471,10 @@ buf_mtflu_io_thread_exit(void) ib_wqueue_nowait(mtflush_io->wq); } - mutex_enter(&mtflush_mtx); + mtflush_ctx->~thread_sync_t(); + mtflush_ctx = NULL; - ut_a(ib_wqueue_is_empty(mtflush_io->wq)); - ut_a(ib_wqueue_is_empty(mtflush_io->wr_cq)); - ut_a(ib_wqueue_is_empty(mtflush_io->rd_cq)); - - /* Free all queues */ - ib_wqueue_free(mtflush_io->wq); - ib_wqueue_free(mtflush_io->wr_cq); - ib_wqueue_free(mtflush_io->rd_cq); - - mtflush_io->wq = NULL; - mtflush_io->wr_cq = NULL; - mtflush_io->rd_cq = NULL; - mtflush_work_initialized = 0; - - /* Free heap */ - mem_heap_free(mtflush_io->wheap); - mem_heap_free(mtflush_io->rheap); - - mutex_exit(&mtflush_mtx); mutex_free(&mtflush_mtx); - mutex_free(&mtflush_io->thread_global_mtx); } /******************************************************************//** @@ -472,7 +486,6 @@ buf_mtflu_handler_init( ulint n_threads, /*!< in: Number of threads to create */ ulint wrk_cnt) /*!< in: Number of work items */ { - ulint i; mem_heap_t* mtflush_heap; mem_heap_t* mtflush_heap2; @@ -484,43 +497,10 @@ buf_mtflu_handler_init( mtflush_heap2 = mem_heap_create(0); ut_a(mtflush_heap2 != NULL); - mtflush_ctx = (thread_sync_t *)mem_heap_alloc(mtflush_heap, - sizeof(thread_sync_t)); - memset(mtflush_ctx, 0, sizeof(thread_sync_t)); - ut_a(mtflush_ctx != NULL); - mtflush_ctx->thread_data = (thread_data_t*)mem_heap_alloc( - mtflush_heap, sizeof(thread_data_t) * n_threads); - ut_a(mtflush_ctx->thread_data); - memset(mtflush_ctx->thread_data, 0, sizeof(thread_data_t) * n_threads); - - mtflush_ctx->n_threads = n_threads; - mtflush_ctx->wq = ib_wqueue_create(); - ut_a(mtflush_ctx->wq); - mtflush_ctx->wr_cq = ib_wqueue_create(); - ut_a(mtflush_ctx->wr_cq); - mtflush_ctx->rd_cq = ib_wqueue_create(); - ut_a(mtflush_ctx->rd_cq); - mtflush_ctx->wheap = mtflush_heap; - mtflush_ctx->rheap = mtflush_heap2; - - mutex_create(LATCH_ID_MTFLUSH_THREAD_MUTEX, &mtflush_ctx->thread_global_mtx); mutex_create(LATCH_ID_MTFLUSH_MUTEX, &mtflush_mtx); - /* Create threads for page-compression-flush */ - for(i=0; i < n_threads; i++) { - os_thread_id_t new_thread_id; - - mtflush_ctx->thread_data[i].wt_status = WTHR_INITIALIZED; - - os_thread_create( - mtflush_io_thread, - ((void *) mtflush_ctx), - &new_thread_id); - - mtflush_ctx->thread_data[i].wthread_id = new_thread_id; - } - - buf_mtflu_work_init(); + mtflush_ctx = new (mem_heap_zalloc(mtflush_heap, sizeof *mtflush_ctx)) + thread_sync_t(n_threads, mtflush_heap, mtflush_heap2); return((void *)mtflush_ctx); } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 19318358dc4..a2865141a4d 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1693,7 +1693,7 @@ fil_space_create( DBUG_LOG("tablespace", "Tablespace for space " << id << " name " << name - << create_table ? " created" : " opened"); + << (create_table ? " created" : " opened")); if (crypt_data) { DBUG_LOG("crypt", "Tablespace " << id << " name " << name @@ -7731,4 +7731,4 @@ fil_system_exit(void) { ut_ad(mutex_own(&fil_system->mutex)); mutex_exit(&fil_system->mutex); -} \ No newline at end of file +} diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 3f2255d4644..0d216d584d7 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -524,7 +524,6 @@ row_merge_fts_doc_tokenize( while (t_ctx->processed_len < doc->text.f_len) { ulint idx = 0; ib_uint32_t position; - ulint offset = 0; ulint cur_len; doc_id_t write_doc_id; row_fts_token_t* fts_token = NULL; From 30f27b0de040b0199d0c3b46a539b638970fa0f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 5 Jan 2017 11:54:10 +0200 Subject: [PATCH 026/167] Post-merge fix for MDEV-11638. logs_empty_and_mark_files_at_shutdown(): Wait for the log_scrub_thread to exit. --- storage/innobase/log/log0log.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 4a10379716b..cf7825bd542 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2230,7 +2230,7 @@ wait_suspend_loop: const ulint n_flush = log_sys->n_pending_flushes; log_mutex_exit(); - if (n_write != 0 || n_flush != 0) { + if (log_scrub_thread_active || n_write || n_flush) { if (srv_print_verbose_log && count > 600) { ib::info() << "Pending checkpoint_writes: " << n_write << ". Pending log flush writes: " << n_flush; From fb5ee7d6d043b01fabc59f09d70d532e843add60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 5 Jan 2017 19:01:14 +0200 Subject: [PATCH 027/167] Plug a memory leak in buf_dblwr_process(). --- storage/innobase/buf/buf0dblwr.cc | 3 ++- storage/xtradb/buf/buf0dblwr.cc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index cc5fe52f80a..1cf856a731f 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -636,6 +636,7 @@ buf_dblwr_process() } } + ut_free(unaligned_read_buf); fil_flush_file_spaces(FIL_TABLESPACE); { diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc index 62ed17296f5..7f6b6caee9d 100644 --- a/storage/xtradb/buf/buf0dblwr.cc +++ b/storage/xtradb/buf/buf0dblwr.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -635,6 +635,7 @@ buf_dblwr_process() } } + ut_free(unaligned_read_buf); fil_flush_file_spaces(FIL_TABLESPACE); { From f0c19b6a57b699d113e3ae4a67920924bbecae45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 5 Jan 2017 20:13:34 +0200 Subject: [PATCH 028/167] MDEV-11730 Memory leak in innodb.innodb_corrupt_bit Memory was leaked when ALTER TABLE is attempted on a table that contains corrupted indexes. The memory leak was reported by AddressSanitizer for the test innodb.innodb_corrupt_bit. The leak was introduced into MariaDB Server 10.0.26, 10.1.15, 10.2.1 by the following: commit c081c978a2c83b9dc9efa84414cf40232460987d Merge: 1d21b221552 a482e76e65a Author: Sergei Golubchik Date: Tue Jun 21 14:11:02 2016 +0200 Merge branch '5.5' into bb-10.0 --- storage/innobase/handler/handler0alter.cc | 2 +- storage/xtradb/handler/handler0alter.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 31648798776..89a58d83a60 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -3890,7 +3890,7 @@ check_if_can_drop_indexes: index->name, TRUE); my_error(ER_INDEX_CORRUPT, MYF(0), index_name); - DBUG_RETURN(true); + goto err_exit; } } } diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index c5ac48dc4e3..7c17e9307ef 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -3904,7 +3904,7 @@ check_if_can_drop_indexes: index->name, TRUE); my_error(ER_INDEX_CORRUPT, MYF(0), index_name); - DBUG_RETURN(true); + goto err_exit; } } } From b2b6cf492e3c7fd99a2d0b6f152516efd28dadf4 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Wed, 4 Jan 2017 19:11:13 +0200 Subject: [PATCH 029/167] MDEV-10988 Sphinx test suite refuses to run silently Add diagnostics output if any Sphinx components aren't found --- storage/sphinx/mysql-test/sphinx/suite.pm | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/storage/sphinx/mysql-test/sphinx/suite.pm b/storage/sphinx/mysql-test/sphinx/suite.pm index e4c3c1b9f74..fc127ffd6c0 100644 --- a/storage/sphinx/mysql-test/sphinx/suite.pm +++ b/storage/sphinx/mysql-test/sphinx/suite.pm @@ -16,13 +16,26 @@ sub locate_sphinx_binary { for (@list) { return $_ if -x $_; } } -# Look for Sphinx binaries. +# Look for Sphinx binaries my $exe_sphinx_indexer = &locate_sphinx_binary('indexer'); + +unless ($exe_sphinx_indexer) { + mtr_report("Sphinx 'indexer' binary not found, sphinx suite will be skipped"); + return "No Sphinx"; +} my $exe_sphinx_searchd = &locate_sphinx_binary('searchd'); -return "No Sphinx" unless $exe_sphinx_indexer and $exe_sphinx_searchd; -return "No SphinxSE" unless $ENV{HA_SPHINX_SO} or - $::mysqld_variables{'sphinx'} eq "ON"; +unless ($exe_sphinx_searchd) { + mtr_report("Sphinx 'searchd' binary not found, sphinx suite will be skipped"); + return "No Sphinx"; +} + +# Check for Sphinx engine + +unless ($ENV{HA_SPHINX_SO} or $::mysqld_variables{'sphinx'} eq "ON") { + mtr_report("Sphinx engine not found, sphinx suite will be skipped"); + return "No SphinxSE"; +} { local $_ = `"$exe_sphinx_searchd" --help`; From 670b85804ca6d3b0e640a7ddbb5b6e494bec7c2b Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 1 Jan 2017 15:36:56 +0200 Subject: [PATCH 030/167] Replication tests fail on valgrind due to waiting-related timeouts MTR raises default wait_for_pos_timeout from 300 to 1500 when tests are run with valgrind. The same needs to be done for other replication-related waits. The change should fix one of failures mentioned in MDEV-10653 (rpl.rpl_parallel fails in buildbot with timeout), the one on the valgrind builder; but not all of them --- mysql-test/include/sync_slave_sql_with_io.inc | 4 ++++ mysql-test/include/sync_with_master_gtid.inc | 4 ++++ mysql-test/include/wait_for_slave_param.inc | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/mysql-test/include/sync_slave_sql_with_io.inc b/mysql-test/include/sync_slave_sql_with_io.inc index 8048f7a177c..9efede9a61f 100644 --- a/mysql-test/include/sync_slave_sql_with_io.inc +++ b/mysql-test/include/sync_slave_sql_with_io.inc @@ -26,6 +26,10 @@ let $_slave_timeout= $slave_timeout; if (!$_slave_timeout) { let $_slave_timeout= 300; + if ($VALGRIND_TEST) + { + let $_slave_timeout= 1500; + } } --let $_master_log_file= query_get_value(SHOW SLAVE STATUS, Master_Log_File, 1) diff --git a/mysql-test/include/sync_with_master_gtid.inc b/mysql-test/include/sync_with_master_gtid.inc index 97ada8eea29..777711b979c 100644 --- a/mysql-test/include/sync_with_master_gtid.inc +++ b/mysql-test/include/sync_with_master_gtid.inc @@ -34,6 +34,10 @@ let $_slave_timeout= $slave_timeout; if (!$_slave_timeout) { let $_slave_timeout= 120; + if ($VALGRIND_TEST) + { + let $_slave_timeout= 1200; + } } --let $_result= `SELECT master_gtid_wait('$master_pos', $_slave_timeout)` diff --git a/mysql-test/include/wait_for_slave_param.inc b/mysql-test/include/wait_for_slave_param.inc index d3f7ec56614..25020d46ed9 100644 --- a/mysql-test/include/wait_for_slave_param.inc +++ b/mysql-test/include/wait_for_slave_param.inc @@ -50,6 +50,10 @@ let $_slave_timeout= $slave_timeout; if (!$_slave_timeout) { let $_slave_timeout= 300; + if ($VALGRIND_TEST) + { + let $_slave_timeout= 1500; + } } if ($slave_error_param == '') From 43378f367c5c01ebc214919006e2072fb2356724 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 25 Jul 2016 13:07:50 +0200 Subject: [PATCH 031/167] MDEV-10271: Stopped SQL slave thread doesn't print a message to error log like IO thread does Make the slave SQL thread always output to the error log the message "Slave SQL thread exiting, replication stopped in ..." whenever it previously outputted "Slave SQL thread initialized, starting replication ...". Before this patch, it was somewhat inconsistent in which cases the message would be output and in which not, depending on the exact time and cause of the condition that caused the SQL thread to stop. --- sql/slave.cc | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index 65bcdc48c6a..c4817ef4794 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4574,11 +4574,11 @@ pthread_handler_t handle_slave_sql(void *arg) { rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL, "Error initializing relay log position: %s", errmsg); - goto err; + goto err_before_start; } rli->reset_inuse_relaylog(); if (rli->alloc_inuse_relaylog(rli->group_relay_log_name)) - goto err; + goto err_before_start; strcpy(rli->future_event_master_log_name, rli->group_master_log_name); THD_CHECK_SENTRY(thd); @@ -4738,6 +4738,7 @@ log '%s' at position %s, relay log '%s' position: %s%s", RPL_LOG_NAME, } } + err: if (mi->using_parallel()) rli->parallel.wait_for_done(thd, rli); @@ -4757,15 +4758,7 @@ log '%s' at position %s, relay log '%s' position: %s%s", RPL_LOG_NAME, tmp.c_ptr_safe()); } - err: - - /* - Once again, in case we aborted with an error and skipped the first one. - (We want the first one to be before the printout of stop position to - get the correct position printed.) - */ - if (mi->using_parallel()) - rli->parallel.wait_for_done(thd, rli); + err_before_start: /* Some events set some playgrounds, which won't be cleared because thread From e4978d26b79120c58706e57fc66e4de1ec4b230c Mon Sep 17 00:00:00 2001 From: Dmitry Lenev Date: Mon, 25 Jul 2016 16:06:52 +0300 Subject: [PATCH 032/167] MDEV-9084 Calling a stored function from a nested select from temporary table causes unpredictable behavior Cherry-pick: f4a0af070ce49abae60040f6f32e1074309c27fb Author: Dmitry Lenev Date: Mon Jul 25 16:06:52 2016 +0300 Fix for bug #16672723 "CAN'T FIND TEMPORARY TABLE". Attempt to execute prepared CREATE TABLE SELECT statement which used temporary table in the subquery in FROM clause and stored function failed with unwarranted ER_NO_SUCH_TABLE error. The same happened when such statement was used in stored procedure and this procedure was re-executed. The problem occurred because execution of such prepared statement/its re-execution as part of stored procedure incorrectly set Query_table_list::query_tables_own_last marker, indicating the last table which is directly used by statement. As result temporary table used in the subquery was treated as indirectly used/belonging to prelocking list and was not pre-opened by open_temporary_tables() call before statement execution. Thus causing ER_NO_SUCH_TABLE errors since our code assumes that temporary tables need to be correctly pre-opened before statement execution. This problem became visible only in version 5.6 after patches related to bug 11746602/27480 "EXTEND CREATE TEMPORARY TABLES PRIVILEGE TO ALLOW TEMP TABLE OPERATIONS" since they have introduced pre-opening of temporary tables for statements. Incorrect setting of Query_table_list::query_tables_own_last happened in LEX::first_lists_tables_same() method which is called by CREATE TABLE SELECT implementation as part of LEX::unlink_first_table(), which temporary excludes table list element for table being created from the query table list before handling SELECT part. LEX::first_lists_tables_same() tries to ensure that global table list of the statement starts with the first table list element from the first statement select. To do this it moves such table list element to the head of the global table list. If this table happens to be last directly-used table for the statement, query_tables_own_last marker is pointing to it. Since this marker was not updated when table list element was moved we ended up with all tables except the first table separated by it as if they were not directly used by statement (i.e. belonged to prelocked tables list). This fix changes code of LEX::first_lists_tables_same() to update query_tables_own_last marker in cases when it points to the table being moved. It is set to the table which precedes table being moved in this case. --- mysql-test/r/sp-prelocking.result | 23 +++++++++++++++++++++++ mysql-test/t/sp-prelocking.test | 30 ++++++++++++++++++++++++++++++ sql/sql_lex.cc | 3 +++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result index 5b594e9ea55..eb47cc21f41 100644 --- a/mysql-test/r/sp-prelocking.result +++ b/mysql-test/r/sp-prelocking.result @@ -340,3 +340,26 @@ f1() DROP FUNCTION f1; DROP VIEW v1; DROP TABLE t1,t2; +# +# Bug #16672723 "CAN'T FIND TEMPORARY TABLE". +# +CREATE FUNCTION f1() RETURNS INT RETURN 1; +CREATE TEMPORARY TABLE tmp1(a INT); +PREPARE stmt1 FROM "CREATE TEMPORARY TABLE tmp2 AS SELECT b FROM (SELECT f1() AS b FROM tmp1) AS t"; +# The below statement failed before the fix. +EXECUTE stmt1; +DROP TEMPORARY TABLES tmp1, tmp2; +DEALLOCATE PREPARE stmt1; +DROP FUNCTION f1; +create procedure sp1() +begin +drop table if exists t1, t2; +create temporary table t1 select 1 v; +create table t2 (col varchar(45)) select distinct col from (select sf1() as col from t1) t; +end$$ +create function sf1() returns text return 'blah'; +call test.sp1(); +call test.sp1(); +drop procedure sp1; +drop function sf1; +drop table t2; diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index c1378d59196..38cbd5aa110 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -414,3 +414,33 @@ SELECT f1(); DROP FUNCTION f1; DROP VIEW v1; DROP TABLE t1,t2; + +--echo # +--echo # Bug #16672723 "CAN'T FIND TEMPORARY TABLE". +--echo # +CREATE FUNCTION f1() RETURNS INT RETURN 1; +CREATE TEMPORARY TABLE tmp1(a INT); +PREPARE stmt1 FROM "CREATE TEMPORARY TABLE tmp2 AS SELECT b FROM (SELECT f1() AS b FROM tmp1) AS t"; +--echo # The below statement failed before the fix. +EXECUTE stmt1; +DROP TEMPORARY TABLES tmp1, tmp2; +DEALLOCATE PREPARE stmt1; +DROP FUNCTION f1; + +# +# MDEV-9084 Calling a stored function from a nested select from temporary table causes unpredictable behavior +# +delimiter $$; +create procedure sp1() +begin + drop table if exists t1, t2; + create temporary table t1 select 1 v; + create table t2 (col varchar(45)) select distinct col from (select sf1() as col from t1) t; +end$$ +delimiter ;$$ +create function sf1() returns text return 'blah'; +call test.sp1(); +call test.sp1(); +drop procedure sp1; +drop function sf1; +drop table t2; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index d20c5ae78af..22489913ded 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3158,6 +3158,9 @@ void LEX::first_lists_tables_same() if (query_tables_last == &first_table->next_global) query_tables_last= first_table->prev_global; + if (query_tables_own_last == &first_table->next_global) + query_tables_own_last= first_table->prev_global; + if ((next= *first_table->prev_global= first_table->next_global)) next->prev_global= first_table->prev_global; /* include in new place */ From ac0b0efa14aa48c7229b5d6ce6b1ec3a3cf26eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 6 Jan 2017 14:42:28 +0200 Subject: [PATCH 033/167] Post-fix MDEV-11695 Define a reasonable upper limit for innodb_spin_wait_delay Adjust the tests. --- .../r/innodb_spin_wait_delay_basic.result | 46 ++++++++++++------- .../suite/sys_vars/r/sysvars_innodb.result | 2 +- .../t/innodb_spin_wait_delay_basic.test | 31 +++++-------- 3 files changed, 42 insertions(+), 37 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result b/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result index 621ef56f61f..88516a854fe 100644 --- a/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_spin_wait_delay_basic.result @@ -43,14 +43,40 @@ set global innodb_spin_wait_delay=0; select @@global.innodb_spin_wait_delay; @@global.innodb_spin_wait_delay 0 +set global innodb_spin_wait_delay=5000; +select @@global.innodb_spin_wait_delay; +@@global.innodb_spin_wait_delay +5000 set global innodb_spin_wait_delay=65535; +Warnings: +Warning 1292 Truncated incorrect innodb_spin_wait_delay value: '65535' select @@global.innodb_spin_wait_delay; @@global.innodb_spin_wait_delay -65535 +6000 set global innodb_spin_wait_delay=4294967295; +Warnings: +Warning 1292 Truncated incorrect innodb_spin_wait_delay value: '4294967295' select @@global.innodb_spin_wait_delay; @@global.innodb_spin_wait_delay -4294967295 +6000 +set @@global.innodb_spin_wait_delay = 4294967296; +Warnings: +Warning 1292 Truncated incorrect innodb_spin_wait_delay value: '4294967296' +select @@global.innodb_spin_wait_delay; +@@global.innodb_spin_wait_delay +6000 +set @@global.innodb_spin_wait_delay = 12345678901; +Warnings: +Warning 1292 Truncated incorrect innodb_spin_wait_delay value: '12345678901' +select @@global.innodb_spin_wait_delay; +@@global.innodb_spin_wait_delay +6000 +set @@global.innodb_spin_wait_delay = 18446744073709551615; +Warnings: +Warning 1292 Truncated incorrect innodb_spin_wait_delay value: '18446744073709551615' +select @@global.innodb_spin_wait_delay; +@@global.innodb_spin_wait_delay +6000 set global innodb_spin_wait_delay=1.1; ERROR 42000: Incorrect argument type to variable 'innodb_spin_wait_delay' set global innodb_spin_wait_delay=1e1; @@ -61,12 +87,12 @@ set global innodb_spin_wait_delay=' '; ERROR 42000: Incorrect argument type to variable 'innodb_spin_wait_delay' select @@global.innodb_spin_wait_delay; @@global.innodb_spin_wait_delay -4294967295 +6000 set global innodb_spin_wait_delay=" "; ERROR 42000: Incorrect argument type to variable 'innodb_spin_wait_delay' select @@global.innodb_spin_wait_delay; @@global.innodb_spin_wait_delay -4294967295 +6000 set global innodb_spin_wait_delay=-7; Warnings: Warning 1292 Truncated incorrect innodb_spin_wait_delay value: '-7' @@ -82,18 +108,6 @@ select @@global.innodb_spin_wait_delay; select * from information_schema.global_variables where variable_name='innodb_spin_wait_delay'; VARIABLE_NAME VARIABLE_VALUE INNODB_SPIN_WAIT_DELAY 0 -SET @@global.innodb_spin_wait_delay = 4294967296; -SELECT @@global.innodb_spin_wait_delay IN (4294967296,4294967295); -@@global.innodb_spin_wait_delay IN (4294967296,4294967295) -1 -SET @@global.innodb_spin_wait_delay = 12345678901; -SELECT @@global.innodb_spin_wait_delay IN (12345678901,4294967295); -@@global.innodb_spin_wait_delay IN (12345678901,4294967295) -1 -SET @@global.innodb_spin_wait_delay = 18446744073709551615; -SELECT @@global.innodb_spin_wait_delay IN (18446744073709551615,4294967295); -@@global.innodb_spin_wait_delay IN (18446744073709551615,4294967295) -1 SET @@global.innodb_spin_wait_delay = @start_global_value; SELECT @@global.innodb_spin_wait_delay; @@global.innodb_spin_wait_delay diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index ad6dcc1bb64..d02dea3dd2d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2199,7 +2199,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum delay between polling for a spin lock (6 by default) NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_MAX_VALUE 6000 NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO diff --git a/mysql-test/suite/sys_vars/t/innodb_spin_wait_delay_basic.test b/mysql-test/suite/sys_vars/t/innodb_spin_wait_delay_basic.test index ab0b38bb6ce..d144d24a58b 100644 --- a/mysql-test/suite/sys_vars/t/innodb_spin_wait_delay_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_spin_wait_delay_basic.test @@ -46,10 +46,21 @@ select @@global.innodb_spin_wait_delay; # set global innodb_spin_wait_delay=0; select @@global.innodb_spin_wait_delay; +set global innodb_spin_wait_delay=5000; +select @@global.innodb_spin_wait_delay; +# +# invalid values +# set global innodb_spin_wait_delay=65535; select @@global.innodb_spin_wait_delay; set global innodb_spin_wait_delay=4294967295; select @@global.innodb_spin_wait_delay; +set @@global.innodb_spin_wait_delay = 4294967296; +select @@global.innodb_spin_wait_delay; +set @@global.innodb_spin_wait_delay = 12345678901; +select @@global.innodb_spin_wait_delay; +set @@global.innodb_spin_wait_delay = 18446744073709551615; +select @@global.innodb_spin_wait_delay; # # incorrect types @@ -74,26 +85,6 @@ select @@global.innodb_spin_wait_delay; select * from information_schema.global_variables where variable_name='innodb_spin_wait_delay'; --enable_warnings -# -# Check for out of bounds -# - -# With a 64 bit mysqld:18446744073709551615,with a 32 bit mysqld: 4294967295 ---disable_warnings -SET @@global.innodb_spin_wait_delay = 4294967296; ---enable_warnings -SELECT @@global.innodb_spin_wait_delay IN (4294967296,4294967295); - ---disable_warnings -SET @@global.innodb_spin_wait_delay = 12345678901; ---enable_warnings -SELECT @@global.innodb_spin_wait_delay IN (12345678901,4294967295); - ---disable_warnings -SET @@global.innodb_spin_wait_delay = 18446744073709551615; ---enable_warnings -SELECT @@global.innodb_spin_wait_delay IN (18446744073709551615,4294967295); - # # cleanup # From bbd4844a43fc61f207421dcb46299c4dcdce2ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 6 Jan 2017 14:52:35 +0200 Subject: [PATCH 034/167] Suppress warnings of NUMA not working. --- mysql-test/suite/sys_vars/r/innodb_numa_interleave_basic.result | 1 + mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mysql-test/suite/sys_vars/r/innodb_numa_interleave_basic.result b/mysql-test/suite/sys_vars/r/innodb_numa_interleave_basic.result index 21ed16c1dab..58f3b4b3e38 100644 --- a/mysql-test/suite/sys_vars/r/innodb_numa_interleave_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_numa_interleave_basic.result @@ -1,3 +1,4 @@ +call mtr.add_suppression("InnoDB: Failed to set NUMA memory policy"); SELECT @@GLOBAL.innodb_numa_interleave; @@GLOBAL.innodb_numa_interleave 1 diff --git a/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test b/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test index de89784f7e4..fcbf766ac65 100644 --- a/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test +++ b/mysql-test/suite/sys_vars/t/innodb_numa_interleave_basic.test @@ -1,6 +1,8 @@ --source include/have_innodb.inc --source include/have_numa.inc +call mtr.add_suppression("InnoDB: Failed to set NUMA memory policy"); + SELECT @@GLOBAL.innodb_numa_interleave; --error ER_INCORRECT_GLOBAL_LOCAL_VAR From ae6eb7a0020eb4d51f97f924e5320325e5b63934 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 4 Jan 2017 23:04:37 +0100 Subject: [PATCH 035/167] MDEV-11088 Client plugins cannot be loaded by command line tools in default installation. Added plugin-dir to the [client] section of the generated my.ini, so that installed services (MSI or mysql_install_db.exe) would be able to find plugin directory. --- sql/CMakeLists.txt | 1 + sql/mysql_install_db.cc | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 88ec26eb6f6..652664fa438 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -387,6 +387,7 @@ IF(WIN32) ${CMAKE_CURRENT_BINARY_DIR}/mysql_bootstrap_sql.c COMPONENT Server ) + SET_TARGET_PROPERTIES(mysql_install_db PROPERTIES COMPILE_FLAGS -DINSTALL_PLUGINDIR=${INSTALL_PLUGINDIR}) TARGET_LINK_LIBRARIES(mysql_install_db mysys) ADD_LIBRARY(winservice STATIC winservice.c) diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index c39789f7c97..c23a20ebac9 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -233,6 +233,20 @@ static void get_basedir(char *basedir, int size, const char *mysqld_path) } } +#define STR(s) _STR(s) +#define _STR(s) #s + +static char *get_plugindir() +{ + static char plugin_dir[2*MAX_PATH]; + get_basedir(plugin_dir, sizeof(plugin_dir), mysqld_path); + strcat(plugin_dir, "/" STR(INSTALL_PLUGINDIR)); + + if (access(plugin_dir, 0) == 0) + return plugin_dir; + + return NULL; +} /** Allocate and initialize command line for mysqld --bootstrap. @@ -313,6 +327,10 @@ static int create_myini() fprintf(myini,"protocol=pipe\n"); else if (opt_port) fprintf(myini,"port=%d\n",opt_port); + + char *plugin_dir = get_plugindir(); + if (plugin_dir) + fprintf(myini, "plugin-dir=%s\n", plugin_dir); fclose(myini); return 0; } From 82b8741ad00e1ffdcbd0e2cf82f3ab31a7f3ce8b Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 4 Jan 2017 22:50:48 +0100 Subject: [PATCH 036/167] Windows : use meaningful DEFAULT_MYSQL_HOME - base directory for the default installation. It is now defined as "C:/Program Files/MariaDB ${MYSQL_BASE_VERSION}" which is where installer indeed puts it by default. It still does not cover every case -32bit installer on 64 bit Windows would put installation root under "C:/Program Files (x86)", but better than the path used previously C:/MariaDB${MYSQL_BASE_VERSION}, which was never correct. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0adbb85d431..b6ffedabd14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -303,7 +303,7 @@ ENDIF() # Set commonly used variables IF(WIN32) - SET(DEFAULT_MYSQL_HOME "C:/MariaDB${MYSQL_BASE_VERSION}") + SET(DEFAULT_MYSQL_HOME "C:/Program Files/MariaDB ${MYSQL_BASE_VERSION}") SET(SHAREDIR share) ELSE() SET(DEFAULT_MYSQL_HOME ${CMAKE_INSTALL_PREFIX}) From eaf6b053b83d2a46250834e8367477bd3d85d38f Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 4 Jan 2017 22:41:43 +0100 Subject: [PATCH 037/167] MDEV-11087 Search path for my.ini is wrong for default installation Add /data/my.ini to the search path - this my.ini location is used since MariaDB 5.2 --- mysys/my_default.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mysys/my_default.c b/mysys/my_default.c index 0f9b70ca326..03cfa973b2c 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -90,7 +90,7 @@ static my_bool defaults_already_read= FALSE; /* Which directories are searched for options (and in which order) */ -#define MAX_DEFAULT_DIRS 6 +#define MAX_DEFAULT_DIRS 7 #define DEFAULT_DIRS_SIZE (MAX_DEFAULT_DIRS + 1) /* Terminate with NULL */ static const char **default_directories = NULL; @@ -1219,7 +1219,12 @@ static const char **init_default_directories(MEM_ROOT *alloc) errors += add_directory(alloc, "C:/", dirs); if (my_get_module_parent(fname_buffer, sizeof(fname_buffer)) != NULL) + { errors += add_directory(alloc, fname_buffer, dirs); + + strncat(fname_buffer, "/data", sizeof(fname_buffer)); + errors += add_directory(alloc, fname_buffer, dirs); + } } #else From 384f4d1e36cf2ba8791b15c83ac601b98f3270c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 7 Jan 2017 15:27:59 +0200 Subject: [PATCH 038/167] Post-push fix for MDEV-11556: Make the debug variable UINT. Sometimes innodb_data_file_size_debug was reported as INT UNSIGNED instead of BIGINT UNSIGNED. Make it uint instead of ulong to get a more deterministic result. --- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/srv0srv.h | 2 +- storage/innobase/srv/srv0start.cc | 2 +- storage/xtradb/handler/ha_innodb.cc | 2 +- storage/xtradb/include/srv0srv.h | 2 +- storage/xtradb/srv/srv0start.cc | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 5274523e3a4..d3e8977c6bb 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -585,7 +585,7 @@ GLOBAL_VALUE 0 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT InnoDB system tablespace size to be set in recovery. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 625ae5f5d27..227018fd3b6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19691,7 +19691,7 @@ static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug, "but the each purges were not done yet.", NULL, NULL, FALSE); -static MYSQL_SYSVAR_ULONG(data_file_size_debug, +static MYSQL_SYSVAR_UINT(data_file_size_debug, srv_sys_space_size_debug, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "InnoDB system tablespace size to be set in recovery.", diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 1ba1e3ae9c6..f404668390f 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -525,7 +525,7 @@ extern my_bool srv_ibuf_disable_background_merge; #ifdef UNIV_DEBUG extern my_bool srv_purge_view_update_only_debug; -extern ulong srv_sys_space_size_debug; +extern uint srv_sys_space_size_debug; #endif /* UNIV_DEBUG */ #define SRV_SEMAPHORE_WAIT_EXTENSION 7200 diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index ffd97b61091..40154c11ce1 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -129,7 +129,7 @@ UNIV_INTERN ibool srv_was_started = FALSE; static ibool srv_start_has_been_called = FALSE; #ifdef UNIV_DEBUG /** InnoDB system tablespace to set during recovery */ -UNIV_INTERN ulong srv_sys_space_size_debug; +UNIV_INTERN uint srv_sys_space_size_debug; #endif /* UNIV_DEBUG */ /** At a shutdown this value climbs from SRV_SHUTDOWN_NONE to diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index a361ab17a7c..a3f1d9c3c85 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -21172,7 +21172,7 @@ static MYSQL_SYSVAR_BOOL(trx_purge_view_update_only_debug, "but the each purges were not done yet.", NULL, NULL, FALSE); -static MYSQL_SYSVAR_ULONG(data_file_size_debug, +static MYSQL_SYSVAR_UINT(data_file_size_debug, srv_sys_space_size_debug, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "InnoDB system tablespace size to be set in recovery.", diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index f3b6098a875..f65848fdf45 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -626,7 +626,7 @@ extern my_bool srv_ibuf_disable_background_merge; #ifdef UNIV_DEBUG extern my_bool srv_purge_view_update_only_debug; -extern ulong srv_sys_space_size_debug; +extern uint srv_sys_space_size_debug; #endif /* UNIV_DEBUG */ #define SRV_SEMAPHORE_WAIT_EXTENSION 7200 diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 31421c7a605..77cdfe1affb 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -132,7 +132,7 @@ UNIV_INTERN ibool srv_was_started = FALSE; static ibool srv_start_has_been_called = FALSE; #ifdef UNIV_DEBUG /** InnoDB system tablespace to set during recovery */ -UNIV_INTERN ulong srv_sys_space_size_debug; +UNIV_INTERN uint srv_sys_space_size_debug; #endif /* UNIV_DEBUG */ /** At a shutdown this value climbs from SRV_SHUTDOWN_NONE to From 8773a5e16199269be090cbed13ff892bac810cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 7 Jan 2017 15:36:08 +0200 Subject: [PATCH 039/167] Post-fix MDEV-11695 Define a reasonable upper limit for innodb_spin_wait_delay Change the parameter type from ulong to uint, so that 32-bit and 64-bit systems will report an identical result. --- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/srv0srv.h | 2 +- storage/innobase/include/ut0mutex.h | 4 ++-- storage/innobase/srv/srv0srv.cc | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 2365f36ee37..de2295859c3 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2196,7 +2196,7 @@ GLOBAL_VALUE 6 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Maximum delay between polling for a spin lock (6 by default) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 6000 diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f0e5edb5704..ae9363d1709 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -22611,7 +22611,7 @@ static MYSQL_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds, "Count of spin-loop rounds in InnoDB mutexes (30 by default)", NULL, NULL, 30L, 0L, ~0UL, 0); -static MYSQL_SYSVAR_ULONG(spin_wait_delay, srv_spin_wait_delay, +static MYSQL_SYSVAR_UINT(spin_wait_delay, srv_spin_wait_delay, PLUGIN_VAR_OPCMDARG, "Maximum delay between polling for a spin lock (6 by default)", NULL, NULL, 6, 0, 6000, 0); diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 1c546dc2a06..1e05c2c6e4a 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -522,7 +522,7 @@ extern my_bool srv_scrub_log; extern ulong srv_n_spin_wait_rounds; extern ulong srv_n_free_tickets_to_enter; extern ulong srv_thread_sleep_delay; -extern ulong srv_spin_wait_delay; +extern uint srv_spin_wait_delay; extern ibool srv_priority_boost; extern ulint srv_truncated_status_writes; diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h index e4ab671eece..197a34e6122 100644 --- a/storage/innobase/include/ut0mutex.h +++ b/storage/innobase/include/ut0mutex.h @@ -28,7 +28,7 @@ Created 2012-03-24 Sunny Bains. #ifndef ut0mutex_h #define ut0mutex_h -extern ulong srv_spin_wait_delay; +extern uint srv_spin_wait_delay; extern ulong srv_n_spin_wait_rounds; extern ulong srv_force_recovery_crash; @@ -75,7 +75,7 @@ typedef BlockSyncArrayMutex ib_bpmutex_t; #error "ib_mutex_t type is unknown" #endif /* MUTEX_FUTEX */ -extern ulong srv_spin_wait_delay; +extern uint srv_spin_wait_delay; extern ulong srv_n_spin_wait_rounds; #define mutex_create(I, M) mutex_init((M), (I), __FILE__, __LINE__) diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index ab9f52b6596..002477bc4e0 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -418,7 +418,7 @@ ulong srv_replication_delay = 0; /*-------------------------------------------*/ UNIV_INTERN ulong srv_n_spin_wait_rounds = 15; -ulong srv_spin_wait_delay = 6; +uint srv_spin_wait_delay; ibool srv_priority_boost = TRUE; static ulint srv_n_rows_inserted_old = 0; From eed319b6fb543849046c8009c38575455e173dc2 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 8 Jan 2017 17:51:36 +0200 Subject: [PATCH 040/167] MDEV-11317: `! is_set()' or `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' fails in Diagnostics_area::set_ok_status on CREATE OR REPLACE with ARCHIVE table Problem was with deleting non existing .frm file for a storage engine that doesn't have .frm files (yet) Fixed by not giving an error for non existing .frm files for storage engines that are using discovery Fixed also valgrind supression related to the given test case --- mysql-test/suite/archive/discover.result | 7 +++++++ mysql-test/suite/archive/discover.test | 10 ++++++++++ mysql-test/valgrind.supp | 15 ++++++++++++++- sql/sql_table.cc | 16 ++++++++++++++-- 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/archive/discover.result b/mysql-test/suite/archive/discover.result index e1ca9cb6a65..0619ca2051a 100644 --- a/mysql-test/suite/archive/discover.result +++ b/mysql-test/suite/archive/discover.result @@ -139,3 +139,10 @@ flush tables; create table t1 (a int) engine=archive; ERROR 42S01: Table 't1' already exists drop table t1; +CREATE OR REPLACE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY ) ENGINE = ARCHIVE; +CREATE OR REPLACE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY ) ENGINE = ARCHIVE; +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY ) ENGINE = ARCHIVE; +SELECT * FROM t1; +pk +DROP TABLE t1; diff --git a/mysql-test/suite/archive/discover.test b/mysql-test/suite/archive/discover.test index 20cb69efa00..4ab35cf1115 100644 --- a/mysql-test/suite/archive/discover.test +++ b/mysql-test/suite/archive/discover.test @@ -132,3 +132,13 @@ flush tables; create table t1 (a int) engine=archive; drop table t1; +# +# MDEV-11317: Error in deleting non existing .frm for tables with disocvery +# + +CREATE OR REPLACE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY ) ENGINE = ARCHIVE; +CREATE OR REPLACE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY ) ENGINE = ARCHIVE; +DROP TABLE t1; +CREATE OR REPLACE TABLE t1 ( pk INT AUTO_INCREMENT PRIMARY KEY ) ENGINE = ARCHIVE; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 77f17cf07ec..a7d7f2ee67a 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -353,10 +353,23 @@ Memcheck:Leak fun:memalign ... - fun:call_init + fun:call_init* fun:_dl_init } +# This one is on OpenSuse 10.3 with gcc 5.4 +{ + memory "loss" from _dl_init 2 + Memcheck:Leak + fun:malloc + fun:pool + ... + fun:call_init* + fun:_dl_init +} + + + # # dlclose can allocate memory for error message, the memory will be # freed by dlerror or other dl* function. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 62dff1b5928..8569771d5f1 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2497,7 +2497,19 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, int frm_delete_error, trigger_drop_error= 0; /* Delete the table definition file */ strmov(end,reg_ext); - frm_delete_error= mysql_file_delete(key_file_frm, path, MYF(MY_WME)); + if (table_type && table_type != view_pseudo_hton && + table_type->discover_table) + { + /* + Table type is using discovery and may not need a .frm file. + Delete it silently if it exists + */ + (void) mysql_file_delete(key_file_frm, path, MYF(0)); + frm_delete_error= 0; + } + else + frm_delete_error= mysql_file_delete(key_file_frm, path, + MYF(MY_WME)); if (frm_delete_error) frm_delete_error= my_errno; else @@ -2513,7 +2525,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, else if (frm_delete_error && if_exists) thd->clear_error(); } - non_tmp_error= error ? TRUE : non_tmp_error; + non_tmp_error|= MY_TEST(error); } if (error) { From 59ea6456c31e47dd0a2f65c28f6fb97d09f6ee7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 9 Jan 2017 09:12:32 +0200 Subject: [PATCH 041/167] Minor cleanup of innodb.innodb-change-buffer-recovery This should be a non-functional change. I was unable to repeat MDEV-11626 innodb.innodb-change-buffer-recovery fails for xtradb and cannot determine the reason for the failure without having access to the files. The repeatability of MDEV-11626 should not be affected by these changes. --- .../r/innodb-change-buffer-recovery.result | 2 +- .../t/innodb-change-buffer-recovery.test | 26 +++++++------------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result b/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result index 96d2a3d462c..5b95742d0e8 100644 --- a/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result +++ b/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result @@ -8,7 +8,7 @@ a INT AUTO_INCREMENT PRIMARY KEY, b CHAR(1), c INT, INDEX(b)) -ENGINE=InnoDB; +ENGINE=InnoDB STATS_PERSISTENT=0; INSERT INTO t1 VALUES(0,'x',1); INSERT INTO t1 SELECT 0,b,c FROM t1; INSERT INTO t1 SELECT 0,b,c FROM t1; diff --git a/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test b/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test index 79f7999d115..18d7aa3be58 100644 --- a/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test +++ b/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test @@ -1,8 +1,3 @@ -if (`select plugin_auth_version < "5.6.17" from information_schema.plugins where plugin_name='innodb'`) -{ - --skip Not fixed in InnoDB before 5.6.17 -} - --echo # --echo # Bug#69122 - INNODB DOESN'T REDO-LOG INSERT BUFFER MERGE --echo # OPERATION IF IT IS DONE IN-PLACE @@ -14,8 +9,9 @@ if (`select plugin_auth_version < "5.6.17" from information_schema.plugins where --source include/not_embedded.inc # DBUG_SUICIDE() hangs under valgrind --source include/not_valgrind.inc -# No windows, need perl ---source include/not_windows.inc + +--let $_server_id= `SELECT @@server_id` +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect # The flag innodb_change_buffering_debug is only available in debug builds. # It instructs InnoDB to try to evict pages from the buffer pool when @@ -29,7 +25,7 @@ CREATE TABLE t1( b CHAR(1), c INT, INDEX(b)) -ENGINE=InnoDB; +ENGINE=InnoDB STATS_PERSISTENT=0; # Create enough rows for the table, so that the change buffer will be # used for modifying the secondary index page. There must be multiple @@ -54,27 +50,23 @@ BEGIN; SELECT b FROM t1 LIMIT 3; connect (con1,localhost,root,,); -connection con1; BEGIN; DELETE FROM t1 WHERE a=1; # This should be buffered, if innodb_change_buffering_debug = 1 is in effect. INSERT INTO t1 VALUES(1,'X',1); SET DEBUG_DBUG='+d,crash_after_log_ibuf_upd_inplace'; ---exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect + +--exec echo "wait" > $_expect_file_name --error 2013 # This should force a change buffer merge SELECT b FROM t1 LIMIT 3; +disconnect con1; +connection default; let SEARCH_PATTERN=Wrote log record for ibuf update in place operation; --source include/search_pattern_in_file.inc - -# Write file to make mysql-test-run.pl start up the server again ---exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect ---enable_reconnect ---source include/wait_until_connected_again.inc +--source include/start_mysqld.inc CHECK TABLE t1; - -# Cleanup DROP TABLE t1; From 4b05d60e62ef6e21d5329a9667813df890034ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 9 Jan 2017 09:15:21 +0200 Subject: [PATCH 042/167] Make encryption.innodb_lotoftables more robust. Perform a slow shutdown at the start of the test, and create all InnoDB tables with STATS_PERSISTENT=0, so that any I/O related to background tasks (change buffer merge, purge, persistent statistics) should be eliminated. --- .../encryption/r/innodb_lotoftables.result | 29 ++++++++++--------- .../encryption/t/innodb_lotoftables.test | 13 +++++++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb_lotoftables.result b/mysql-test/suite/encryption/r/innodb_lotoftables.result index 34f2684253e..b7cfdd2db9d 100644 --- a/mysql-test/suite/encryption/r/innodb_lotoftables.result +++ b/mysql-test/suite/encryption/r/innodb_lotoftables.result @@ -1,3 +1,4 @@ +SET GLOBAL innodb_fast_shutdown=0; SET GLOBAL innodb_file_format = `Barracuda`; SET GLOBAL innodb_file_per_table = ON; SHOW VARIABLES LIKE 'innodb_encrypt%'; @@ -11,13 +12,13 @@ create database innodb_encrypted_1; use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 set autocommit=0; set autocommit=1; commit work; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 # should be 100 SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE NAME LIKE 'innodb_encrypted%'; COUNT(*) @@ -87,47 +88,47 @@ Innodb_pages0_read 3 # Restart Success! show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 use test; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 use innodb_encrypted_2; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 use innodb_encrypted_3; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 3 +Innodb_pages0_read 1 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 103 +Innodb_pages0_read 101 use innodb_encrypted_2; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 103 +Innodb_pages0_read 101 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 203 +Innodb_pages0_read 201 use innodb_encrypted_3; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 203 +Innodb_pages0_read 201 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 303 +Innodb_pages0_read 301 SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%'; COUNT(*) 100 diff --git a/mysql-test/suite/encryption/t/innodb_lotoftables.test b/mysql-test/suite/encryption/t/innodb_lotoftables.test index cad3cb54326..8bad356a9e0 100644 --- a/mysql-test/suite/encryption/t/innodb_lotoftables.test +++ b/mysql-test/suite/encryption/t/innodb_lotoftables.test @@ -11,6 +11,10 @@ let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let $innodb_encryption_threads_orig = `SELECT @@global.innodb_encryption_threads`; --enable_query_log +# empty the change buffer and the undo logs to avoid extra reads +SET GLOBAL innodb_fast_shutdown=0; +--source include/restart_mysqld.inc + SET GLOBAL innodb_file_format = `Barracuda`; SET GLOBAL innodb_file_per_table = ON; @@ -29,7 +33,8 @@ let $tables = 100; --disable_query_log while ($tables) { - eval create table t_$tables (a int not null primary key, b varchar(200)) engine=innodb; + eval create table t_$tables (a int not null primary key, b varchar(200)) engine=innodb + stats_persistent=0; commit; let $rows = 100; while($rows) @@ -64,7 +69,8 @@ set autocommit=0; let $tables = 100; while ($tables) { - eval create table t_$tables (a int not null primary key, b varchar(200)) engine=innodb encrypted=yes; + eval create table t_$tables (a int not null primary key, b varchar(200)) engine=innodb + stats_persistent=0 encrypted=yes; commit; let $rows = 100; while($rows) @@ -100,7 +106,8 @@ set autocommit=0; let $tables = 100; while ($tables) { - eval create table t_$tables (a int not null primary key, b varchar(200)) engine=innodb encrypted=no; + eval create table t_$tables (a int not null primary key, b varchar(200)) engine=innodb + stats_persistent=0 encrypted=no; commit; let $rows = 100; while($rows) From 171e59ed479ee347dae04a34855ea3c29b13349d Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 9 Jan 2017 23:37:42 +0400 Subject: [PATCH 043/167] MDEV-11548 Reproducible server crash after the 2nd ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS. Have to use 'keyname' to check the name uniqueness. --- mysql-test/r/alter_table.result | 15 +++++++++++++++ mysql-test/t/alter_table.test | 19 +++++++++++++++++++ sql/sql_table.cc | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 67de5f3160a..72e81895816 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -2076,3 +2076,18 @@ tab1 CREATE TABLE `tab1` ( PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE `tab1`; +# +# MDEV-11548 Reproducible server crash after the 2nd ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS +# +CREATE TABLE t1 (id INT UNSIGNED NOT NULL PRIMARY KEY); +CREATE TABLE t2 (id1 INT UNSIGNED NOT NULL); +ALTER TABLE t2 +ADD FOREIGN KEY IF NOT EXISTS (id1) +REFERENCES t1 (id); +ALTER TABLE t2 +ADD FOREIGN KEY IF NOT EXISTS (id1) +REFERENCES t1 (id); +Warnings: +Note 1061 Duplicate key name 'id1' +DROP TABLE t2; +DROP TABLE t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index d2b8a6082a6..6fe0f4d30ee 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -1737,3 +1737,22 @@ SHOW CREATE TABLE `tab1`; ALTER TABLE `tab1` CHANGE COLUMN v_col `v_col` varchar(128) AS (IF(field11='option1',CONCAT_WS(":","field1",field2,field3,field4,field5,field6,field7,field8,field9,field10), CONCAT_WS(":","field1",field11,field2,field3,field4,field5,field6,field7,field8,field9,field10))) PERSISTENT; SHOW CREATE TABLE `tab1`; DROP TABLE `tab1`; + +--echo # +--echo # MDEV-11548 Reproducible server crash after the 2nd ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS +--echo # + +CREATE TABLE t1 (id INT UNSIGNED NOT NULL PRIMARY KEY); +CREATE TABLE t2 (id1 INT UNSIGNED NOT NULL); + +ALTER TABLE t2 +ADD FOREIGN KEY IF NOT EXISTS (id1) + REFERENCES t1 (id); + +ALTER TABLE t2 +ADD FOREIGN KEY IF NOT EXISTS (id1) +REFERENCES t1 (id); + +DROP TABLE t2; +DROP TABLE t1; + diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8569771d5f1..31f61301c37 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5943,7 +5943,7 @@ drop_create_field: while ((f_key= fk_key_it++)) { if (my_strcasecmp(system_charset_info, f_key->foreign_id->str, - key->name.str) == 0) + keyname) == 0) goto remove_key; } } From 78e6fafcaa93bdd2cf793a82a812137eb7a779a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 10 Jan 2017 14:11:32 +0200 Subject: [PATCH 044/167] Fix an innodb_plugin leak noted in MDEV-11686 buf_flush_init_flush_rbt() was called too early in MariaDB server 10.0, 10.1, MySQL 5.5 and MySQL 5.6. The memory leak has been fixed in the XtraDB storage engine and in MySQL 5.7. As a result, when the server is started to initialize new data files, the buf_pool->flush_rbt will be created unnecessarily and then leaked. This memory leak was noticed in MariaDB server 10.1 when running the test encryption.innodb_first_page. --- storage/innobase/log/log0recv.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 85f4f6ea671..aed94d00834 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2,6 +2,7 @@ Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -387,12 +388,6 @@ recv_sys_init( } #ifndef UNIV_HOTBACKUP - /* Initialize red-black tree for fast insertions into the - flush_list during recovery process. - As this initialization is done while holding the buffer pool - mutex we perform it before acquiring recv_sys->mutex. */ - buf_flush_init_flush_rbt(); - mutex_enter(&(recv_sys->mutex)); recv_sys->heap = mem_heap_create_typed(256, @@ -3030,6 +3025,11 @@ recv_recovery_from_checkpoint_start_func( byte* buf; byte log_hdr_buf[LOG_FILE_HDR_SIZE]; dberr_t err; + + /* Initialize red-black tree for fast insertions into the + flush_list during recovery process. */ + buf_flush_init_flush_rbt(); + ut_when_dtor tmp(recv_sys->dblwr); #ifdef UNIV_LOG_ARCHIVE From f516db3500c0c20ff119203308cfc95e8752d62d Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Wed, 11 Jan 2017 04:45:47 +0200 Subject: [PATCH 045/167] Updated list of unstable tests for 10.0.29 release --- mysql-test/unstable-tests | 147 +++++++++++++++++++++++--------------- 1 file changed, 91 insertions(+), 56 deletions(-) diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index 3e25115599f..e4c57d9f9d7 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -23,47 +23,65 @@ # ############################################################################## +main.count_distinct2 : MDEV-11768 - timeout +main.create : Modified in 10.0.29 main.create_delayed : MDEV-10605 - failed with timeout -main.ctype_utf32 : Modified on 2016-09-27 (merge) -main.func_group : Modified on 2016-08-08 (MDEV-10468) -main.func_math : Modified on 2016-08-10 (merge) -main.func_misc : Modified on 2016-08-10 (merge) -main.group_min_max_innodb : Modified on 2016-08-25 (MDEV-10595) +main.ctype_ucs2_def : Modified in 10.0.29 +main.ctype_ucs2_query_cache : Modified in 10.0.29 +main.ctype_utf16_def : Modified in 10.0.29 +main.ctype_utf8 : Modified in 10.0.29 +main.ctype_utf8mb4 : Modified in 10.0.29 +main.ctype_utf8mb4 : Modified in 10.0.29 (load file changed) +main.debug_sync : MDEV-10607 - internal error +main.default : Modified in 10.0.29 +main.derived : Modified in 10.0.29 +main.derived_opt : MDEV-11768 - timeout +main.derived_view : Modified in 10.0.29 +main.events_restart : MDEV-11221 - Assertion failure +main.events_slowlog : Added in 10.0.29 +main.fulltext_charsets : Added in 10.0.29 +main.func_time : Modified in 10.0.29 +main.group_by : Modified in 10.0.29 +main.group_by_innodb : Modified in 10.0.29 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout -main.index_merge_myisam : Modified on 2016-09-05 (include file changed) -main.index_merge_innodb : Modified on 2016-09-05 (MDEV-7142) -main.information_schema_stats : Modified on 2016-07-25 (MDEV-10428) +main.index_merge_innodb : MDEV-7142 - wrong result +main.information_schema_part : Modified in 10.0.29 main.innodb_mysql_lock : MDEV-7861 - sporadic lock detection failure -main.loaddata : Modified on 2016-08-10 (merge) +main.join_cache : Modified in 10.0.29 +main.loaddata : Modified in 10.0.29 +main.log_slow : Modified in 10.0.29 main.mdev-504 : MDEV-10607 - sporadic "can't connect" main.mdev375 : MDEV-10607 - sporadic "can't connect" main.merge : MDEV-10607 - sporadic "can't connect" -main.myisam_enable_keys-10506 : New test, added on 2016-08-10 (MDEV-10506) -main.mysqlcheck : Modified on 2016-08-10 (merge) -main.mysqldump : MDEV-10512 - sporadic assertion failure main.mysqlhotcopy_myisam : MDEV-10995 - test hangs on debug build main.mysqltest : MDEV-9269 - fails on Alpha -main.named_pipe : Modified on 2016-08-02 (MDEV-10383) -main.pool_of_threads : MDEV-10100 - sporadic error on detecting max connections +main.order_by : Modified in 10.0.29 +main.parser : Modified in 10.0.29 +main.pool_of_threads : Modified in 10.0.29 main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count -main.range : Modified on 2016-08-10 (merge) -main.range_mrr_icp : Modified on 2016-08-10 (merge) -main.query_cache : MDEV-10611 - sporadic mutex problem -main.shutdown : MDEV-10563 - sporadic crashes -main.sp-prelocking : Modified on 2016-08-10 (merge) +main.selectivity : Modified in 10.0.29 +main.signal_demo3 : MDEV-11720 - Thread stack overrun on Solaris +main.sp : Modified in 10.0.29 +main.sp_notembedded : MDEV-10607 - internal error +main.sp-prelocking : Modified in 10.0.29 main.sp-security : MDEV-10607 - sporadic "can't connect" -main.ssl_compress : MDEV-11110 - valgrind failures main.stat_tables_par_innodb : MDEV-10515 - sporadic wrong results +main.subselect : Modified in 10.0.29 +main.subselect2 : Modified in 10.0.29 +main.subselect4 : Modified in 10.0.29 main.subselect_innodb : MDEV-10614 - sporadic wrong results -main.type_date : Modified on 2016-08-10 (merge) -main.type_uint : Modified on 2016-09-27 (merge) -main.view : Modified on 2016-08-10 (merge) -main.xtradb_mrr : Modified on 2016-08-04 (MDEV-9946) +main.subselect_sj2_jcl6 : MDEV-11766 - unexpected warnings +main.type_bit_innodb : MDEV-11766 - unexpected warnings +main.type_decimal : Modified in 10.0.29 +main.union : Modified in 10.0.29 +main.view : Modified in 10.0.29 +main.xa : MDEV-11769 - lock wait timeout #---------------------------------------------------------------- archive.archive-big : MDEV-10615 - table is marked as crashed +archive.archive_bitfield : MDEV-11771 - table is marked as crashed archive.discover : MDEV-10510 - table is marked as crashed archive.mysqlhotcopy_archive : MDEV-10995 - test hangs on debug build @@ -74,6 +92,8 @@ binlog.binlog_xa_recover : MDEV-8517 - Extra checkpoint #---------------------------------------------------------------- +connect.jdbc : re-enabled in 10.0.29 +connect.jdbc_new : re-enabled in 10.0.29 connect.tbl : MDEV-9844, MDEV-10179 - sporadic crashes, valgrind warnings, wrong results #---------------------------------------------------------------- @@ -82,10 +102,6 @@ engines/rr_trx.* : MDEV-10998 - tests not maintained #---------------------------------------------------------------- -extra/binlog_tests.database : Modified on 2016-10-21 (Upstream MIPS test fixes) - -#---------------------------------------------------------------- - federated.federatedx : MDEV-10617 - Wrong checksum, timeouts federated.federated_innodb : MDEV-10617, MDEV-10417 - Wrong checksum, timeouts, fails on Mips federated.federated_partition : MDEV-10417 - Fails on Mips @@ -93,19 +109,23 @@ federated.federated_transactions : MDEV-10617, MDEV-10417 - Wrong checksum, time #---------------------------------------------------------------- -funcs_2/charset.* : MDEV-10999 - test not maintained +funcs_1.memory_views : MDEV-11773 - timeout +funcs_2/charset.* : MDEV-10999 - test not maintained #---------------------------------------------------------------- innodb.binlog_consistent : MDEV-10618 - Server fails to start +innodb.group_commit_crash_no_optimize_thread : MDEV-11770 - checksum mismatch innodb.innodb-alter-table : MDEV-10619 - Testcase timeout -innodb.innodb-alter-tempfile : Modified on 2016-08-09 (MDEV-10469) innodb.innodb_bug30423 : MDEV-7311 - Wrong number of rows in the plan -innodb.innodb_bug54044 : Modified on 2016-09-27 (merge) +innodb.innodb_bug53290 : MDEV-11767 - timeout +innodb.innodb_bug56143 : MDEV-11766 - unexpected warnings innodb.innodb_monitor : MDEV-10939 - Testcase timeout -innodb.innodb-wl5522 : rdiff file modified on 2016-08-10 (merge) -innodb.innodb-wl5522-debug-zip : MDEV-10427 - Warning: database page corruption -innodb.system_tables : Added on 2016-09-23 (MDEV-10775) +innodb.innodb-wl5522-debug-zip : Modified in 10.0.29 +innodb.table_index_statistics : Modified in 10.0.29 + +innodb_fts.innodb_fts_misc : MDEV-11767 - timeout +innodb_fts.innodb_fts_plugin : MDEV-11766 - unexpected warnings #---------------------------------------------------------------- @@ -125,29 +145,41 @@ multi_source.status_vars : MDEV-4632 - failed while waiting for Slave_received_h #---------------------------------------------------------------- +parts.partition_exch_qa_10 : MDEV-11765 - wrong result parts.partition_float_myisam : MDEV-10621 - Testcase timeout parts.partition_int_myisam : MDEV-10621 - Testcase timeout #---------------------------------------------------------------- +percona.percona_xtradb_bug317074 : MDEV-11767 - timeout + +#---------------------------------------------------------------- + perfschema.func_file_io : MDEV-5708 - fails for s390x perfschema.func_mutex : MDEV-5708 - fails for s390x perfschema.hostcache_ipv6_ssl : MDEV-10696 - crash on shutdown +perfschema.table_name : MDEV-11764 - wrong result perfschema.socket_summary_by_event_name_func : MDEV-10622 - Socket summary tables do not match perfschema_stress.* : MDEV-10996 - tests not maintained #---------------------------------------------------------------- -plugins.feedback_plugin_send : MDEV-7932 - ssl failed for url, MDEV-11112 - valgrind warnings -plugins.pam : Modified on 2016-08-03 (MDEV-7329) -plugins.pam_cleartext : Modified on 2016-08-03 +plugins.feedback_plugin_send : MDEV-7932 - ssl failed for url, MDEV-11118 - wrong result plugins.server_audit : MDEV-9562 - crashes on sol10-sparc plugins.thread_pool_server_audit : MDEV-9562 - crashes on sol10-sparc + +#---------------------------------------------------------------- + +roles.create_and_drop_role : Modified in 10.0.29 +roles.create_and_grant_role : MDEV-11772 - wrong result +roles.role_case_sensitive-10744 : Added in 10.0.29 + #---------------------------------------------------------------- rpl.last_insert_id : MDEV-10625 - warnings in error log +rpl.rpl_alter_extra_persistent : Added in 10.0.29 rpl.rpl_auto_increment : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_bug45679 : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_update_failure : MDEV-10625 - warnings in error log @@ -155,29 +187,31 @@ rpl.rpl_binlog_index : MDEV-9501 - Warning: failed registering rpl.rpl_checksum_cache : MDEV-10626 - Testcase timeout rpl.rpl_circular_for_4_hosts : MDEV-10627 - Testcase timeout rpl.rpl_ddl : MDEV-10417 - Fails on Mips -rpl.rpl_drop_db : Modified on 2016-10-21 (Upstream MIPS test fixes) rpl.rpl_gtid_crash : MDEV-9501 - Warning: failed registering on master rpl.rpl_gtid_master_promote : MDEV-10628 - Timeout in sync_with_master rpl.rpl_gtid_stop_start : MDEV-10629 - Crash on shutdown rpl.rpl_gtid_until : MDEV-10625 - warnings in error log +rpl.rpl_heartbeat_basic : MDEV-11668 - Wrong result rpl.rpl_innodb_bug30888 : MDEV-10417 - Fails on Mips rpl.rpl_insert : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_insert_delayed : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_invoked_features : MDEV-10417 - Fails on Mips +rpl.rpl_mdev10863 : Added in 10.0.29 rpl.rpl_mdev6020 : MDEV-10630, MDEV-10417 - Timeouts, fails on Mips rpl.rpl_mdev6386 : MDEV-10631 - Wrong result on slave rpl.rpl_parallel : MDEV-10632, MDEV-10653 - Failures to sync, timeouts rpl.rpl_parallel_temptable : MDEV-10356 - Crash in close_thread_tables rpl.rpl_partition_innodb : MDEV-10417 - Fails on Mips rpl.rpl_row_drop_create_temp_table : MDEV-10626 - Testcase timeout +rpl.rpl_row_mysqlbinlog : Modified in 10.0.29 rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Wrong plugin status rpl.rpl_slave_grp_exec : MDEV-10514 - Unexpected deadlock -rpl.rpl_switch_stm_row_mixed : MDEV-10611 - Wrong usage of mutex +rpl.rpl_special_charset : Modified in 10.0.29 rpl.rpl_sync : MDEV-10633 - Database page corruption rpl.rpl_temporary_error2 : MDEV-10634 - Wrong number of retries -rpl.sec_behind_master-5114 : MDEV-8518 - Wrong value of Seconds_Behind_Master rpl.rpl_skip_replication : MDEV-9268 - Fails with timeout in sync_slave_with_master on Alpha +rpl.sec_behind_master-5114 : Modified in 10.0.29 rpl/extra/rpl_tests.* : MDEV-10994 - tests not maintained @@ -187,6 +221,8 @@ spider.* : MDEV-9329 - tests are too memory-consuming spider/bg.direct_aggregate : MDEV-7098 - Trying to unlock mutex that wasn't locked spider/bg.direct_aggregate_part : MDEV-7098 - Trying to unlock mutex that wasn't locked +spider/bg.spider3_fixes : MDEV-7098 - Trying to unlock mutex that wasn't locked +spider/bg.spider_fixes_part : MDEV-7098 - Trying to unlock mutex that wasn't locked spider/bg.ha : MDEV-7914, MDEV-9329 - Crash, failures on s390x spider/bg.ha_part : MDEV-9329 - Fails on Ubuntu/s390x spider/bg.spider_fixes : MDEV-7098, MDEV-9329 - Mutex problem, failures on s390x @@ -194,7 +230,7 @@ spider/bg.vp_fixes : MDEV-9329 - Fails on Ubuntu/s390x #---------------------------------------------------------------- -sphinx.* : MDEV-10747 - tests are not run in buildbot, they can't be stable +sphinx.* : MDEV-10986 - sphinx tests fail in buildbot and outside #---------------------------------------------------------------- @@ -203,34 +239,33 @@ stress.ddl_innodb : MDEV-10635 - Testcase timeout #---------------------------------------------------------------- sys_vars.autocommit_func2 : MDEV-9329 - Fails on Ubuntu/s390x -sys_vars.general_log_file_basic : Modified on 2016-08-09 (MDEV-10465) -sys_vars.slow_query_log_file_basic : Modified on 2016-08-09 (MDEV-10465) sys_vars.innodb_buffer_pool_dump_pct_basic : MDEV-10651 - sporadic failure on file_exists +sys_vars.replicate_do_db_basic : Modified in 10.0.29 +sys_vars.replicate_do_table_basic : Modified in 10.0.29 +sys_vars.replicate_ignore_db_basic : Modified in 10.0.29 +sys_vars.replicate_ignore_table_basic : Modified in 10.0.29 +sys_vars.replicate_wild_do_table_basic : Modified in 10.0.29 +sys_vars.replicate_wild_ignore_table_basic : Modified in 10.0.29 +sys_vars.thread_cache_size_func : MDEV-11775 - wrong result #---------------------------------------------------------------- -tokudb.background_job_manager : MDEV-10327 - Assertion failure on server shutdown tokudb.cluster_filter_unpack_varchar : MDEV-10636 - Wrong execution plan -tokudb.* : MDEV-9891 - massive crashes on shutdown -tokudb_alter_table.* : MDEV-9891 - massive crashes on shutdown +tokudb.dir_per_db : MDEV-11537 - wrong result +tokudb.locks-select-update-3 : MDEV-11774 - lock wait timeout +tokudb.table_index_statistics : Added in 10.0.29 + tokudb_backup.* : MDEV-11001 - tests don't work tokudb_bugs.checkpoint_lock : MDEV-10637 - Wrong processlist output tokudb_bugs.checkpoint_lock_3 : MDEV-10637 - Wrong processlist output -tokudb_bugs.* : MDEV-9891 - massive crashes on shutdown -tokudb_parts.* : MDEV-9891 - massive crashes on shutdown -tokudb_rpl_suites.* : MDEV-11001 - tests don't work -tokudb_sys_vars.* : MDEV-11001 - tests don't work -rpl-tokudb.* : MDEV-9891 - massive crashes on shutdown -tokudb/tokudb_add_index.* : MDEV-9891 - massive crashes on shutdown -tokudb/tokudb_backup.* : MDEV-9891 - massive crashes on shutdown -tokudb/tokudb_mariadb.* : MDEV-9891 - massive crashes on shutdown -tokudb/tokudb_sys_vars.* : MDEV-9891 - massive crashes on shutdown -tokudb/tokudb_rpl.* : MDEV-9891 - massive crashes on shutdown +tokudb_rpl.* : MDEV-11001 - tests don't work +tokudb_sys_vars.* : MDEV-11001 - tests don't work #---------------------------------------------------------------- unit.ma_test_loghandler : MDEV-10638 - record read not ok +unit.pfs : MySQL:84457 - unittest pft-t failing #---------------------------------------------------------------- From 67034b6d5265621d67ce589cdee537571ccacfa9 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 6 Dec 2016 14:05:09 +0200 Subject: [PATCH 046/167] Fixes for running with gcov --- .gitignore | 2 ++ BUILD/SETUP.sh | 2 +- BUILD/compile-pentium64-gcov | 2 +- debian/mariadb-test.install | 2 +- mysql-test/{README.gcov => README-gcov} | 10 ++++++---- mysql-test/lib/mtr_gcov.pl | 2 +- mysql-test/mysql-test-run.pl | 2 +- 7 files changed, 13 insertions(+), 9 deletions(-) rename mysql-test/{README.gcov => README-gcov} (56%) diff --git a/.gitignore b/.gitignore index dce5b5ea934..3cec6585ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -80,6 +80,8 @@ mysql-test/lib/My/SafeProcess/my_safe_process mysql-test/mtr mysql-test/mysql-test-run mysql-test/var +mysql-test-gcov.err +mysql-test-gcov.msg mysys/thr_lock mysys/thr_timer packaging/rpm-oel/mysql.spec diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 01d654dba53..5f5b0250088 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -293,7 +293,7 @@ gcov_compile_flags="$gcov_compile_flags -DMYSQL_SERVER_SUFFIX=-gcov -DHAVE_gcov" # GCC4 needs -fprofile-arcs -ftest-coverage on the linker command line (as well # as on the compiler command line), and this requires setting LDFLAGS for BDB. -gcov_link_flags="-fprofile-arcs -ftest-coverage" +gcov_link_flags="-fprofile-arcs -ftest-coverage -lgcov" gcov_configs="--with-gcov" diff --git a/BUILD/compile-pentium64-gcov b/BUILD/compile-pentium64-gcov index 36d4b6192ec..9587c51b4e0 100755 --- a/BUILD/compile-pentium64-gcov +++ b/BUILD/compile-pentium64-gcov @@ -28,6 +28,6 @@ export LDFLAGS="$gcov_link_flags" extra_flags="$pentium64_cflags $max_cflags $gcov_compile_flags" c_warnings="$c_warnings $debug_extra_warnings" cxx_warnings="$cxx_warnings $debug_extra_warnings" -extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs --with-zlib-dir=bundled" +extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs" . "$path/FINISH.sh" diff --git a/debian/mariadb-test.install b/debian/mariadb-test.install index 5e6c3717d1f..605620dc28c 100644 --- a/debian/mariadb-test.install +++ b/debian/mariadb-test.install @@ -17,7 +17,7 @@ usr/lib/mysql/plugin/qa_auth_client.so usr/lib/mysql/plugin/qa_auth_interface.so usr/lib/mysql/plugin/qa_auth_server.so usr/share/mysql/mysql-test/README -usr/share/mysql/mysql-test/README.gcov +usr/share/mysql/mysql-test/README-gcov usr/share/mysql/mysql-test/README.stress usr/share/mysql/mysql-test/disabled.def usr/share/mysql/mysql-test/lib diff --git a/mysql-test/README.gcov b/mysql-test/README-gcov similarity index 56% rename from mysql-test/README.gcov rename to mysql-test/README-gcov index 6d2852e8ca0..ba22a796423 100644 --- a/mysql-test/README.gcov +++ b/mysql-test/README-gcov @@ -2,12 +2,14 @@ To be able to see the level of coverage with the current test suite, do the following: - Make sure gcov is installed - - Compile the MySQL distribution with BUILD/compile-pentium-gcov (if your + - Compile the MySQL distribution with BUILD/compile-pentium64-gcov (if your machine does not have a pentium CPU, hack this script, or just live with the pentium-specific stuff) - In the mysql-test directory, run this command: ./mysql-test-run -gcov - To see the level of coverage for a given source file: - grep source_file_name /tmp/gcov.out + grep -1 source_file_name ../mysql-test-gcov.msg - To see which lines are not yet covered, look at source_file_name.gcov in - the source tree. Then think hard about a test case that will cover those - lines, and write one! + the source tree. You can find this by doing something like: + find source-directory -name "mysqld.cc.gcov" + Then think hard about a test case that will cover those lines, and write + one! diff --git a/mysql-test/lib/mtr_gcov.pl b/mysql-test/lib/mtr_gcov.pl index a6e1f8efd5f..4c260d089b2 100644 --- a/mysql-test/lib/mtr_gcov.pl +++ b/mysql-test/lib/mtr_gcov.pl @@ -27,7 +27,7 @@ sub gcov_prepare ($) { print "Purging gcov information from '$dir'...\n"; system("find $dir -name \*.gcov -o -name \*.da" - . " -o -name \*.gcda | grep -v 'README.gcov\$' | xargs rm"); + . " -o -name \*.gcda | xargs rm"); } # diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 58aedf169d8..9efc9035555 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -248,7 +248,7 @@ our $opt_mem= $ENV{'MTR_MEM'}; our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'}; our $opt_gcov; -our $opt_gcov_src_dir; +our $opt_gcov_src_dir="."; our $opt_gcov_exe= "gcov"; our $opt_gcov_err= "mysql-test-gcov.err"; our $opt_gcov_msg= "mysql-test-gcov.msg"; From e80ad58de8bce0923b91c08d12959c42e9e213a5 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 19 Dec 2016 22:25:42 +0200 Subject: [PATCH 047/167] Improve mysys/hash by caching hash_nr This is done without using any additional memory Added internal test case This is similar to MDEV-7716 --- .gitignore | 1 + include/hash.h | 2 +- mysys/CMakeLists.txt | 4 + mysys/hash.c | 238 ++++++++++++++++++++++++++++++------------- 4 files changed, 175 insertions(+), 70 deletions(-) diff --git a/.gitignore b/.gitignore index 3cec6585ca8..ee52f228ea2 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,7 @@ mysql-test/mysql-test-run mysql-test/var mysql-test-gcov.err mysql-test-gcov.msg +mysys/test_hash mysys/thr_lock mysys/thr_timer packaging/rpm-oel/mysql.spec diff --git a/include/hash.h b/include/hash.h index fde7fc30d38..892922d81a3 100644 --- a/include/hash.h +++ b/include/hash.h @@ -42,7 +42,7 @@ extern "C" { #define HASH_UNIQUE 1 /* hash_insert fails on duplicate key */ #define HASH_THREAD_SPECIFIC 2 /* Mark allocated memory THREAD_SPECIFIC */ -typedef uint my_hash_value_type; +typedef uint32 my_hash_value_type; typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool); typedef my_hash_value_type (*my_hash_function)(CHARSET_INFO *, const uchar *, size_t); diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 892928ca69b..6456db6c0bf 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -96,6 +96,10 @@ ADD_EXECUTABLE(thr_timer thr_timer.c) TARGET_LINK_LIBRARIES(thr_timer mysys) SET_TARGET_PROPERTIES(thr_timer PROPERTIES COMPILE_FLAGS "-DMAIN") +ADD_EXECUTABLE(test_hash hash.c) +TARGET_LINK_LIBRARIES(test_hash mysys) +SET_TARGET_PROPERTIES(test_hash PROPERTIES COMPILE_FLAGS "-DMAIN") + IF(MSVC) INSTALL_DEBUG_TARGET(mysys DESTINATION ${INSTALL_LIBDIR}/debug) ENDIF() diff --git a/mysys/hash.c b/mysys/hash.c index dc03ea9a4dc..2b8130ee47f 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -23,14 +23,15 @@ #include #include "hash.h" -#define NO_RECORD ((uint) -1) +#define NO_RECORD ~((my_hash_value_type) 0) #define LOWFIND 1 #define LOWUSED 2 #define HIGHFIND 4 #define HIGHUSED 8 typedef struct st_hash_info { - uint next; /* index to next key */ + uint32 next; /* index to next key */ + my_hash_value_type hash_nr; uchar *data; /* data for current entry */ } HASH_LINK; @@ -196,13 +197,10 @@ static uint my_hash_mask(my_hash_value_type hashnr, size_t buffmax, return (uint) (hashnr & ((buffmax >> 1) -1)); } -static uint my_hash_rec_mask(const HASH *hash, HASH_LINK *pos, - size_t buffmax, size_t maxlength) +static inline uint my_hash_rec_mask(HASH_LINK *pos, + size_t buffmax, size_t maxlength) { - size_t length; - uchar *key= (uchar*) my_hash_key(hash, pos->data, &length, 0); - return my_hash_mask(hash->hash_function(hash->charset, key, length), buffmax, - maxlength); + return my_hash_mask(pos->hash_nr, buffmax, maxlength); } @@ -266,14 +264,13 @@ uchar* my_hash_first_from_hash_value(const HASH *hash, HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; - uint flag,idx; DBUG_ENTER("my_hash_first_from_hash_value"); - flag=1; if (hash->records) { - idx= my_hash_mask(hash_value, - hash->blength, hash->records); + uint flag= 1; + uint idx= my_hash_mask(hash_value, + hash->blength, hash->records); do { pos= dynamic_element(&hash->array,idx,HASH_LINK*); @@ -286,7 +283,7 @@ uchar* my_hash_first_from_hash_value(const HASH *hash, if (flag) { flag=0; /* Reset flag */ - if (my_hash_rec_mask(hash, pos, hash->blength, hash->records) != idx) + if (my_hash_rec_mask(pos, hash->blength, hash->records) != idx) break; /* Wrong link */ } } @@ -378,15 +375,19 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, my_bool my_hash_insert(HASH *info, const uchar *record) { int flag; - size_t idx,halfbuff,first_index; - my_hash_value_type hash_nr; - uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); + uint idx, halfbuff, first_index; + size_t length; + my_hash_value_type current_hash_nr, UNINIT_VAR(rec_hash_nr), + UNINIT_VAR(rec2_hash_nr); + uchar *UNINIT_VAR(rec_data),*UNINIT_VAR(rec2_data), *key; HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; + key= (uchar*) my_hash_key(info, record, &length, 1); + current_hash_nr= info->hash_function(info->charset, key, length); + if (info->flags & HASH_UNIQUE) { - uchar *key= (uchar*) my_hash_key(info, record, &idx, 1); - if (my_hash_search(info, key, idx)) + if (my_hash_search_using_hash_value(info, current_hash_nr, key, length)) return(TRUE); /* Duplicate entry */ } @@ -402,8 +403,9 @@ my_bool my_hash_insert(HASH *info, const uchar *record) { do { + my_hash_value_type hash_nr; pos=data+idx; - hash_nr=rec_hashnr(info,pos->data); + hash_nr= pos->hash_nr; if (flag == 0) /* First loop; Check if ok */ if (my_hash_mask(hash_nr, info->blength, info->records) != first_index) break; @@ -413,17 +415,19 @@ my_bool my_hash_insert(HASH *info, const uchar *record) { if (flag & HIGHFIND) { - flag=LOWFIND | HIGHFIND; + flag= LOWFIND | HIGHFIND; /* key shall be moved to the current empty position */ - gpos=empty; - ptr_to_rec=pos->data; + gpos= empty; + rec_data= pos->data; + rec_hash_nr= pos->hash_nr; empty=pos; /* This place is now free */ } else { - flag=LOWFIND | LOWUSED; /* key isn't changed */ - gpos=pos; - ptr_to_rec=pos->data; + flag= LOWFIND | LOWUSED; /* key isn't changed */ + gpos= pos; + rec_data= pos->data; + rec_hash_nr= pos->hash_nr; } } else @@ -431,12 +435,14 @@ my_bool my_hash_insert(HASH *info, const uchar *record) if (!(flag & LOWUSED)) { /* Change link of previous LOW-key */ - gpos->data=ptr_to_rec; - gpos->next= (uint) (pos-data); + gpos->data= rec_data; + gpos->hash_nr= rec_hash_nr; + gpos->next= (uint) (pos-data); flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED); } - gpos=pos; - ptr_to_rec=pos->data; + gpos= pos; + rec_data= pos->data; + rec_hash_nr= pos->hash_nr; } } else @@ -445,20 +451,24 @@ my_bool my_hash_insert(HASH *info, const uchar *record) { flag= (flag & LOWFIND) | HIGHFIND; /* key shall be moved to the last (empty) position */ - gpos2 = empty; empty=pos; - ptr_to_rec2=pos->data; + gpos2= empty; + empty= pos; + rec2_data= pos->data; + rec2_hash_nr= pos->hash_nr; } else { if (!(flag & HIGHUSED)) { /* Change link of previous hash-key and save */ - gpos2->data=ptr_to_rec2; - gpos2->next=(uint) (pos-data); + gpos2->data= rec2_data; + gpos2->hash_nr= rec2_hash_nr; + gpos2->next= (uint) (pos-data); flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED); } - gpos2=pos; - ptr_to_rec2=pos->data; + gpos2= pos; + rec2_data= pos->data; + rec2_hash_nr= pos->hash_nr; } } } @@ -466,41 +476,44 @@ my_bool my_hash_insert(HASH *info, const uchar *record) if ((flag & (LOWFIND | LOWUSED)) == LOWFIND) { - gpos->data=ptr_to_rec; - gpos->next=NO_RECORD; + gpos->data= rec_data; + gpos->hash_nr= rec_hash_nr; + gpos->next= NO_RECORD; } if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND) { - gpos2->data=ptr_to_rec2; - gpos2->next=NO_RECORD; + gpos2->data= rec2_data; + gpos2->hash_nr= rec2_hash_nr; + gpos2->next= NO_RECORD; } } - /* Check if we are at the empty position */ - idx= my_hash_mask(rec_hashnr(info, record), info->blength, info->records + 1); - pos=data+idx; + idx= my_hash_mask(current_hash_nr, info->blength, info->records + 1); + pos= data+idx; + /* Check if we are at the empty position */ if (pos == empty) { - pos->data=(uchar*) record; pos->next=NO_RECORD; } else { - /* Check if more records in same hash-nr family */ - empty[0]=pos[0]; - gpos= data + my_hash_rec_mask(info, pos, info->blength, info->records + 1); + /* Move conflicting record to empty position (last) */ + empty[0]= pos[0]; + /* Check if the moved record was in same hash-nr family */ + gpos= data + my_hash_rec_mask(pos, info->blength, info->records + 1); if (pos == gpos) { - pos->data=(uchar*) record; - pos->next=(uint) (empty - data); + /* Point to moved record */ + pos->next= (uint32) (empty - data); } else { - pos->data=(uchar*) record; - pos->next=NO_RECORD; + pos->next= NO_RECORD; movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data)); } } + pos->data= (uchar*) record; + pos->hash_nr= current_hash_nr; if (++info->records == info->blength) info->blength+= info->blength; return(0); @@ -557,15 +570,14 @@ my_bool my_hash_delete(HASH *hash, uchar *record) else if (pos->next != NO_RECORD) { empty=data+(empty_index=pos->next); - pos->data=empty->data; - pos->next=empty->next; + pos[0]= empty[0]; } - if (empty == lastpos) /* last key at wrong pos or no next link */ + if (empty == lastpos) /* last key at wrong pos or no next link */ goto exit; /* Move the last key (lastpos) */ - lastpos_hashnr=rec_hashnr(hash,lastpos->data); + lastpos_hashnr= lastpos->hash_nr; /* pos is where lastpos should be */ pos= data + my_hash_mask(lastpos_hashnr, hash->blength, hash->records); if (pos == empty) /* Move to empty position. */ @@ -573,7 +585,7 @@ my_bool my_hash_delete(HASH *hash, uchar *record) empty[0]=lastpos[0]; goto exit; } - pos_hashnr=rec_hashnr(hash,pos->data); + pos_hashnr= pos->hash_nr; /* pos3 is where the pos should be */ pos3= data + my_hash_mask(pos_hashnr, hash->blength, hash->records); if (pos != pos3) @@ -616,23 +628,30 @@ exit: my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, size_t old_key_length) { - uint new_index,new_pos_index,records; - size_t idx, empty, blength; + uint new_index, new_pos_index, org_index, records, idx; + size_t length, empty, blength; + my_hash_value_type hash_nr; HASH_LINK org_link,*data,*previous,*pos; + uchar *new_key; DBUG_ENTER("my_hash_update"); + + new_key= (uchar*) my_hash_key(hash, record, &length, 1); + hash_nr= hash->hash_function(hash->charset, new_key, length); if (HASH_UNIQUE & hash->flags) { HASH_SEARCH_STATE state; - uchar *found, *new_key= (uchar*) my_hash_key(hash, record, &idx, 1); - if ((found= my_hash_first(hash, new_key, idx, &state))) + uchar *found; + + if ((found= my_hash_first_from_hash_value(hash, hash_nr, new_key, length, + &state))) { do { if (found != record) DBUG_RETURN(1); /* Duplicate entry */ } - while ((found= my_hash_next(hash, new_key, idx, &state))); + while ((found= my_hash_next(hash, new_key, length, &state))); } } @@ -645,19 +664,24 @@ my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, (old_key_length ? old_key_length : hash->key_length)), blength, records); - new_index= my_hash_mask(rec_hashnr(hash, record), blength, records); - if (idx == new_index) - DBUG_RETURN(0); /* Nothing to do (No record check) */ + org_index= idx; + new_index= my_hash_mask(hash_nr, blength, records); previous=0; for (;;) { - if ((pos= data+idx)->data == record) break; previous=pos; if ((idx=pos->next) == NO_RECORD) DBUG_RETURN(1); /* Not found in links */ } + + if (org_index == new_index) + { + data[idx].hash_nr= hash_nr; /* Hash number may have changed */ + DBUG_RETURN(0); /* Record is in right position */ + } + org_link= *pos; empty=idx; @@ -692,21 +716,24 @@ my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, data[empty]= org_link; } data[empty].next= NO_RECORD; + data[empty].hash_nr= hash_nr; DBUG_RETURN(0); } pos=data+new_index; - new_pos_index= my_hash_rec_mask(hash, pos, blength, records); + new_pos_index= my_hash_rec_mask(pos, blength, records); if (new_index != new_pos_index) { /* Other record in wrong position */ - data[empty] = *pos; + data[empty]= *pos; movelink(data,new_index,new_pos_index, (uint) empty); org_link.next=NO_RECORD; data[new_index]= org_link; + data[new_index].hash_nr= hash_nr; } else { /* Link in chain at right position */ org_link.next=data[new_index].next; data[empty]=org_link; + data[empty].hash_nr= hash_nr; data[new_index].next= (uint) empty; } DBUG_RETURN(0); @@ -765,7 +792,7 @@ my_bool my_hash_iterate(HASH *hash, my_hash_walk_action action, void *argument) } -#ifndef DBUG_OFF +#if !defined(DBUG_OFF) || defined(MAIN) my_bool my_hash_check(HASH *hash) { @@ -781,7 +808,15 @@ my_bool my_hash_check(HASH *hash) for (i=found=max_links=seek=0 ; i < records ; i++) { - if (my_hash_rec_mask(hash, data + i, blength, records) == i) + size_t length; + uchar *key= (uchar*) my_hash_key(hash, data[i].data, &length, 0); + if (data[i].hash_nr != hash->hash_function(hash->charset, key, length)) + { + DBUG_PRINT("error", ("record at %d has wrong hash", i)); + error= 1; + } + + if (my_hash_rec_mask(data + i, blength, records) == i) { found++; seek++; links=1; for (idx=data[i].next ; @@ -797,7 +832,7 @@ my_bool my_hash_check(HASH *hash) } hash_info=data+idx; seek+= ++links; - if ((rec_link= my_hash_rec_mask(hash, hash_info, + if ((rec_link= my_hash_rec_mask(hash_info, blength, records)) != i) { DBUG_PRINT("error", ("Record in wrong link at %d: Start %d " @@ -820,6 +855,71 @@ my_bool my_hash_check(HASH *hash) DBUG_PRINT("info", ("records: %u seeks: %d max links: %d hitrate: %.2f", records,seek,max_links,(float) seek / (float) records)); + DBUG_ASSERT(error == 0); return error; } #endif + +#ifdef MAIN + +#define RECORDS 1000 + +uchar *test_get_key(uchar *data, size_t *length, + my_bool not_used __attribute__((unused))) +{ + *length= 2; + return data; +} + + +int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) +{ + uchar records[RECORDS][2], copy[2]; + HASH hash_test; + uint i; + MY_INIT(argv[0]); + DBUG_PUSH("d:t:O,/tmp/test_hash.trace"); + + printf("my_hash_init\n"); + if (my_hash_init2(&hash_test, 100, &my_charset_bin, 20, + 0, 0, (my_hash_get_key) test_get_key, 0, 0, HASH_UNIQUE)) + { + fprintf(stderr, "hash init failed\n"); + exit(1); + } + + printf("my_hash_insert\n"); + for (i= 0 ; i < RECORDS ; i++) + { + int2store(records[i],i); + my_hash_insert(&hash_test, records[i]); + my_hash_check(&hash_test); + } + printf("my_hash_update\n"); + for (i= 0 ; i < RECORDS ; i+=2) + { + memcpy(copy, records[i], 2); + int2store(records[i],i + RECORDS); + if (my_hash_update(&hash_test, records[i], copy, 2)) + { + fprintf(stderr, "hash update failed\n"); + exit(1); + } + my_hash_check(&hash_test); + } + printf("my_hash_delete\n"); + for (i= 0 ; i < RECORDS ; i++) + { + if (my_hash_delete(&hash_test, records[i])) + { + fprintf(stderr, "hash delete failed\n"); + exit(1); + } + my_hash_check(&hash_test); + } + my_hash_free(&hash_test); + printf("ok\n"); + my_end(MY_CHECK_ERROR); + return(0); +} +#endif /* MAIN */ From ed0bc17bee591599c988df21b8d5a264f08eb885 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Dec 2016 13:03:45 +0200 Subject: [PATCH 048/167] Removed usage of my_hash_search() with uninitialized HASH. - Not documented on intened usage - Extra checking takes time for all HASH usage --- mysys/hash.c | 14 +++++++------- sql/item_func.cc | 3 ++- sql/sql_acl.cc | 2 ++ sql/sql_handler.cc | 13 ++++++++----- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/mysys/hash.c b/mysys/hash.c index 2b8130ee47f..1d6b3d5daaa 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -246,13 +246,13 @@ uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, HASH_SEARCH_STATE *current_record) { uchar *res; - if (my_hash_inited(hash)) - res= my_hash_first_from_hash_value(hash, - hash->hash_function(hash->charset, key, - length ? length : hash->key_length), - key, length, current_record); - else - res= 0; + DBUG_ASSERT(my_hash_inited(hash)); + + res= my_hash_first_from_hash_value(hash, + hash->hash_function(hash->charset, key, + length ? length : + hash->key_length), + key, length, current_record); return res; } diff --git a/sql/item_func.cc b/sql/item_func.cc index c38bdba05c2..8e912fe83c8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4302,7 +4302,8 @@ longlong Item_func_release_lock::val_int() User_level_lock *ull; - if (!(ull= + if (!my_hash_inited(&thd->ull_hash) || + !(ull= (User_level_lock*) my_hash_search(&thd->ull_hash, ull_key.ptr(), ull_key.length()))) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ce7de2ed72b..d2840a81e7e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -4365,6 +4365,8 @@ table_hash_search(const char *host, const char *ip, const char *db, static GRANT_COLUMN * column_hash_search(GRANT_TABLE *t, const char *cname, uint length) { + if (!my_hash_inited(&t->hash_columns)) + return (GRANT_COLUMN*) 0; return (GRANT_COLUMN*) my_hash_search(&t->hash_columns, (uchar*) cname, length); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 58db104ec96..4a27244f5b9 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -458,9 +458,10 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); DBUG_RETURN(TRUE); } - if ((handler= (SQL_HANDLER*) my_hash_search(&thd->handler_tables_hash, - (uchar*) tables->alias, - strlen(tables->alias) + 1))) + if ((my_hash_inited(&thd->handler_tables_hash)) && + (handler= (SQL_HANDLER*) my_hash_search(&thd->handler_tables_hash, + (uchar*) tables->alias, + strlen(tables->alias) + 1))) { mysql_ha_close_table(handler); my_hash_delete(&thd->handler_tables_hash, (uchar*) handler); @@ -497,8 +498,10 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables) SQL_HANDLER *mysql_ha_find_handler(THD *thd, const char *name) { SQL_HANDLER *handler; - if ((handler= (SQL_HANDLER*) my_hash_search(&thd->handler_tables_hash, - (uchar*) name, strlen(name) + 1))) + if ((my_hash_inited(&thd->handler_tables_hash)) && + (handler= (SQL_HANDLER*) my_hash_search(&thd->handler_tables_hash, + (uchar*) name, + strlen(name) + 1))) { DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' table: %p", handler->db.str, From ed008a74cf4cfe8619595ec71a6073a9e94f984c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 31 Dec 2016 15:11:52 +0100 Subject: [PATCH 049/167] Make atomic writes general - Atomic writes are enabled by default - Automatically detect if device supports atomic write and use it if atomic writes are enabled - Remove ATOMIC WRITE options from CREATE TABLE - Atomic write is a device option, not a table options as the table may crash if the media changes - Add support for SHANNON SSD cards --- include/my_sys.h | 8 + .../r/innodb_use_atomic_writes_basic.result | 10 +- .../suite/sys_vars/r/sysvars_innodb.result | 6 +- mysys/CMakeLists.txt | 1 + mysys/my_atomic_writes.c | 333 ++++++++++++++++++ sql/mysqld.cc | 3 + storage/innobase/buf/buf0flu.cc | 4 +- storage/innobase/dict/dict0dict.cc | 7 - storage/innobase/fil/fil0fil.cc | 116 +++--- storage/innobase/fsp/fsp0fsp.cc | 12 +- storage/innobase/fsp/fsp0space.cc | 9 +- storage/innobase/fsp/fsp0sysspace.cc | 20 +- storage/innobase/handler/ha_innodb.cc | 66 ++-- storage/innobase/handler/handler0alter.cc | 3 +- storage/innobase/include/dict0dict.h | 4 +- storage/innobase/include/dict0dict.ic | 43 +-- storage/innobase/include/dict0pagecompress.h | 20 -- storage/innobase/include/dict0pagecompress.ic | 36 -- storage/innobase/include/dict0types.h | 7 - storage/innobase/include/fil0fil.h | 21 +- storage/innobase/include/fil0pagecompress.h | 2 +- storage/innobase/include/fsp0file.h | 8 - storage/innobase/include/fsp0fsp.h | 2 +- storage/innobase/include/fsp0fsp.ic | 10 +- storage/innobase/include/fsp0pagecompress.h | 9 - storage/innobase/include/fsp0pagecompress.ic | 30 +- storage/innobase/os/os0file.cc | 45 --- storage/innobase/srv/srv0start.cc | 11 +- support-files/build-tags | 4 +- 29 files changed, 473 insertions(+), 377 deletions(-) create mode 100644 mysys/my_atomic_writes.c diff --git a/include/my_sys.h b/include/my_sys.h index c8f3e1bf3a4..2e9f842d06e 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -192,6 +192,14 @@ extern void my_large_free(uchar *ptr); #define my_large_free(A) my_free_lock((A)) #endif /* HAVE_LARGE_PAGES */ +void my_init_atomic_write(void); +#ifdef __linux__ +my_bool my_test_if_atomic_write(File handle, int pagesize); +#else +#define my_test_if_atomic_write(A, B) 0 +#endif /* __linux__ */ +extern my_bool my_may_have_atomic_write; + #if defined(HAVE_ALLOCA) && !defined(HAVE_valgrind) #if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43) #pragma alloca diff --git a/mysql-test/suite/sys_vars/r/innodb_use_atomic_writes_basic.result b/mysql-test/suite/sys_vars/r/innodb_use_atomic_writes_basic.result index fa6379fbe1c..e420d6e5161 100644 --- a/mysql-test/suite/sys_vars/r/innodb_use_atomic_writes_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_use_atomic_writes_basic.result @@ -1,20 +1,20 @@ select @@global.innodb_use_atomic_writes; @@global.innodb_use_atomic_writes -0 +1 select @@session.innodb_use_atomic_writes; ERROR HY000: Variable 'innodb_use_atomic_writes' is a GLOBAL variable show global variables like 'innodb_use_atomic_writes'; Variable_name Value -innodb_use_atomic_writes OFF +innodb_use_atomic_writes ON show session variables like 'innodb_use_atomic_writes'; Variable_name Value -innodb_use_atomic_writes OFF +innodb_use_atomic_writes ON select * from information_schema.global_variables where variable_name='innodb_use_atomic_writes'; VARIABLE_NAME VARIABLE_VALUE -INNODB_USE_ATOMIC_WRITES OFF +INNODB_USE_ATOMIC_WRITES ON select * from information_schema.session_variables where variable_name='innodb_use_atomic_writes'; VARIABLE_NAME VARIABLE_VALUE -INNODB_USE_ATOMIC_WRITES OFF +INNODB_USE_ATOMIC_WRITES ON set global innodb_use_atomic_writes=1; ERROR HY000: Variable 'innodb_use_atomic_writes' is a read only variable set session innodb_use_atomic_writes=1; diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index de2295859c3..8f655c91427 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2584,12 +2584,12 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME INNODB_USE_ATOMIC_WRITES SESSION_VALUE NULL -GLOBAL_VALUE OFF +GLOBAL_VALUE ON GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE OFF +DEFAULT_VALUE ON VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Prevent partial page writes, via atomic writes.The option is used to prevent partial writes in case of a crash/poweroff, as faster alternative to doublewrite buffer.Currently this option works only on Linux only with FusionIO device, and directFS filesystem. +VARIABLE_COMMENT Enable atomic writes, instead of using the doublewrite buffer, for files on devices that supports atomic writes. To use this option one must use file_per_table=1, flush_method=O_DIRECT and use_fallocate=1. This option only works on Linux with either FusionIO cards using the directFS filesystem or with Shannon cards using any file system. NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 6456db6c0bf..6c43c29a758 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -42,6 +42,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c my_rdtsc.c my_context.c psi_noop.c + my_atomic_writes.c file_logger.c) IF (WIN32) diff --git a/mysys/my_atomic_writes.c b/mysys/my_atomic_writes.c new file mode 100644 index 00000000000..0b54a207713 --- /dev/null +++ b/mysys/my_atomic_writes.c @@ -0,0 +1,333 @@ +/* Copyright (c) 2016, MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "mysys_priv.h" + +my_bool my_may_have_atomic_write= 0; + +#ifdef __linux__ + +my_bool has_shannon_atomic_write= 0, has_fusion_io_atomic_write= 0; + +#include + + +/*********************************************************************** + FUSION_IO +************************************************************************/ + +/** FusionIO atomic write control info */ +#define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) + + +/** + Check if the system has a funsion_io card + @return TRUE Card exists +*/ + +static my_bool test_if_fusion_io_card_exists() +{ + /* Fusion card requires fallocate to exists */ +#ifndef HAVE_POSIX_FALLOCATE + return 0; +#else + return (access("/dev/fcta", F_OK)) == 0; +#endif +} + + +/** + Check if a file is on a Fusion_IO device and that it supports atomic_write + @param[in] file OS file handle + @param[in] page_size page size + @return TRUE Atomic write supported +*/ + +static my_bool fusion_io_has_atomic_write(File file, int page_size) +{ + int atomic= 1; + if (page_size <= 32768 && + ioctl(file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic) != -1) + return(TRUE); + return(FALSE); +} + + +/*********************************************************************** + SHANNON +************************************************************************/ + +#define SHANNON_IOMAGIC 'x' +#define SHANNON_IOCQATOMIC_SIZE _IO(SHANNON_IOMAGIC, 22) + +#define SHANNON_MAX_DEVICES 32 +#define SHANNON_NO_ATOMIC_SIZE_YET -2 + +struct shannon_dev +{ + char dev_name[32]; + dev_t st_dev; + int atomic_size; +}; + + +static struct shannon_dev shannon_devices[SHANNON_MAX_DEVICES+1]; + +/** + Check if the system has a Shannon card + If card exists, record device numbers to allow us to later check if + a given file is on this device. + @return TRUE Card exists +*/ + +static my_bool test_if_shannon_card_exists() +{ + uint shannon_found_devices= 0; + char dev_part; + uint dev_no; + + if (access("/dev/scta", F_OK) < 0) + return 0; + + /* + The Shannon devices are /dev/dfX, where X can be from a-z. + We have to check all of them as some may be missing if the user + removed one with the U.2 interface. + */ + + for (dev_part= 'a' ; dev_part < 'z' ; dev_part++) + { + char path[32]; + struct stat stat_buff; + + sprintf(path, "/dev/df%c", dev_part); +#ifdef TEST_SHANNON + if (lstat(path, &stat_buff) < 0) + { + printf("%s(): lstat failed.\n", __func__); + break; + } +#endif + shannon_devices[shannon_found_devices].st_dev= stat_buff.st_rdev; + sprintf(shannon_devices[shannon_found_devices].dev_name, "/dev/sct%c", + dev_part); + +#ifdef TEST_SHANNON + printf("%s(): i=%d, stat_buff.st_dev=0x%lx, stat_buff.st_rdev=0x%lx, st_rdev=0x%lx, dev_name=%s\n", + __func__, + shannon_found_devices, + (ulong) stat_buff.st_dev, + (ulong) stat_buff.st_rdev, + (ulong) shannon_devices[shannon_found_devices].st_dev, + shannon_devices[shannon_found_devices].dev_name); +#endif + + /* + The atomic size will be checked on first access. This is needed + as a normal user can't open the /dev/scta file + */ + shannon_devices[shannon_found_devices].atomic_size= + SHANNON_NO_ATOMIC_SIZE_YET; + if (++shannon_found_devices== SHANNON_MAX_DEVICES) + goto end; + + for (dev_no= 1 ; dev_no < 9 ; dev_no++) + { + sprintf(path, "/dev/df%c%d", dev_part, dev_no); + if (lstat(path, &stat_buff) < 0) + break; + + shannon_devices[shannon_found_devices].st_dev= stat_buff.st_rdev; + sprintf(shannon_devices[shannon_found_devices].dev_name, "/dev/sct%c%d", + dev_part, dev_no); + +#ifdef TEST_SHANNON + printf("%s(): i=%d, st_dev=0x%lx, st_rdev=0x%lx, dev_name=%s\n", + __func__, + shannon_found_devices, + (ulong) stat_buff.st_dev, + (ulong) shannon_devices[shannon_found_devices].st_dev, + shannon_devices[shannon_found_devices].dev_name); +#endif + + /* + The atomic size will be checked on first access. This is needed + as a normal user can't open the /dev/scta file + */ + shannon_devices[shannon_found_devices].atomic_size= + SHANNON_NO_ATOMIC_SIZE_YET; + if (++shannon_found_devices == SHANNON_MAX_DEVICES) + goto end; + } + } +end: + shannon_devices[shannon_found_devices].st_dev= 0; + return shannon_found_devices > 0; +} + + +static my_bool shannon_dev_has_atomic_write(struct shannon_dev *dev, + int page_size) +{ +#ifdef TEST_SHANNON + printf("%s: enter: page_size=%d, atomic_size=%d, dev_name=%s\n", + __func__, + page_size, + dev->atomic_size, + dev->dev_name); +#endif + if (dev->atomic_size == SHANNON_NO_ATOMIC_SIZE_YET) + { + int fd= open(dev->dev_name, 0); + if (fd < 0) + { + perror("open() failed!"); + dev->atomic_size= 0; /* Don't try again */ + return FALSE; + } + dev->atomic_size= ioctl(fd, SHANNON_IOCQATOMIC_SIZE); + close(fd); + } + +#ifdef TEST_SHANNON + printf("%s: exit: page_size=%d, atomic_size=%d, dev_name=%s\n", + __func__, + page_size, + dev->atomic_size, + dev->dev_name); +#endif + return (page_size <= dev->atomic_size); +} + + +/** + Check if a file is on a Shannon device and that it supports atomic_write + @param[in] file OS file handle + @param[in] page_size page size + @return TRUE Atomic write supported + + @notes + This is called only at first open of a file. In this case it's doesn't + matter so much that we loop over all cards. + We update the atomic size on first access. +*/ + +static my_bool shannon_has_atomic_write(File file, int page_size) +{ + struct shannon_dev *dev; + struct stat stat_buff; + + if (fstat(file, &stat_buff) < 0) + { +#ifdef TEST_SHANNON + printf("%s(): fstat failed\n", __func__); +#endif + return 0; + } + +#ifdef TEST_SHANNON + printf("%s(): st_dev=0x%lx, st_rdev=0x%lx\n", __func__, + (ulong) stat_buff.st_dev, (ulong) stat_buff.st_rdev); +#endif + + for (dev= shannon_devices ; dev->st_dev; dev++) + { +#ifdef TEST_SHANNON + printf("%s(): st_rdev=0x%lx\n", __func__, (ulong) dev->st_dev); +#endif + if (stat_buff.st_dev == dev->st_dev) + return shannon_dev_has_atomic_write(dev, page_size); + } + return 0; +} + + +/*********************************************************************** + Generic atomic write code +************************************************************************/ + +/* + Initalize automic write sub systems. + Checks if we have any devices that supports atomic write +*/ + +void my_init_atomic_write(void) +{ + if ((has_shannon_atomic_write= test_if_shannon_card_exists()) || + (has_fusion_io_atomic_write= test_if_fusion_io_card_exists())) + my_may_have_atomic_write= 1; +#ifdef TEST_SHANNON + printf("%s(): has_shannon_atomic_write=%d, my_may_have_atomic_write=%d\n", + __func__, + has_shannon_atomic_write, + my_may_have_atomic_write); +#endif +} + + +/** + Check if a file supports atomic write + + @return FALSE No atomic write support + TRUE File supports atomic write +*/ + +my_bool my_test_if_atomic_write(File handle, int page_size) +{ +#ifdef TEST_SHANNON + printf("%s(): has_shannon_atomic_write=%d, my_may_have_atomic_write=%d\n", + __func__, + has_shannon_atomic_write, + my_may_have_atomic_write); +#endif + if (!my_may_have_atomic_write) + return 0; + if (has_shannon_atomic_write && + shannon_has_atomic_write(handle, page_size)) + return 1; + + if (has_fusion_io_atomic_write && + fusion_io_has_atomic_write(handle, page_size)) + return 1; + + return 0; +} + +#ifdef TEST_SHANNON +int main() +{ + int fd, ret; + + my_init_atomic_write(); + fd= open("/u01/1.file", O_RDWR); + ret= my_test_if_atomic_write(fd, 4096); + if (ret) + printf("support atomic_write\n"); + else + printf("do not support atomic_write\n"); + close(fd); + return 0; +} +#endif + + +#else /* __linux__ */ + +/* Dummy functions to provide the interfaces for other systems */ + +void my_init_atomic_write(void) +{ +} +#endif /* __linux__ */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 84d6e3b582f..4b79ea43c7c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5862,6 +5862,9 @@ int mysqld_main(int argc, char **argv) if (my_setwd(mysql_real_data_home, opt_abort ? 0 : MYF(MY_WME)) && !opt_abort) unireg_abort(1); /* purecov: inspected */ + /* Atomic write initialization must be done as root */ + my_init_atomic_write(); + if ((user_info= check_user(mysqld_user))) { #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index b82c4db18ad..0f901363596 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1008,7 +1008,7 @@ buf_flush_write_block_low( { page_t* frame = NULL; ulint space_id = bpage->id.space(); - atomic_writes_t awrites = fil_space_get_atomic_writes(space_id); + bool atomic_writes = fil_space_get_atomic_writes(space_id); #ifdef UNIV_DEBUG buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); @@ -1086,7 +1086,7 @@ buf_flush_write_block_low( || buf_dblwr == NULL || srv_read_only_mode || fsp_is_system_temporary(bpage->id.space()) - || awrites == ATOMIC_WRITES_ON) { + || atomic_writes) { ut_ad(!srv_read_only_mode || fsp_is_system_temporary(bpage->id.space())); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 37c6341a293..0013a5f690f 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -7273,7 +7273,6 @@ dict_tf_to_fsp_flags( bool is_shared = DICT_TF_HAS_SHARED_SPACE(table_flags); bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags); ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags); - ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags); ut_ad(!page_size.is_compressed() || has_atomic_blobs); @@ -7305,12 +7304,6 @@ dict_tf_to_fsp_flags( fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(fsp_flags, page_compression_level); } - /* In addition, tablespace flags also contain flag if atomic writes - is used for this table */ - if (atomic_writes) { - fsp_flags |= FSP_FLAGS_SET_ATOMIC_WRITES(fsp_flags, atomic_writes); - } - ut_ad(fsp_flags_is_valid(fsp_flags)); return(fsp_flags); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a2865141a4d..f104112eb7a 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -475,34 +475,6 @@ fil_space_is_flushed( return(true); } -#ifdef UNIV_LINUX - -#include -/** FusionIO atomic write control info */ -#define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) - -/** -Try and enable FusionIO atomic writes. -@param[in] file OS file handle -@return true if successful */ -bool -fil_fusionio_enable_atomic_write(os_file_t file) -{ - if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) { - - uint atomic = 1; - - ut_a(file != -1); - - if (ioctl(file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic) != -1) { - - return(true); - } - } - - return(false); -} -#endif /* UNIV_LINUX */ /** Append a file to the chain of files of a space. @param[in] name file name of a file that is not open @@ -510,7 +482,7 @@ fil_fusionio_enable_atomic_write(os_file_t file) @param[in,out] space tablespace from fil_space_create() @param[in] is_raw whether this is a raw device or partition @param[in] punch_hole true if supported for this node -@param[in] atomic_write true if the file has atomic write enabled +@param[in] atomic_write true if the file could use atomic write @param[in] max_pages maximum number of pages in file, ULINT_MAX means the file size is unlimited. @return pointer to the file name @@ -606,7 +578,7 @@ fil_node_create_low( an integer @param[in,out] space space where to append @param[in] is_raw true if a raw device or a raw disk partition -@param[in] atomic_write true if the file has atomic write enabled +@param[in] atomic_write true if the file could use atomic write @param[in] max_pages maximum number of pages in file, ULINT_MAX means the file size is unlimited. @return pointer to the file name @@ -829,7 +801,27 @@ retry: node->handle = os_file_create( innodb_data_file_key, node->name, OS_FILE_OPEN, OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success); - } + + if (!space->atomic_write_tested) + { + const page_size_t page_size(space->flags); + + space->atomic_write_tested= 1; + /* + Atomic writes is supported if the file can be used + with atomic_writes (not log file), O_DIRECT is + used (tested in ha_innodbc.cc) and the file is + device and file system that supports atomic writes + for the given block size + */ + space->atomic_write_supported= + srv_use_atomic_writes && + node->atomic_write && + my_test_if_atomic_write(node->handle, + page_size.physical()) ? + true : false; + } + } ut_a(success); @@ -3855,37 +3847,34 @@ fil_ibd_create( return(DB_ERROR); } -#ifdef UNIV_LINUX - const bool atomic_write = fil_fusionio_enable_atomic_write(file); + success= false; +#ifdef HAVE_POSIX_FALLOCATE + /* + Extend the file using posix_fallocate(). This is required by + FusionIO HW/Firmware but should also be the prefered way to extend + a file. + */ + int ret = posix_fallocate(file, 0, size * UNIV_PAGE_SIZE); - if (atomic_write) { - /* This is required by FusionIO HW/Firmware */ - int ret = posix_fallocate(file, 0, size * UNIV_PAGE_SIZE); - - if (ret != 0) { - - ib::error() << - "posix_fallocate(): Failed to preallocate" - " data for file " << path - << ", desired size " - << size * UNIV_PAGE_SIZE - << " Operating system error number " << ret - << ". Check" - " that the disk is not full or a disk quota" - " exceeded. Make sure the file system supports" - " this function. Some operating system error" - " numbers are described at " REFMAN - " operating-system-error-codes.html"; - - success = false; + if (ret != 0) { + ib::error() << + "posix_fallocate(): Failed to preallocate" + " data for file " << path + << ", desired size " + << size * UNIV_PAGE_SIZE + << " Operating system error number " << ret + << ". Check" + " that the disk is not full or a disk quota" + " exceeded. Make sure the file system supports" + " this function. Some operating system error" + " numbers are described at " REFMAN + " operating-system-error-codes.html"; } else { success = true; } - } else -#else - const bool atomic_write = false; -#endif /* UNIV_LINUX */ - { +#endif /* HAVE_POSIX_FALLOCATE */ + if (!success) + { success = os_file_set_size( path, file, size * UNIV_PAGE_SIZE, srv_read_only_mode); } @@ -4022,7 +4011,7 @@ fil_ibd_create( crypt_data, true); if (!fil_node_create_low( - path, size, space, false, punch_hole, atomic_write)) { + path, size, space, false, punch_hole, TRUE)) { if (crypt_data) { free(crypt_data); @@ -4234,13 +4223,6 @@ fil_ibd_open( df_dict.close(); } -#ifdef UNIV_LINUX - const bool atomic_write = !srv_use_doublewrite_buf && df_default.is_open() - && fil_fusionio_enable_atomic_write(df_default.handle()); -#else - const bool atomic_write = false; -#endif /* UNIV_LINUX */ - /* We have now checked all possible tablespace locations and have a count of how many unique files we found. If things are normal, we only found 1. */ @@ -4443,7 +4425,7 @@ skip_validate: df_remote.is_open() ? df_remote.filepath() : df_dict.is_open() ? df_dict.filepath() : df_default.filepath(), 0, space, false, - true, atomic_write) == NULL) { + true, TRUE) == NULL) { err = DB_ERROR; } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 54070c12406..4fa1d92a6fd 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -200,7 +200,6 @@ fsp_flags_to_dict_tf( bool shared_space = FSP_FLAGS_GET_SHARED(fsp_flags); bool page_compressed = FSP_FLAGS_GET_PAGE_COMPRESSION(fsp_flags); ulint comp_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(fsp_flags); - bool atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(fsp_flags); /* FSP_FLAGS_GET_TEMPORARY(fsp_flags) does not have an equivalent flag position in the table flags. But it would go into flags2 if @@ -208,7 +207,7 @@ fsp_flags_to_dict_tf( ulint flags = dict_tf_init(post_antelope | compact, zip_ssize, atomic_blobs, data_dir, shared_space, - page_compressed, comp_level, atomic_writes); + page_compressed, comp_level, 0); return(flags); } @@ -235,7 +234,6 @@ fsp_flags_is_valid( ulint unused = FSP_FLAGS_GET_UNUSED(flags); bool page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags); ulint page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags); - ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags); const char *file; ulint line; @@ -301,11 +299,6 @@ fsp_flags_is_valid( } } - if (atomic_writes > ATOMIC_WRITES_OFF) { - GOTO_ERROR; - return (false); - } - #if UNIV_FORMAT_MAX != UNIV_FORMAT_B # error UNIV_FORMAT_MAX != UNIV_FORMAT_B, Add more validations. #endif @@ -329,8 +322,7 @@ err_exit: << " is_temp: " << is_temp << " is_encryption: " << is_encryption << " page_compressed: " << page_compression - << " page_compression_level: " << page_compression_level - << " atomic_writes: " << atomic_writes; + << " page_compression_level: " << page_compression_level; return (false); } diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc index 45942f58dd3..b72590e48e8 100644 --- a/storage/innobase/fsp/fsp0space.cc +++ b/storage/innobase/fsp/fsp0space.cc @@ -118,13 +118,6 @@ Tablespace::open_or_create(bool is_temp) break; } -#ifdef UNIV_LINUX - const bool atomic_write = fil_fusionio_enable_atomic_write( - it->m_handle); -#else - const bool atomic_write = false; -#endif - /* We can close the handle now and open the tablespace the proper way. */ it->close(); @@ -149,7 +142,7 @@ Tablespace::open_or_create(bool is_temp) /* Create the tablespace node entry for this data file. */ if (!fil_node_create( it->m_filepath, it->m_size, space, false, - atomic_write)) { + TRUE)) { err = DB_ERROR; break; diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index fa6a46890db..9a9e7051403 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -906,24 +906,6 @@ SysTablespace::open_or_create( return(err); } -#ifdef UNIV_LINUX - /* Note: This should really be per node and not per - tablespace because a tablespace can contain multiple - files (nodes). The implication is that all files of - the tablespace should be on the same medium. */ - - it->m_atomic_write - = fil_fusionio_enable_atomic_write(it->m_handle); - - if (it->m_atomic_write && srv_use_doublewrite_buf) { - ib::info() << "FusionIO atomic IO enabled," - " disabling the double write buffer"; - - srv_use_doublewrite_buf = false; - } -#else - it->m_atomic_write = false; -#endif } if (!create_new_db && flush_lsn) { @@ -975,7 +957,7 @@ SysTablespace::open_or_create( if (!fil_node_create( it->m_filepath, it->m_size, space, it->m_type != SRV_NOT_RAW, - it->m_atomic_write, max_size)) { + TRUE, max_size)) { err = DB_ERROR; break; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ae9363d1709..ff80d967092 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -249,7 +249,7 @@ values */ static ulong innobase_fast_shutdown = 1; static my_bool innobase_file_format_check = TRUE; -static my_bool innobase_use_atomic_writes = FALSE; +static my_bool innobase_use_atomic_writes = TRUE; static my_bool innobase_use_fallocate; static my_bool innobase_use_doublewrite = TRUE; static my_bool innobase_use_checksums = TRUE; @@ -791,8 +791,6 @@ ha_create_table_option innodb_table_option_list[]= /* With this option user can set zip compression level for page compression for this table*/ HA_TOPTION_NUMBER("PAGE_COMPRESSION_LEVEL", page_compression_level, 0, 1, 9, 1), - /* With this option user can enable atomic writes feature for this table */ - HA_TOPTION_ENUM("ATOMIC_WRITES", atomic_writes, "DEFAULT,ON,OFF", 0), /* With this option the user can enable encryption for the table */ HA_TOPTION_ENUM("ENCRYPTED", encryption, "DEFAULT,YES,NO", 0), /* With this option the user defines the key identifier using for the encryption */ @@ -4332,7 +4330,7 @@ innobase_init( /* Create the filespace flags. */ fsp_flags = fsp_flags_init( - univ_page_size, false, false, false, false, false, 0, ATOMIC_WRITES_DEFAULT); + univ_page_size, false, false, false, false, false, 0, 0); srv_sys_space.set_flags(fsp_flags); srv_sys_space.set_name(reserved_system_space_name); @@ -4358,7 +4356,7 @@ innobase_init( /* Create the filespace flags with the temp flag set. */ fsp_flags = fsp_flags_init( - univ_page_size, false, false, false, true, false, 0, ATOMIC_WRITES_DEFAULT); + univ_page_size, false, false, false, true, false, 0, 0); srv_tmp_space.set_flags(fsp_flags); if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) { @@ -4647,17 +4645,20 @@ innobase_change_buffering_inited_ok: " It will be removed in MariaDB 10.3."; } - srv_use_atomic_writes = (ibool) innobase_use_atomic_writes; - if (innobase_use_atomic_writes) { - fprintf(stderr, "InnoDB: using atomic writes.\n"); - /* Force doublewrite buffer off, atomic writes replace it. */ - if (srv_use_doublewrite_buf) { - fprintf(stderr, "InnoDB: Switching off doublewrite buffer " - "because of atomic writes.\n"); - innobase_use_doublewrite = srv_use_doublewrite_buf = FALSE; - } + srv_use_atomic_writes = (ibool) (innobase_use_atomic_writes && + my_may_have_atomic_write); + if (srv_use_atomic_writes && !srv_file_per_table) + { + fprintf(stderr, "InnoDB: Disabling atomic_writes as file_per_table is not used.\n"); + srv_use_atomic_writes= 0; + } - /* Force O_DIRECT on Unixes (on Windows writes are always unbuffered)*/ + if (srv_use_atomic_writes) { + fprintf(stderr, "InnoDB: using atomic writes.\n"); + /* + Force O_DIRECT on Unixes (on Windows writes are always + unbuffered) + */ #ifndef _WIN32 if (!innobase_file_flush_method || !strstr(innobase_file_flush_method, "O_DIRECT")) { @@ -13153,7 +13154,6 @@ create_table_info_t::check_table_options() { enum row_type row_format = m_form->s->row_type; ha_table_option_struct *options= m_form->s->option_struct; - atomic_writes_t awrites = (atomic_writes_t)options->atomic_writes; fil_encryption_t encrypt = (fil_encryption_t)options->encryption; if (encrypt != FIL_SPACE_ENCRYPTION_DEFAULT && !m_allow_file_per_table) { @@ -13287,19 +13287,6 @@ create_table_info_t::check_table_options() } } - /* Check atomic writes requirements */ - if (awrites == ATOMIC_WRITES_ON || - (awrites == ATOMIC_WRITES_DEFAULT && srv_use_atomic_writes)) { - if (!m_allow_file_per_table) { - push_warning( - m_thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: ATOMIC_WRITES requires" - " innodb_file_per_table."); - return "ATOMIC_WRITES"; - } - } - return NULL; } @@ -13712,7 +13699,7 @@ index_bad: options->page_compressed, options->page_compression_level == 0 ? default_compression_level : options->page_compression_level, - options->atomic_writes); + 0); if (m_use_file_per_table) { ut_ad(!m_use_shared_space); @@ -15032,7 +15019,7 @@ innobase_create_tablespace( false, /* Temporary General Tablespaces not allowed */ false, /* Page compression is not used. */ 0, /* Page compression level 0 */ - ATOMIC_WRITES_DEFAULT); /* No atomic writes yet */ + 0); tablespace.set_flags(fsp_flags); @@ -19482,8 +19469,8 @@ ha_innobase::check_if_incompatible_data( /* Changes on engine specific table options requests a rebuild of the table. */ if (param_new->page_compressed != param_old->page_compressed || - param_new->page_compression_level != param_old->page_compression_level || - param_new->atomic_writes != param_old->atomic_writes) { + param_new->page_compression_level != param_old->page_compression_level) + { return(COMPATIBLE_DATA_NO); } @@ -21950,12 +21937,13 @@ static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite, static MYSQL_SYSVAR_BOOL(use_atomic_writes, innobase_use_atomic_writes, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, - "Prevent partial page writes, via atomic writes." - "The option is used to prevent partial writes in case of a crash/poweroff, " - "as faster alternative to doublewrite buffer." - "Currently this option works only " - "on Linux only with FusionIO device, and directFS filesystem.", - NULL, NULL, FALSE); + "Enable atomic writes, instead of using the doublewrite buffer, for files " + "on devices that supports atomic writes. " + "To use this option one must use " + "file_per_table=1, flush_method=O_DIRECT and use_fallocate=1. " + "This option only works on Linux with either FusionIO cards using " + "the directFS filesystem or with Shannon cards using any file system.", + NULL, NULL, TRUE); static MYSQL_SYSVAR_BOOL(use_fallocate, innobase_use_fallocate, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index b1bdf29c057..53157258d2e 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -614,8 +614,7 @@ ha_innobase::check_if_supported_inplace_alter( ha_table_option_struct *old_options= table->s->option_struct; if (new_options->page_compressed != old_options->page_compressed || - new_options->page_compression_level != old_options->page_compression_level || - new_options->atomic_writes != old_options->atomic_writes) { + new_options->page_compression_level != old_options->page_compression_level) { ha_alter_info->unsupported_reason = innobase_get_err_msg( ER_ALTER_OPERATION_NOT_SUPPORTED_REASON); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index be6f6b1d9a5..ca3951dd309 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1003,7 +1003,7 @@ dict_tf_set( bool shared_space, bool page_compressed, ulint page_compression_level, - ulint atomic_writes); + ulint not_used); /** Initialize a dict_table_t::flags pointer. @param[in] compact, Table uses Compact or greater @@ -1021,7 +1021,7 @@ dict_tf_init( bool shared_space, bool page_compressed, ulint page_compression_level, - ulint atomic_writes); + ulint not_used); /** Convert a 32 bit integer table flags to the 32 bit FSP Flags. Fsp Flags are written into the tablespace header at the offset diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index b99cb421ab2..c7d553f5daa 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -664,7 +664,6 @@ dict_tf_is_valid( ulint unused = DICT_TF_GET_UNUSED(flags); bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(flags); ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags); - ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(flags); bool flags_corrupt = false; /* Make sure there are no bits that we do not know about. */ @@ -711,12 +710,6 @@ dict_tf_is_valid( } } - if (atomic_writes) { - - if(atomic_writes > ATOMIC_WRITES_OFF) { - flags_corrupt = true; - } - } /* HAS_DATA_DIR and SHARED_SPACE are mutually exclusive. */ if (data_dir && shared_space) { @@ -734,7 +727,6 @@ dict_tf_is_valid( << " zip_ssize:" << zip_ssize << " page_compression:" << page_compression << " page_compression_level:" << page_compression_level - << " atomic_writes:" << atomic_writes << " shared_space:" << shared_space; return (false); } else { @@ -789,9 +781,6 @@ dict_sys_tables_type_validate( ulint unused = DICT_TF_GET_UNUSED(type); bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(type); ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(type); - ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(type); - - ut_a(atomic_writes <= ATOMIC_WRITES_OFF); /* The low order bit of SYS_TABLES.TYPE is always set to 1. If the format is UNIV_FORMAT_B or higher, this field is the same @@ -875,13 +864,6 @@ dict_sys_tables_type_validate( } } - /* Validate that the atomic writes number is within allowed range. */ - if (atomic_writes > ATOMIC_WRITES_OFF) { - ib::error() << "SYS_TABLES::TYPE=" << type - << " atomic_writes:" << atomic_writes; - return(ULINT_UNDEFINED); - } - /* Return the validated SYS_TABLES.TYPE. */ return(type); } @@ -949,11 +931,10 @@ dict_table_get_format( @param[in] format File Format @param[in] zip_ssize Zip Shift Size @param[in] use_data_dir Table uses DATA DIRECTORY -@param[in] atomic_writes Does table use atomic writes @param[in] shared_space Table uses a General Shared Tablespace @param[in] page_compressed Table uses page compression @param[in] page_compression_level Page compression level -@param[in] atomic_writes Table uses atomic writes */ +@param[in] not_used For future */ UNIV_INLINE void dict_tf_set( @@ -965,7 +946,7 @@ dict_tf_set( bool shared_space, bool page_compressed, ulint page_compression_level, - ulint atomic_writes) + ulint not_used) { switch (format) { case REC_FORMAT_REDUNDANT: @@ -1005,11 +986,6 @@ dict_tf_set( ut_ad(dict_tf_get_page_compression(*flags) == TRUE); ut_ad(dict_tf_get_page_compression_level(*flags) == page_compression_level); } - - if (atomic_writes) { - *flags |= (atomic_writes << DICT_TF_POS_ATOMIC_WRITES); - ut_a(dict_tf_get_atomic_writes(*flags) == atomic_writes); - } } /** Initialize a dict_table_t::flags pointer. @@ -1020,7 +996,7 @@ dict_tf_set( @param[in] shared_space Table uses a General Shared Tablespace @param[in] page_compression Table uses page compression @param[in] page_compression_level used compression level -@param[in] atomic_writes Table atomic writes option */ +@param[in] not_used For future */ UNIV_INLINE ulint dict_tf_init( @@ -1031,7 +1007,7 @@ dict_tf_init( bool shared_space, bool page_compressed, ulint page_compression_level, - ulint atomic_writes) + ulint not_used) { ulint flags = 0; @@ -1065,11 +1041,6 @@ dict_tf_init( ut_ad(dict_tf_get_page_compression_level(flags) == page_compression_level); } - if (atomic_writes) { - flags |= (atomic_writes << DICT_TF_POS_ATOMIC_WRITES); - ut_a(dict_tf_get_atomic_writes(flags) == atomic_writes); - } - return(flags); } @@ -1097,13 +1068,12 @@ dict_sys_tables_type_to_tf( flags = redundant ? 0 : 1; /* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION, - PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES are the same. */ + PAGE_COMPRESSION_LEVEL are the same. */ flags |= type & (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS | DICT_TF_MASK_DATA_DIR | DICT_TF_MASK_PAGE_COMPRESSION | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL - | DICT_TF_MASK_ATOMIC_WRITES | DICT_TF_MASK_SHARED_SPACE); ut_ad(!DICT_TF_GET_ZIP_SSIZE(flags) || DICT_TF_HAS_ATOMIC_BLOBS(flags)); @@ -1134,13 +1104,12 @@ dict_tf_to_sys_tables_type( type = 1; /* ZIP_SSIZE, ATOMIC_BLOBS, DATA_DIR, PAGE_COMPRESSION, - PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES are the same. */ + PAGE_COMPRESSION_LEVEL are the same. */ type |= flags & (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS | DICT_TF_MASK_DATA_DIR | DICT_TF_MASK_PAGE_COMPRESSION | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL - | DICT_TF_MASK_ATOMIC_WRITES | DICT_TF_MASK_SHARED_SPACE); return(type); diff --git a/storage/innobase/include/dict0pagecompress.h b/storage/innobase/include/dict0pagecompress.h index 19a2a6c52f3..f8873aec965 100644 --- a/storage/innobase/include/dict0pagecompress.h +++ b/storage/innobase/include/dict0pagecompress.h @@ -67,26 +67,6 @@ dict_tf_verify_flags( ulint fsp_flags) /*!< in: fil_space_t::flags */ __attribute__((const)); -/********************************************************************//** -Extract the atomic writes flag from table flags. -@return true if atomic writes are used, false if not used */ -UNIV_INLINE -atomic_writes_t -dict_tf_get_atomic_writes( -/*======================*/ - ulint flags) /*!< in: flags */ - __attribute__((const)); - -/********************************************************************//** -Check whether the table uses the atomic writes. -@return true if atomic writes is used, false if not */ -UNIV_INLINE -atomic_writes_t -dict_table_get_atomic_writes( -/*=========================*/ - const dict_table_t* table); /*!< in: table */ - - #ifndef UNIV_NONINL #include "dict0pagecompress.ic" #endif diff --git a/storage/innobase/include/dict0pagecompress.ic b/storage/innobase/include/dict0pagecompress.ic index 811976434a8..05a26f00711 100644 --- a/storage/innobase/include/dict0pagecompress.ic +++ b/storage/innobase/include/dict0pagecompress.ic @@ -41,7 +41,6 @@ dict_tf_verify_flags( ulint data_dir = DICT_TF_HAS_DATA_DIR(table_flags); ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags); ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags); - ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags); ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(fsp_flags); ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags); ulint fsp_atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(fsp_flags); @@ -49,7 +48,6 @@ dict_tf_verify_flags( ulint fsp_unused = FSP_FLAGS_GET_UNUSED(fsp_flags); ulint fsp_page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(fsp_flags); ulint fsp_page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(fsp_flags); - ulint fsp_atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(fsp_flags); DBUG_EXECUTE_IF("dict_tf_verify_flags_failure", return(ULINT_UNDEFINED);); @@ -97,16 +95,6 @@ dict_tf_verify_flags( return (FALSE); } - if (atomic_writes != fsp_atomic_writes) { - fprintf(stderr, - "InnoDB: Error: table flags has atomic writes %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has atomic_writes %ld\n", - atomic_writes, fsp_atomic_writes); - - return (FALSE); - } - return(TRUE); } @@ -165,27 +153,3 @@ dict_table_is_page_compressed( { return (dict_tf_get_page_compression(table->flags)); } - -/********************************************************************//** -Extract the atomic writes flag from table flags. -@return enumerated value of atomic writes */ -UNIV_INLINE -atomic_writes_t -dict_tf_get_atomic_writes( -/*======================*/ - ulint flags) /*!< in: flags */ -{ - return((atomic_writes_t)DICT_TF_GET_ATOMIC_WRITES(flags)); -} - -/********************************************************************//** -Check whether the table uses the atomic writes. -@return enumerated value of atomic writes */ -UNIV_INLINE -atomic_writes_t -dict_table_get_atomic_writes( -/*=========================*/ - const dict_table_t* table) /*!< in: table */ -{ - return ((atomic_writes_t)dict_tf_get_atomic_writes(table->flags)); -} diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h index ae002dd9487..b0623f82bb7 100644 --- a/storage/innobase/include/dict0types.h +++ b/storage/innobase/include/dict0types.h @@ -80,13 +80,6 @@ enum ib_quiesce_t { QUIESCE_COMPLETE /*!< All done */ }; -/** Enum values for atomic_writes table option */ -typedef enum { - ATOMIC_WRITES_DEFAULT = 0, - ATOMIC_WRITES_ON = 1, - ATOMIC_WRITES_OFF = 2 -} atomic_writes_t; - #ifndef UNIV_INNOCHECKSUM typedef ib_mutex_t DictSysMutex; #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 30d79a52b4d..0197dfaabb4 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -190,6 +190,14 @@ struct fil_space_t { /** True if we have already printed compression failure */ bool printed_compression_failure; + /** True if page 0 of tablespace is read */ + bool read_page0; + + /** True if we have tested if this filespace supports atomic writes */ + bool atomic_write_tested; + /** True if the device this filespace is on supports atomic writes */ + bool atomic_write_supported; + /** Release the reserved free extents. @param[in] n_reserved number of reserved extents */ void release_free_extents(ulint n_reserved); @@ -244,7 +252,7 @@ struct fil_node_t { /** block size to use for punching holes */ ulint block_size; - /** whether atomic write is enabled for this file */ + /** whether this file could use atomic write (data file) */ bool atomic_write; /** FIL_NODE_MAGIC_N */ @@ -663,7 +671,7 @@ MY_ATTRIBUTE((warn_unused_result, pure)); @param[in] size file size in entire database blocks @param[in,out] space tablespace from fil_space_create() @param[in] is_raw whether this is a raw device or partition -@param[in] atomic_write true if atomic write enabled +@param[in] atomic_write true if atomic write could be enabled @param[in] max_pages maximum number of pages in file, ULINT_MAX means the file size is unlimited. @return pointer to the file name @@ -1730,15 +1738,6 @@ fil_names_clear( lsn_t lsn, bool do_write); -#ifdef UNIV_LINUX -/** -Try and enable FusionIO atomic writes. -@param[in] file OS file handle -@return true if successful */ -bool -fil_fusionio_enable_atomic_write(os_file_t file); -#endif /* UNIV_LINUX */ - /** Note that the file system where the file resides doesn't support PUNCH HOLE @param[in,out] node Node to set */ void fil_no_punch_hole(fil_node_t* node); diff --git a/storage/innobase/include/fil0pagecompress.h b/storage/innobase/include/fil0pagecompress.h index d4cc54c7b2a..e65d3491155 100644 --- a/storage/innobase/include/fil0pagecompress.h +++ b/storage/innobase/include/fil0pagecompress.h @@ -62,7 +62,7 @@ Returns the atomic writes flag of the space, or false if the space is not using atomic writes. The tablespace must be cached in the memory cache. @return atomic write table option value */ UNIV_INLINE -atomic_writes_t +bool fil_space_get_atomic_writes( /*=========================*/ ulint id); /*!< in: space id */ diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 83aa370abf0..82d086bcf7a 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -65,7 +65,6 @@ public: m_is_valid(), m_first_page_buf(), m_first_page(), - m_atomic_write(), m_last_os_error(), m_file_info(), m_encryption_key(NULL), @@ -91,7 +90,6 @@ public: m_is_valid(), m_first_page_buf(), m_first_page(), - m_atomic_write(), m_last_os_error(), m_file_info(), m_encryption_key(NULL), @@ -115,7 +113,6 @@ public: m_is_valid(file.m_is_valid), m_first_page_buf(), m_first_page(), - m_atomic_write(file.m_atomic_write), m_last_os_error(), m_file_info(), m_encryption_key(NULL), @@ -183,8 +180,6 @@ public: /* Do not copy crypt info it is read from first page */ m_crypt_info = NULL; - m_atomic_write = file.m_atomic_write; - return(*this); } @@ -475,9 +470,6 @@ private: /** Pointer to the first page held in the buffer above */ byte* m_first_page; - /** true if atomic writes enabled for this file */ - bool m_atomic_write; - protected: /** Last OS error received so it can be reported if needed. */ ulint m_last_os_error; diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index f503580a1a7..6ddcec78a01 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -708,7 +708,7 @@ fsp_flags_init( bool is_temporary, bool page_compression, ulint page_compression_level, - ulint atomic_writes, + ulint not_used, bool is_encrypted = false); /** Convert a 32 bit integer tablespace flags to the 32 bit table flags. diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index c675c6302a6..31317969bf0 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -184,7 +184,7 @@ fsp_flags_set_page_size( @param[in] is_encrypted This tablespace is encrypted. @param[in] page_compressed Table uses page compression @param[in] page_compression_level Page compression level -@param[in] atomic_writes Table uses atomic writes +@param[in] not_used For future @@return tablespace flags after initialization */ UNIV_INLINE ulint @@ -196,7 +196,7 @@ fsp_flags_init( bool is_temporary, bool page_compression, ulint page_compression_level, - ulint atomic_writes, + ulint not_used, bool is_encrypted) { ut_ad(page_size.physical() <= page_size.logical()); @@ -247,12 +247,6 @@ fsp_flags_init( flags |= FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(flags, page_compression_level); } - /* In addition, tablespace flags also contain flag if atomic writes - is used for this table */ - if (atomic_writes) { - flags |= FSP_FLAGS_SET_ATOMIC_WRITES(flags, atomic_writes); - } - ut_ad(fsp_flags_is_valid(flags)); return(flags); diff --git a/storage/innobase/include/fsp0pagecompress.h b/storage/innobase/include/fsp0pagecompress.h index 44bdddfa3bf..9038aa0fdef 100644 --- a/storage/innobase/include/fsp0pagecompress.h +++ b/storage/innobase/include/fsp0pagecompress.h @@ -68,15 +68,6 @@ fsp_flags_get_page_compression_level( /*=================================*/ ulint flags); /*!< in: tablespace flags */ -/********************************************************************//** -Determine the tablespace is using atomic writes from dict_table_t::flags. -@return true if atomic writes is used, false if not */ -UNIV_INLINE -atomic_writes_t -fsp_flags_get_atomic_writes( -/*========================*/ - ulint flags); /*!< in: tablespace flags */ - #ifndef UNIV_NONINL #include "fsp0pagecompress.ic" #endif diff --git a/storage/innobase/include/fsp0pagecompress.ic b/storage/innobase/include/fsp0pagecompress.ic index a3971da6772..0915fae4b92 100644 --- a/storage/innobase/include/fsp0pagecompress.ic +++ b/storage/innobase/include/fsp0pagecompress.ic @@ -49,17 +49,6 @@ fsp_flags_get_page_compression_level( return(FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags)); } -/********************************************************************//** -Determine the tablespace is using atomic writes from dict_table_t::flags. -@return true if atomic writes is used, false if not */ -UNIV_INLINE -atomic_writes_t -fsp_flags_get_atomic_writes( -/*========================*/ - ulint flags) /*!< in: tablespace flags */ -{ - return((atomic_writes_t)FSP_FLAGS_GET_ATOMIC_WRITES(flags)); -} /*******************************************************************//** Find out wheather the page is index page or not @@ -186,25 +175,28 @@ fil_get_compression_alg_name( /*******************************************************************//** Returns the atomic writes flag of the space, or false if the space is not using atomic writes. The tablespace must be cached in the memory cache. -@return atomic writes table option value */ +@return 1 if atomic writes can be used for the file */ UNIV_INLINE -atomic_writes_t +bool fil_space_get_atomic_writes( /*========================*/ ulint id) /*!< in: space id */ { - ulint flags; + struct fil_space_t* space; + bool ret= 0; - flags = fil_space_get_flags(id); + ut_ad(fil_system); - if (flags && flags != ULINT_UNDEFINED) { + mutex_enter(&fil_system->mutex); - return((atomic_writes_t)fsp_flags_get_atomic_writes(flags)); - } + if ((space = fil_space_get_by_id(id))) + ret= space->atomic_write_supported; - return((atomic_writes_t)0); + mutex_exit(&fil_system->mutex); + return(ret); } + /*******************************************************************//** Find out wheather the page is page compressed with lzo method @return true if page is page compressed with lzo method, false if not */ diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 5755707d710..58cc1ff8d3e 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -79,13 +79,6 @@ Created 10/21/1995 Heikki Tuuri bool innodb_calling_exit; #endif /* UNIV_DEBUG */ -#if defined(UNIV_LINUX) && defined(HAVE_SYS_IOCTL_H) -# include -# ifndef DFS_IOCTL_ATOMIC_WRITE_SET -# define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) -# endif -#endif - #if defined(UNIV_LINUX) && defined(HAVE_SYS_STATVFS_H) #include #endif @@ -3310,26 +3303,6 @@ os_file_create_simple_func( } #endif /* USE_FILE_LOCK */ - /* If we have proper file handle and atomic writes should be used, - try to set atomic writes and if that fails when creating a new - table, produce a error. If atomic writes are used on existing - file, ignore error and use traditional writes for that file */ - /* JAN: TODO: ATOMIC WRITES - if (file != -1 - && (awrites == ATOMIC_WRITES_ON || - (srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT)) - && !os_file_set_atomic_writes(name, file)) { - if (create_mode == OS_FILE_CREATE) { - fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n"); - close(file); - os_file_delete_if_exists_func(name); - *success = FALSE; - file = -1; - } - } - */ - - return(file); } @@ -3682,24 +3655,6 @@ os_file_create_func( } #endif /* USE_FILE_LOCK */ - /* If we have proper file handle and atomic writes should be used, - try to set atomic writes and if that fails when creating a new - table, produce a error. If atomic writes are used on existing - file, ignore error and use traditional writes for that file */ - /* JAN: TODO: ATOMIC WRITES - if (file != -1 && type == OS_DATA_FILE - && (awrites == ATOMIC_WRITES_ON || - (srv_use_atomic_writes && awrites == ATOMIC_WRITES_DEFAULT)) - && !os_file_set_atomic_writes(name, file)) { - if (create_mode == OS_FILE_CREATE) { - fprintf(stderr, "InnoDB: Error: Can't create file using atomic writes\n"); - close(file); - os_file_delete_if_exists_func(name); - *success = FALSE; - file = -1; - } - } - */ return(file); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 708356512be..56576c2f29e 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -675,13 +675,6 @@ srv_undo_tablespace_open( os_offset_t size; fil_space_t* space; -#ifdef UNIV_LINUX - const bool atomic_write = !srv_use_doublewrite_buf - && fil_fusionio_enable_atomic_write(fh); -#else - const bool atomic_write = false; -#endif - size = os_file_get_size(fh); ut_a(size != (os_offset_t) -1); @@ -699,7 +692,7 @@ srv_undo_tablespace_open( /* Set the compressed page size to 0 (non-compressed) */ flags = fsp_flags_init( - univ_page_size, false, false, false, false, false, 0, ATOMIC_WRITES_DEFAULT); + univ_page_size, false, false, false, false, false, 0, 0); space = fil_space_create( undo_name, space_id, flags, FIL_TYPE_TABLESPACE, NULL, true); @@ -713,7 +706,7 @@ srv_undo_tablespace_open( the unit has been scaled to pages and page number is always 32 bits. */ if (fil_node_create( - name, (ulint) n_pages, space, false, atomic_write)) { + name, (ulint) n_pages, space, false, TRUE)) { err = DB_SUCCESS; } diff --git a/support-files/build-tags b/support-files/build-tags index 87f320ba5f5..03b243ee8cc 100755 --- a/support-files/build-tags +++ b/support-files/build-tags @@ -8,9 +8,9 @@ then echo client storage dbug libmysql sql-common \ sql extra mysys mysys_ssl strings regex pcre vio include \ tools unittest plugin libmysqld | \ - xargs -n1 git ls-files | \ + xargs -n1 git ls-files | grep -v '\.jar$' | \ xargs etags -o TAGS --append else - find . -type f | + find . -type f ! -name "*.jar" | xargs etags -o TAGS --append fi From 1afb17047a61d7666d4c3d6e5fae97ec526693ba Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Dec 2016 18:06:49 +0200 Subject: [PATCH 050/167] Fixed bugs found by mysql-test-run: - privilege_table_io.test didn't properly reset roles_mapping - Fixed memory allocation problem with CHECK CONSTRAINT, found when running --valgrind main.check_constraint --- mysql-test/suite/perfschema/r/privilege_table_io.result | 1 + mysql-test/suite/perfschema/t/privilege_table_io.test | 1 + sql/table.cc | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/perfschema/r/privilege_table_io.result b/mysql-test/suite/perfschema/r/privilege_table_io.result index f1f0946cb90..aeacd0ba011 100644 --- a/mysql-test/suite/perfschema/r/privilege_table_io.result +++ b/mysql-test/suite/perfschema/r/privilege_table_io.result @@ -15,6 +15,7 @@ optimize table mysql.proxies_priv; optimize table mysql.tables_priv; optimize table mysql.procs_priv; optimize table mysql.servers; +optimize table mysql.roles_mapping; update performance_schema.setup_consumers set enabled='YES'; update performance_schema.setup_objects set enabled='YES' where object_type='TABLE' and object_schema= 'mysql'; diff --git a/mysql-test/suite/perfschema/t/privilege_table_io.test b/mysql-test/suite/perfschema/t/privilege_table_io.test index 35c49bf33fb..8f06be5075e 100644 --- a/mysql-test/suite/perfschema/t/privilege_table_io.test +++ b/mysql-test/suite/perfschema/t/privilege_table_io.test @@ -24,6 +24,7 @@ optimize table mysql.proxies_priv; optimize table mysql.tables_priv; optimize table mysql.procs_priv; optimize table mysql.servers; +optimize table mysql.roles_mapping; --enable_result_log # Start recording events diff --git a/sql/table.cc b/sql/table.cc index 6d11ac3d3eb..5c9d4805943 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3110,7 +3110,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, share->default_expressions +1)* sizeof(Field*)), &check_constraint_ptr, - (uint) ((share->table_check_constraints + 1)* + (uint) ((share->table_check_constraints + + share->field_check_constraints + 1)* sizeof(Virtual_column_info*)), NullS)) goto err; From 1628a2ae27cfc8b96e4b50d85d430955625e2d88 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 27 Dec 2016 01:30:20 +0200 Subject: [PATCH 051/167] Fixed issues found by buildbot - MDEV-11621 rpl.rpl_gtid_stop_start fails sporadically in buildbot - MDEV-11620 rpl.rpl_upgrade_master_info fails sporadically in buildbot The issue above was probably that the build machine was overworked and the shutdown took longer than 30 resp 10 seconds, which caused MyISAM tables to be marked as crashed. Fixed by flushing myisam tables before doing a forced shutdown/kill. I also increased timeout for forced shutdown from 10 seconds to 60 seconds to fix other possible issues on slow machines. Fixed also some compiler warnings --- client/mysqltest.cc | 1 + mysql-test/include/rpl_stop_server.inc | 4 ++-- mysql-test/suite/rpl/r/rpl_gtid_stop_start.result | 6 ++++++ mysql-test/suite/rpl/r/rpl_upgrade_master_info.result | 5 +++++ mysql-test/suite/rpl/t/rpl_gtid_stop_start.test | 6 ++++++ mysql-test/suite/rpl/t/rpl_upgrade_master_info.test | 5 +++++ sql/compat56.cc | 6 +++--- sql/item_jsonfunc.cc | 2 +- sql/log_event.cc | 8 ++++---- storage/innobase/row/row0ftsort.cc | 4 ---- storage/mroonga/vendor/groonga/lib/proc.c | 2 +- 11 files changed, 34 insertions(+), 15 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index f0c56bc639c..702098fc5bc 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5156,6 +5156,7 @@ uint get_errcode_from_name(const char *error_name, const char *error_end) handler_error_names))) return tmp; die("Unknown SQL error name '%s'", error_name); + return 0; // Keep compiler happy } const char *unknown_error= ""; diff --git a/mysql-test/include/rpl_stop_server.inc b/mysql-test/include/rpl_stop_server.inc index e1f8839dd69..978cfec1885 100644 --- a/mysql-test/include/rpl_stop_server.inc +++ b/mysql-test/include/rpl_stop_server.inc @@ -47,8 +47,8 @@ if ($rpl_debug) --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.$rpl_server_number.expect # Send shutdown to the connected server and give -# it 10 seconds to die before zapping it -shutdown_server 10; +# it 60 seconds to die before zapping it +shutdown_server 60; --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result index db2f40fd495..3ba17822319 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result @@ -55,6 +55,7 @@ INSERT INTO t1 VALUES(5); include/save_master_gtid.inc connection server_2; include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 @@ -87,6 +88,7 @@ a connection server_1; INSERT INTO t1 VALUES (7); connection server_2; +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 @@ -116,6 +118,7 @@ include/start_slave.inc connection server_1; INSERT INTO t1 VALUES (8); connection server_2; +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 @@ -142,6 +145,7 @@ Error 1286 Unknown storage engine 'InnoDB' connection server_1; INSERT INTO t1 VALUES (9); connection server_2; +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 @@ -171,6 +175,7 @@ domain_id COUNT(*) connection server_1; INSERT INTO t1 VALUES (11); connection server_2; +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id COUNT(*) 0 2 @@ -180,6 +185,7 @@ connection server_1; INSERT INTO t1 VALUES (12); INSERT INTO t1 VALUES (13); connection server_2; +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id COUNT(*) 0 2 diff --git a/mysql-test/suite/rpl/r/rpl_upgrade_master_info.result b/mysql-test/suite/rpl/r/rpl_upgrade_master_info.result index 3e737267fbd..ffa041efd27 100644 --- a/mysql-test/suite/rpl/r/rpl_upgrade_master_info.result +++ b/mysql-test/suite/rpl/r/rpl_upgrade_master_info.result @@ -14,6 +14,7 @@ connection slave; CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1; include/start_slave.inc include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1; a 1 @@ -27,6 +28,7 @@ connection slave; CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1; include/start_slave.inc include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 @@ -41,6 +43,7 @@ connection slave; CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1; include/start_slave.inc include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 @@ -56,6 +59,7 @@ connection slave; CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1; include/start_slave.inc include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 @@ -72,6 +76,7 @@ connection slave; CHANGE MASTER TO master_host='127.0.0.1', master_port=SERVER_MYPORT_1; include/start_slave.inc include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; a 1 diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index b57714aaa57..65b13b57f2d 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -92,6 +92,7 @@ INSERT INTO t1 VALUES(5); --connection server_2 --source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; --echo *** Test that @@gtid_slave_pos and @@gtid_current_pos are correctly loaded even if slave threads have not started. *** @@ -136,6 +137,7 @@ INSERT INTO t1 VALUES (7); --connection server_2 --sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; # Now we restart the slave server. When it restarts, there is nothing new @@ -177,6 +179,7 @@ INSERT INTO t1 VALUES (8); --connection server_2 --sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; --source include/stop_slave.inc @@ -210,6 +213,7 @@ INSERT INTO t1 VALUES (9); --connection server_2 --sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; # Put things back as they were. @@ -248,6 +252,7 @@ INSERT INTO t1 VALUES (11); --connection server_2 --sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect @@ -270,6 +275,7 @@ INSERT INTO t1 VALUES (13); --connection server_2 --sync_with_master +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id; diff --git a/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test b/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test index e81e7c0d714..42b375c4579 100644 --- a/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test +++ b/mysql-test/suite/rpl/t/rpl_upgrade_master_info.test @@ -29,6 +29,7 @@ INSERT INTO t1 VALUES (1); eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; --source include/start_slave.inc --source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1; --source include/stop_slave.inc @@ -54,6 +55,7 @@ INSERT INTO t1 VALUES (2); eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; --source include/start_slave.inc --source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; --source include/stop_slave.inc @@ -79,6 +81,7 @@ INSERT INTO t1 VALUES (3); eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; --source include/start_slave.inc --source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; --source include/stop_slave.inc @@ -104,6 +107,7 @@ INSERT INTO t1 VALUES (4); eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; --source include/start_slave.inc --source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; --source include/stop_slave.inc @@ -129,6 +133,7 @@ INSERT INTO t1 VALUES (5); eval CHANGE MASTER TO master_host='127.0.0.1', master_port=$SERVER_MYPORT_1; --source include/start_slave.inc --source include/sync_with_master_gtid.inc +FLUSH NO_WRITE_TO_BINLOG TABLES; SELECT * FROM t1 ORDER BY a; --source include/stop_slave.inc diff --git a/sql/compat56.cc b/sql/compat56.cc index 3bd6b21a154..704d1db9a98 100644 --- a/sql/compat56.cc +++ b/sql/compat56.cc @@ -65,7 +65,7 @@ void TIME_from_longlong_time_packed(MYSQL_TIME *ltime, longlong tmp) long hms; if ((ltime->neg= (tmp < 0))) tmp= -tmp; - hms= MY_PACKED_TIME_GET_INT_PART(tmp); + hms= (long) MY_PACKED_TIME_GET_INT_PART(tmp); ltime->year= (uint) 0; ltime->month= (uint) 0; ltime->day= (uint) 0; @@ -264,11 +264,11 @@ void TIME_from_longlong_datetime_packed(MYSQL_TIME *ltime, longlong tmp) ltime->day= ymd % (1 << 5); ltime->month= ym % 13; - ltime->year= ym / 13; + ltime->year= (uint) (ym / 13); ltime->second= hms % (1 << 6); ltime->minute= (hms >> 6) % (1 << 6); - ltime->hour= (hms >> 12); + ltime->hour= (uint) (hms >> 12); ltime->time_type= MYSQL_TIMESTAMP_DATETIME; } diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 9b9490a0cbc..a500170ead0 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -2307,7 +2307,7 @@ bool Item_func_json_search::fix_fields(THD *thd, Item **ref) } -static const uint SQR_MAX_BLOB_WIDTH= sqrt(MAX_BLOB_WIDTH); +static const uint SQR_MAX_BLOB_WIDTH= (uint) sqrt(MAX_BLOB_WIDTH); void Item_func_json_search::fix_length_and_dec() { diff --git a/sql/log_event.cc b/sql/log_event.cc index 85dce217743..0af348ab453 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1794,7 +1794,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, if (fdle->crypto_data.scheme) { uchar iv[BINLOG_IV_LENGTH]; - fdle->crypto_data.set_iv(iv, my_b_tell(file) - data_len); + fdle->crypto_data.set_iv(iv, (uint32) (my_b_tell(file) - data_len)); char *newpkt= (char*)my_malloc(data_len + ev_offset + 1, MYF(MY_WME)); if (!newpkt) @@ -7058,7 +7058,7 @@ Binlog_checkpoint_log_event::Binlog_checkpoint_log_event( uint8 header_size= description_event->common_header_len; uint8 post_header_len= description_event->post_header_len[BINLOG_CHECKPOINT_EVENT-1]; - if (event_len < header_size + post_header_len || + if (event_len < (uint) header_size + (uint) post_header_len || post_header_len < BINLOG_CHECKPOINT_HEADER_LEN) return; buf+= header_size; @@ -7096,7 +7096,7 @@ Gtid_log_event::Gtid_log_event(const char *buf, uint event_len, { uint8 header_size= description_event->common_header_len; uint8 post_header_len= description_event->post_header_len[GTID_EVENT-1]; - if (event_len < header_size + post_header_len || + if (event_len < (uint) header_size + (uint) post_header_len || post_header_len < GTID_HEADER_LEN) return; @@ -7421,7 +7421,7 @@ Gtid_list_log_event::Gtid_list_log_event(const char *buf, uint event_len, uint32 val; uint8 header_size= description_event->common_header_len; uint8 post_header_len= description_event->post_header_len[GTID_LIST_EVENT-1]; - if (event_len < header_size + post_header_len || + if (event_len < (uint) header_size + (uint) post_header_len || post_header_len < GTID_LIST_HEADER_LEN) return; diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 0d216d584d7..3179c63f162 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -793,7 +793,6 @@ fts_parallel_tokenization( mem_heap_t* blob_heap = NULL; fts_doc_t doc; dict_table_t* table = psort_info->psort_common->new_table; - dict_field_t* idx_field; fts_tokenize_ctx_t t_ctx; ulint retried = 0; dberr_t error = DB_SUCCESS; @@ -822,9 +821,6 @@ fts_parallel_tokenization( doc.charset = fts_index_get_charset( psort_info->psort_common->dup->index); - idx_field = dict_index_get_nth_field( - psort_info->psort_common->dup->index, 0); - block = psort_info->merge_block; crypt_block = psort_info->crypt_block; crypt_data = psort_info->psort_common->crypt_data; diff --git a/storage/mroonga/vendor/groonga/lib/proc.c b/storage/mroonga/vendor/groonga/lib/proc.c index 86b0fd58c02..ba858de6f2a 100644 --- a/storage/mroonga/vendor/groonga/lib/proc.c +++ b/storage/mroonga/vendor/groonga/lib/proc.c @@ -713,7 +713,7 @@ grn_select_drilldown(grn_ctx *ctx, grn_obj *table, { uint32_t i; for (i = 0; i < n_keys; i++) { - grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0}; + grn_table_group_result g = {NULL, 0, 0, 1, GRN_TABLE_GROUP_CALC_COUNT, 0, 0 ,0}; uint32_t n_hits; int offset; int limit; From 7454087d071d1c1954c51f08ccd7a29682cd9da8 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 27 Dec 2016 17:18:10 +0200 Subject: [PATCH 052/167] Revert "bugfix: UPDATE and virtual BLOBs" This reverts commit f73bdb685d77b944f4565e0a97778faa30999145. --- sql/field.h | 3 -- sql/sql_class.h | 99 +---------------------------------------------- sql/sql_insert.cc | 36 ++--------------- sql/sql_insert.h | 1 + sql/sql_load.cc | 6 --- sql/sql_update.cc | 18 --------- 6 files changed, 7 insertions(+), 156 deletions(-) diff --git a/sql/field.h b/sql/field.h index fd62218f144..0d278968eb5 100644 --- a/sql/field.h +++ b/sql/field.h @@ -3339,9 +3339,6 @@ public: uint max_packed_col_length(uint max_length); void free() { value.free(); } inline void clear_temporary() { bzero((uchar*) &value, sizeof(value)); } - inline bool owns_ptr(uchar* p) const { return p == (uchar*)value.ptr(); } - inline void own_value_ptr() - { value.reset((char*)get_ptr(), get_length(), get_length(), value.charset()); } uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } diff --git a/sql/sql_class.h b/sql/sql_class.h index ef10d7e4053..a55e1739318 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -201,99 +201,6 @@ typedef struct st_user_var_events bool unsigned_flag; } BINLOG_USER_VAR_EVENT; - -/* - When updating a table with virtual BLOB columns, the following might happen: - - an old record is read from the table, it has no vcol blob. - - update_virtual_fields() is run, vcol blob gets its value into the - record. But only a pointer to the value is in the table->record[0], - the value is in Field_blob::value String (or, it can be elsewhere!) - - store_record(table,record[1]), old record now is in record[1] - - fill_record() prepares new values in record[0], vcol blob is updated, - new value replaces the old one in the Field_blob::value - - now both record[1] and record[0] have a pointer that points to the - *new* vcol blob value. Or record[1] has a pointer to nowhere if - Field_blob::value had to realloc. - - To resolve this we unlink vcol blobs from the pointer to the - data (in the record[1]). The orphan memory must be freed manually - (but, again, only if it was owned by Field_blob::value String). - - With REPLACE and INSERT ... ON DUP KEY UPATE it's even more complex. - There is no store_record(table,record[1]), instead the row is read - directly into record[1]. -*/ -struct BLOB_VALUE_ORPHANAGE { - MY_BITMAP map; - TABLE *table; - BLOB_VALUE_ORPHANAGE() { map.bitmap= NULL; } - ~BLOB_VALUE_ORPHANAGE() { free(); } - bool init(TABLE *table_arg) - { - table= table_arg; - if (table->s->virtual_fields && table->s->blob_fields) - return bitmap_init(&map, NULL, table->s->virtual_fields, FALSE); - map.bitmap= NULL; - return 0; - } - void free() { bitmap_free(&map); } - - /** Remove blob's ownership from blob value memory - - @note the memory becomes orphaned, it needs to be freed using - free_orphans() or re-attached back to blobs using adopt_orphans() - */ - void make_orphans() - { - DBUG_ASSERT(!table || !table->s->virtual_fields || !table->s->blob_fields || map.bitmap); - if (!map.bitmap) - return; - for (Field **ptr=table->vfield; *ptr; ptr++) - { - Field_blob *vb= (Field_blob*)(*ptr); - if (!(vb->flags & BLOB_FLAG) || !vb->owns_ptr(vb->get_ptr())) - continue; - bitmap_set_bit(&map, ptr - table->vfield); - vb->clear_temporary(); - } - } - - /** Frees orphaned blob values - - @note It is assumed that value pointers are in table->record[1], while - Field_blob::ptr's point to table->record[0] as usual - */ - void free_orphans() - { - DBUG_ASSERT(!table || !table->s->virtual_fields || !table->s->blob_fields || map.bitmap); - if (!map.bitmap) - return; - for (Field **ptr=table->vfield; *ptr; ptr++) - { - Field_blob *vb= (Field_blob*)(*ptr); - if (vb->flags & BLOB_FLAG && bitmap_fast_test_and_clear(&map, ptr - table->vfield)) - my_free(vb->get_ptr(table->s->rec_buff_length)); - } - DBUG_ASSERT(bitmap_is_clear_all(&map)); - } - - /** Restores blob's ownership over previously orphaned values */ - void adopt_orphans() - { - DBUG_ASSERT(!table || !table->s->virtual_fields || !table->s->blob_fields || map.bitmap); - if (!map.bitmap) - return; - for (Field **ptr=table->vfield; *ptr; ptr++) - { - Field_blob *vb= (Field_blob*)(*ptr); - if (vb->flags & BLOB_FLAG && bitmap_fast_test_and_clear(&map, ptr - table->vfield)) - vb->own_value_ptr(); - } - DBUG_ASSERT(bitmap_is_clear_all(&map)); - } -}; - - /* The COPY_INFO structure is used by INSERT/REPLACE code. The schema of the row counting by the INSERT/INSERT ... ON DUPLICATE KEY @@ -306,7 +213,7 @@ struct BLOB_VALUE_ORPHANAGE { of the INSERT ... ON DUPLICATE KEY UPDATE no matter whether the row was actually changed or not. */ -struct COPY_INFO { +typedef struct st_copy_info { ha_rows records; /**< Number of processed records */ ha_rows deleted; /**< Number of deleted records */ ha_rows updated; /**< Number of updated records */ @@ -322,8 +229,7 @@ struct COPY_INFO { /* for VIEW ... WITH CHECK OPTION */ TABLE_LIST *view; TABLE_LIST *table_list; /* Normal table */ - BLOB_VALUE_ORPHANAGE vblobs0, vblobs1; // vcol blobs of record[0] and record[1] -}; +} COPY_INFO; class Key_part_spec :public Sql_alloc { @@ -5435,7 +5341,6 @@ class multi_update :public select_result_interceptor TABLE_LIST *update_tables, *table_being_updated; TABLE **tmp_tables, *main_table, *table_to_update; TMP_TABLE_PARAM *tmp_table_param; - BLOB_VALUE_ORPHANAGE *vblobs; ha_rows updated, found; List *fields, *values; List **fields_for_table, **values_for_table; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9c21cb74802..7b583e1ddec 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -812,11 +812,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, info.update_values= &update_values; info.view= (table_list->view ? table_list : 0); info.table_list= table_list; - if (duplic != DUP_ERROR) - { - info.vblobs0.init(table); - info.vblobs1.init(table); - } /* Count warnings for all inserts. @@ -1184,6 +1179,7 @@ values_loop_end: thd->lex->current_select->save_leaf_tables(thd); thd->lex->current_select->first_cond_optimization= 0; } + DBUG_RETURN(FALSE); abort: @@ -1695,12 +1691,9 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) } if (table->vfield) { - info->vblobs0.make_orphans(); table->move_fields(table->field, table->record[1], table->record[0]); table->update_virtual_fields(VCOL_UPDATE_INDEXED); - info->vblobs1.make_orphans(); table->move_fields(table->field, table->record[0], table->record[1]); - info->vblobs0.adopt_orphans(); } if (info->handle_duplicates == DUP_UPDATE) { @@ -1861,7 +1854,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) trg_error= 1; goto ok_or_after_trg_err; } - info->vblobs1.free_orphans(); /* Let us attempt do write_row() once more */ } } @@ -1912,7 +1904,6 @@ ok_or_after_trg_err: my_safe_afree(key,table->s->max_unique_length); if (!table->file->has_transactions()) thd->transaction.stmt.modified_non_trans_table= TRUE; - info->vblobs1.free_orphans(); DBUG_RETURN(trg_error); err: @@ -1924,7 +1915,6 @@ before_trg_err: if (key) my_safe_afree(key, table->s->max_unique_length); table->column_bitmaps_set(save_read_set, save_write_set); - info->vblobs1.free_orphans(); DBUG_RETURN(1); } @@ -3106,14 +3096,10 @@ static void free_delayed_insert_blobs(register TABLE *table) { for (Field **ptr=table->field ; *ptr ; ptr++) { - Field_blob *f= (Field_blob*)(*ptr); - if (f->flags & BLOB_FLAG) + if ((*ptr)->flags & BLOB_FLAG) { - if (f->vcol_info) - f->free(); - else - my_free(f->get_ptr()); - f->reset(); + my_free(((Field_blob *) (*ptr))->get_ptr()); + ((Field_blob *) (*ptr))->reset(); } } } @@ -3135,9 +3121,6 @@ bool Delayed_insert::handle_inserts(void) table->next_number_field=table->found_next_number_field; table->use_all_columns(); - info.vblobs0.init(table); - info.vblobs1.init(table); - THD_STAGE_INFO(&thd, stage_upgrading_lock); if (thr_upgrade_write_delay_lock(*thd.lock->locks, delayed_lock, thd.variables.lock_wait_timeout)) @@ -3244,8 +3227,6 @@ bool Delayed_insert::handle_inserts(void) if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); thd.clear_error(); // reset error for binlog - if (table->vfield) - table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); if (write_record(&thd, table, &info)) { info.error_count++; // Ignore errors @@ -3352,8 +3333,6 @@ bool Delayed_insert::handle_inserts(void) DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop")); goto err; } - info.vblobs0.free(); - info.vblobs1.free(); query_cache_invalidate3(&thd, table, 1); mysql_mutex_lock(&mutex); DBUG_RETURN(0); @@ -3362,8 +3341,6 @@ bool Delayed_insert::handle_inserts(void) #ifndef DBUG_OFF max_rows= 0; // For DBUG output #endif - info.vblobs0.free(); - info.vblobs1.free(); /* Remove all not used rows */ mysql_mutex_lock(&mutex); while ((row=rows.get())) @@ -3611,11 +3588,6 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) restore_record(table,s->default_values); // Get empty record table->reset_default_fields(); table->next_number_field=table->found_next_number_field; - if (info.handle_duplicates != DUP_ERROR) - { - info.vblobs0.init(table); - info.vblobs1.init(table); - } #ifdef HAVE_REPLICATION if (thd->rgi_slave && diff --git a/sql/sql_insert.h b/sql/sql_insert.h index 5ec1846425d..cbfc1ea9dcd 100644 --- a/sql/sql_insert.h +++ b/sql/sql_insert.h @@ -21,6 +21,7 @@ /* Instead of including sql_lex.h we add this typedef here */ typedef List List_item; +typedef struct st_copy_info COPY_INFO; bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table, List &fields, List_item *values, diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c25e73e7346..6f0e97a61c9 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -537,12 +537,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, !(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))) ? (*escaped)[0] : INT_MAX; - if (handle_duplicates != DUP_ERROR) - { - info.vblobs0.init(table); - info.vblobs1.init(table); - } - READ_INFO read_info(thd, file, tot_length, ex->cs ? ex->cs : thd->variables.collation_database, *field_term,*ex->line_start, *ex->line_term, *enclosed, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 1f1af7f2660..05f7080609a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -273,7 +273,6 @@ int mysql_update(THD *thd, SORT_INFO *file_sort= 0; READ_RECORD info; SELECT_LEX *select_lex= &thd->lex->select_lex; - BLOB_VALUE_ORPHANAGE vblobs; ulonglong id; List all_fields; killed_state killed_status= NOT_KILLED; @@ -725,8 +724,6 @@ int mysql_update(THD *thd, table->reset_default_fields(); - vblobs.init(table); - /* We can use compare_record() to optimize away updates if the table handler is returning all columns OR if @@ -748,9 +745,6 @@ int mysql_update(THD *thd, explain->tracker.on_record_after_where(); store_record(table,record[1]); - - vblobs.make_orphans(); - if (fill_record_n_invoke_before_triggers(thd, table, fields, values, 0, TRG_EVENT_UPDATE)) break; /* purecov: inspected */ @@ -910,9 +904,7 @@ int mysql_update(THD *thd, error= 1; break; } - vblobs.free_orphans(); } - vblobs.free_orphans(); ANALYZE_STOP_TRACKING(&explain->command_tracker); table->auto_increment_field_not_null= FALSE; dup_key_found= 0; @@ -1760,8 +1752,6 @@ int multi_update::prepare(List ¬_used_values, table_count); values_for_table= (List_item **) thd->alloc(sizeof(List_item *) * table_count); - vblobs= (BLOB_VALUE_ORPHANAGE *)thd->calloc(sizeof(*vblobs) * table_count); - if (thd->is_fatal_error) DBUG_RETURN(1); for (i=0 ; i < table_count ; i++) @@ -1794,7 +1784,6 @@ int multi_update::prepare(List ¬_used_values, TABLE *table= ((Item_field*)(fields_for_table[i]->head()))->field->table; switch_to_nullable_trigger_fields(*fields_for_table[i], table); switch_to_nullable_trigger_fields(*values_for_table[i], table); - vblobs[i].init(table); } } copy_field= new Copy_field[max_fields]; @@ -2076,8 +2065,6 @@ multi_update::~multi_update() free_tmp_table(thd, tmp_tables[cnt]); tmp_table_param[cnt].cleanup(); } - vblobs[cnt].free_orphans(); - vblobs[cnt].free(); } } if (copy_field) @@ -2123,9 +2110,7 @@ int multi_update::send_data(List ¬_used_values) can_compare_record= records_are_comparable(table); table->status|= STATUS_UPDATED; - vblobs[offset].free_orphans(); store_record(table,record[1]); - vblobs[offset].make_orphans(); if (fill_record_n_invoke_before_triggers(thd, table, *fields_for_table[offset], *values_for_table[offset], 0, @@ -2342,7 +2327,6 @@ int multi_update::do_updates() goto err; } table->file->extra(HA_EXTRA_NO_CACHE); - empty_record(table); check_opt_it.rewind(); while(TABLE *tbl= check_opt_it++) @@ -2416,9 +2400,7 @@ int multi_update::do_updates() goto err2; table->status|= STATUS_UPDATED; - vblobs[offset].free_orphans(); store_record(table,record[1]); - vblobs[offset].make_orphans(); /* Copy data from temporary table to current table */ for (copy_field_ptr=copy_field; From ea1b25046c81db8fdf59130126d57cfb42737ba5 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 30 Dec 2016 11:07:44 +0200 Subject: [PATCH 053/167] New simpler bugfix for UPDATE and virtual BLOBs When updating a table with virtual BLOB columns, the following might happen: - an old record is read from the table, it has no virtual blob values - update_virtual_fields() is run, vcol blob gets its value into the record. But only a pointer to the value is in the table->record[0], the value is in Field_blob::value String (but it doesn't have to be! it can be in the record, if the column is just a copy of another columns: ... b VARCHAR, c BLOB AS (b) ...) - store_record(table,record[1]), old record now is in record[1] - fill_record() prepares new values in record[0], vcol blob is updated, new value replaces the old one in the Field_blob::value - now both record[1] and record[0] have a pointer that points to the *new* vcol blob value. Or record[1] has a pointer to nowhere if Field_blob::value had to realloc. To fix this I have introduced a new String object 'read_value' in Field_blob. When updating virtual columns when a row has been read, the allocated value is stored in 'read_value' instead of 'value'. The allocated blobs for the new row is stored in 'value' as before. I also made, as a safety precaution, the insert delayed handling of blobs more general by using value to store strings instead of the record. This ensures that virtual functions on delayed insert should work in as in the case of normal insert. Triggers are now properly updating the read, write and vcol maps for used fields. This means that we don't need VCOL_UPDATE_FOR_READ_WRITE anymore and there is no need for any other special handling of triggers in update_virtual_fields(). To be able to test how many times virtual fields are invoked, I also relaxed rules that one can use local (@) variables in DEFAULT and non persistent virtual field expressions. --- mysql-test/r/default.result | 8 +- mysql-test/suite/vcol/inc/vcol_trigger_sp.inc | 132 +++++++++++++ mysql-test/suite/vcol/r/not_supported.result | 4 +- .../vcol/r/vcol_trigger_sp_innodb.result | 179 ++++++++++++++++++ .../vcol/r/vcol_trigger_sp_myisam.result | 179 ++++++++++++++++++ mysql-test/suite/vcol/t/not_supported.test | 8 +- mysql-test/t/default.test | 8 +- sql/field.h | 40 +++- sql/item_func.cc | 2 +- sql/sql_base.cc | 13 +- sql/sql_insert.cc | 41 +++- sql/sql_trigger.cc | 6 + sql/sql_update.cc | 15 +- sql/table.cc | 46 ++++- sql/table.h | 4 +- storage/innobase/handler/handler0alter.cc | 2 +- storage/myisam/ha_myisam.cc | 8 +- 17 files changed, 643 insertions(+), 52 deletions(-) diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index dc7a33d6b9c..ac449d44fee 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -480,6 +480,10 @@ a b 2 2 3 4 drop table t1; +CREATE OR REPLACE TABLE t1 (a INT DEFAULT @v); +drop table t1; +CREATE TABLE t1 (a INT DEFAULT @v:=1); +drop table t1; # # Error handling # @@ -516,10 +520,6 @@ CREATE TABLE t1 (a INT DEFAULT(?)); Got one of the listed errors CREATE TABLE t1 (a INT DEFAULT (b), b INT DEFAULT(a)); ERROR 01000: Expression for field `a` is refering to uninitialized field `b` -CREATE TABLE t1 (a INT DEFAULT @v); -ERROR HY000: Function or expression '@v' cannot be used in the DEFAULT clause of `a` -CREATE TABLE t1 (a INT DEFAULT @v:=1); -ERROR HY000: Function or expression '@v' cannot be used in the DEFAULT clause of `a` CREATE TABLE t1 (a INT DEFAULT(NAME_CONST('xxx', 'yyy')); ERROR HY000: Function or expression 'name_const()' cannot be used in the DEFAULT clause of `a` CREATE TABLE t1 (a INT DEFAULT COUNT(*)); diff --git a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc index eb7e6ad32b9..f807405d18d 100644 --- a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc +++ b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc @@ -149,3 +149,135 @@ DROP TRIGGER t1_ins_aft; DROP TRIGGER t1_del_bef; DROP TABLE t1,t2; +--echo # +--echo # Examine the number of times triggers are recalculated for updates +--echo # + +CREATE TABLE t1 ( + a INTEGER UNSIGNED NULL DEFAULT NULL, + b CHAR(10) NULL DEFAULT NULL, + c blob NULL DEFAULT NULL, + blob_a blob GENERATED ALWAYS AS (last_value(@a:=@a+1,a)) VIRTUAL, + blob_b blob GENERATED ALWAYS AS (last_value(@b:=@b+1,b)) VIRTUAL, + blob_c blob GENERATED ALWAYS AS (last_value(@c:=@c+1,c)) VIRTUAL +); + +DELIMITER |; +CREATE TRIGGER t1_ins + BEFORE INSERT + ON t1 + FOR EACH ROW +BEGIN + IF NEW.b IS NULL THEN + SET NEW.b="generated before insert"; + END IF; +END | + +CREATE TRIGGER t1_update + BEFORE UPDATE + ON t1 + FOR EACH ROW +BEGIN + IF NEW.b IS NULL or NEW.c IS NULL THEN + SET NEW.b="generated before update"; + SET NEW.c="generated before update"; + END IF; +END | + +DELIMITER ;| + +--echo # Inserts +set @a=0,@b=0,@c=0; + +insert into t1 (a) values(1); +insert into t1 (a,b) values(2, "*2*"); +insert into t1 (a,b,c) values(3, "*3*", "**3**"); +insert into t1 (a,c) values(4, "**4**"); +select * from t1; +select @a,@b,@c; +select * from t1; +select @a,@b,@c; +select a,b,c from t1; +select @a,@b,@c; +select a,b,c,blob_a from t1; +select @a,@b,@c; + +--echo # updates +set @a=0,@b=0,@c=0; + +update t1 set a=a+100 where a=1; +update t1 set a=a+100, b="*102*" where a=2; +update t1 set a=a+100, b=NULL where a=3; +update t1 set a=a+100, b="invisible", c=NULL where a=4; +select @a,@b,@c; +select * from t1; + +drop trigger t1_ins; +drop trigger t1_update; +drop table t1; + +--echo # +--echo # Same test, but with virtual keys +--echo # + +CREATE TABLE t1 ( + a INTEGER UNSIGNED NULL DEFAULT NULL, + b CHAR(10) NULL DEFAULT NULL, + c blob NULL DEFAULT NULL, + blob_a blob GENERATED ALWAYS AS (a) VIRTUAL, + blob_b blob GENERATED ALWAYS AS (b) VIRTUAL, + blob_c blob GENERATED ALWAYS AS (c) VIRTUAL, + key (a), + key (blob_a(10)), + key (blob_b(10)), + key (blob_c(10)) +); + +DELIMITER |; +CREATE TRIGGER t1_ins + BEFORE INSERT + ON t1 + FOR EACH ROW +BEGIN + IF NEW.b IS NULL THEN + SET NEW.b="generated before insert"; + END IF; +END | + +CREATE TRIGGER t1_update + BEFORE UPDATE + ON t1 + FOR EACH ROW +BEGIN + IF NEW.b IS NULL or NEW.c IS NULL THEN + SET NEW.b="generated before update"; + SET NEW.c="generated before update"; + END IF; +END | + +DELIMITER ;| + +--echo # Inserts +insert into t1 (a) values(1); +insert into t1 (a,b) values(2, "*2*"); +insert into t1 (a,b,c) values(3, "*3*", "**3**"); +insert into t1 (a,c) values(4, "**4**"); +select * from t1; +select @a,@b,@c; +select * from t1; +select @a,@b,@c; +select a,b,c from t1; +select @a,@b,@c; +select a,b,c,blob_a from t1; +select @a,@b,@c; + +--echo # updates +update t1 set a=a+100 where a=1; +update t1 set a=a+100, b="*102*" where a=2; +update t1 set a=a+100, b=NULL where a=3; +update t1 set a=a+100, b="invisible", c=NULL where a=4; +select * from t1; + +drop trigger t1_ins; +drop trigger t1_update; +drop table t1; diff --git a/mysql-test/suite/vcol/r/not_supported.result b/mysql-test/suite/vcol/r/not_supported.result index f2c98706dd6..c804cf220d2 100644 --- a/mysql-test/suite/vcol/r/not_supported.result +++ b/mysql-test/suite/vcol/r/not_supported.result @@ -4,14 +4,14 @@ set time_zone='+10:00'; set div_precision_increment=20; create table t1 (a int, b int, v decimal(20,19) as (a/3)); create table t2 (a int, b int, v int as (a+@a)); -ERROR HY000: Function or expression '@a' cannot be used in the GENERATED ALWAYS AS clause of `v` +drop table t2; create table t2 (a int, b int, v int as (a+@a) PERSISTENT); ERROR HY000: Function or expression '@a' cannot be used in the GENERATED ALWAYS AS clause of `v` create table t3_ok (a int, b int, v int as (a+@@error_count)); create table t3 (a int, b int, v int as (a+@@error_count) PERSISTENT); ERROR HY000: Function or expression '@@error_count' cannot be used in the GENERATED ALWAYS AS clause of `v` create table t4 (a int, b int, v int as (@a:=a)); -ERROR HY000: Function or expression '@a' cannot be used in the GENERATED ALWAYS AS clause of `v` +drop table t4; create table t4 (a int, b int, v int as (@a:=a) PERSISTENT); ERROR HY000: Function or expression '@a' cannot be used in the GENERATED ALWAYS AS clause of `v` create table t8 (a int, b int, v varchar(100) as (from_unixtime(a))); diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result index 1d78bbf50e4..0a82f1006e7 100644 --- a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result @@ -125,3 +125,182 @@ c DROP TRIGGER t1_ins_aft; DROP TRIGGER t1_del_bef; DROP TABLE t1,t2; +# +# Examine the number of times triggers are recalculated for updates +# +CREATE TABLE t1 ( +a INTEGER UNSIGNED NULL DEFAULT NULL, +b CHAR(10) NULL DEFAULT NULL, +c blob NULL DEFAULT NULL, +blob_a blob GENERATED ALWAYS AS (last_value(@a:=@a+1,a)) VIRTUAL, +blob_b blob GENERATED ALWAYS AS (last_value(@b:=@b+1,b)) VIRTUAL, +blob_c blob GENERATED ALWAYS AS (last_value(@c:=@c+1,c)) VIRTUAL +); +CREATE TRIGGER t1_ins +BEFORE INSERT +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL THEN +SET NEW.b="generated before insert"; +END IF; +END | +CREATE TRIGGER t1_update +BEFORE UPDATE +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL or NEW.c IS NULL THEN +SET NEW.b="generated before update"; +SET NEW.c="generated before update"; +END IF; +END | +# Inserts +set @a=0,@b=0,@c=0; +insert into t1 (a) values(1); +insert into t1 (a,b) values(2, "*2*"); +insert into t1 (a,b,c) values(3, "*3*", "**3**"); +insert into t1 (a,c) values(4, "**4**"); +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +8 8 8 +select a,b,c from t1; +a b c +1 generated NULL +2 *2* NULL +3 *3* **3** +4 generated **4** +select @a,@b,@c; +@a @b @c +8 8 8 +select a,b,c,blob_a from t1; +a b c blob_a +1 generated NULL 1 +2 *2* NULL 2 +3 *3* **3** 3 +4 generated **4** 4 +select @a,@b,@c; +@a @b @c +12 8 8 +# updates +set @a=0,@b=0,@c=0; +update t1 set a=a+100 where a=1; +update t1 set a=a+100, b="*102*" where a=2; +update t1 set a=a+100, b=NULL where a=3; +update t1 set a=a+100, b="invisible", c=NULL where a=4; +select @a,@b,@c; +@a @b @c +0 0 0 +select * from t1; +a b c blob_a blob_b blob_c +101 generated generated before update 101 generated generated before update +102 generated generated before update 102 generated generated before update +103 generated generated before update 103 generated generated before update +104 generated generated before update 104 generated generated before update +drop trigger t1_ins; +drop trigger t1_update; +drop table t1; +# +# Same test, but with virtual keys +# +CREATE TABLE t1 ( +a INTEGER UNSIGNED NULL DEFAULT NULL, +b CHAR(10) NULL DEFAULT NULL, +c blob NULL DEFAULT NULL, +blob_a blob GENERATED ALWAYS AS (a) VIRTUAL, +blob_b blob GENERATED ALWAYS AS (b) VIRTUAL, +blob_c blob GENERATED ALWAYS AS (c) VIRTUAL, +key (a), +key (blob_a(10)), +key (blob_b(10)), +key (blob_c(10)) +); +CREATE TRIGGER t1_ins +BEFORE INSERT +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL THEN +SET NEW.b="generated before insert"; +END IF; +END | +CREATE TRIGGER t1_update +BEFORE UPDATE +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL or NEW.c IS NULL THEN +SET NEW.b="generated before update"; +SET NEW.c="generated before update"; +END IF; +END | +# Inserts +insert into t1 (a) values(1); +insert into t1 (a,b) values(2, "*2*"); +insert into t1 (a,b,c) values(3, "*3*", "**3**"); +insert into t1 (a,c) values(4, "**4**"); +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select a,b,c from t1; +a b c +1 generated NULL +2 *2* NULL +3 *3* **3** +4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select a,b,c,blob_a from t1; +a b c blob_a +1 generated NULL 1 +2 *2* NULL 2 +3 *3* **3** 3 +4 generated **4** 4 +select @a,@b,@c; +@a @b @c +4 4 4 +# updates +update t1 set a=a+100 where a=1; +update t1 set a=a+100, b="*102*" where a=2; +update t1 set a=a+100, b=NULL where a=3; +update t1 set a=a+100, b="invisible", c=NULL where a=4; +select * from t1; +a b c blob_a blob_b blob_c +101 generated generated before update 101 generated generated before update +102 generated generated before update 102 generated generated before update +103 generated generated before update 103 generated generated before update +104 generated generated before update 104 generated generated before update +drop trigger t1_ins; +drop trigger t1_update; +drop table t1; diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result index 77efa8fe6b9..edafd474286 100644 --- a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result @@ -125,3 +125,182 @@ c DROP TRIGGER t1_ins_aft; DROP TRIGGER t1_del_bef; DROP TABLE t1,t2; +# +# Examine the number of times triggers are recalculated for updates +# +CREATE TABLE t1 ( +a INTEGER UNSIGNED NULL DEFAULT NULL, +b CHAR(10) NULL DEFAULT NULL, +c blob NULL DEFAULT NULL, +blob_a blob GENERATED ALWAYS AS (last_value(@a:=@a+1,a)) VIRTUAL, +blob_b blob GENERATED ALWAYS AS (last_value(@b:=@b+1,b)) VIRTUAL, +blob_c blob GENERATED ALWAYS AS (last_value(@c:=@c+1,c)) VIRTUAL +); +CREATE TRIGGER t1_ins +BEFORE INSERT +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL THEN +SET NEW.b="generated before insert"; +END IF; +END | +CREATE TRIGGER t1_update +BEFORE UPDATE +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL or NEW.c IS NULL THEN +SET NEW.b="generated before update"; +SET NEW.c="generated before update"; +END IF; +END | +# Inserts +set @a=0,@b=0,@c=0; +insert into t1 (a) values(1); +insert into t1 (a,b) values(2, "*2*"); +insert into t1 (a,b,c) values(3, "*3*", "**3**"); +insert into t1 (a,c) values(4, "**4**"); +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +8 8 8 +select a,b,c from t1; +a b c +1 generated NULL +2 *2* NULL +3 *3* **3** +4 generated **4** +select @a,@b,@c; +@a @b @c +8 8 8 +select a,b,c,blob_a from t1; +a b c blob_a +1 generated NULL 1 +2 *2* NULL 2 +3 *3* **3** 3 +4 generated **4** 4 +select @a,@b,@c; +@a @b @c +12 8 8 +# updates +set @a=0,@b=0,@c=0; +update t1 set a=a+100 where a=1; +update t1 set a=a+100, b="*102*" where a=2; +update t1 set a=a+100, b=NULL where a=3; +update t1 set a=a+100, b="invisible", c=NULL where a=4; +select @a,@b,@c; +@a @b @c +0 0 0 +select * from t1; +a b c blob_a blob_b blob_c +101 generated generated before update 101 generated generated before update +102 generated generated before update 102 generated generated before update +103 generated generated before update 103 generated generated before update +104 generated generated before update 104 generated generated before update +drop trigger t1_ins; +drop trigger t1_update; +drop table t1; +# +# Same test, but with virtual keys +# +CREATE TABLE t1 ( +a INTEGER UNSIGNED NULL DEFAULT NULL, +b CHAR(10) NULL DEFAULT NULL, +c blob NULL DEFAULT NULL, +blob_a blob GENERATED ALWAYS AS (a) VIRTUAL, +blob_b blob GENERATED ALWAYS AS (b) VIRTUAL, +blob_c blob GENERATED ALWAYS AS (c) VIRTUAL, +key (a), +key (blob_a(10)), +key (blob_b(10)), +key (blob_c(10)) +); +CREATE TRIGGER t1_ins +BEFORE INSERT +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL THEN +SET NEW.b="generated before insert"; +END IF; +END | +CREATE TRIGGER t1_update +BEFORE UPDATE +ON t1 +FOR EACH ROW +BEGIN +IF NEW.b IS NULL or NEW.c IS NULL THEN +SET NEW.b="generated before update"; +SET NEW.c="generated before update"; +END IF; +END | +# Inserts +insert into t1 (a) values(1); +insert into t1 (a,b) values(2, "*2*"); +insert into t1 (a,b,c) values(3, "*3*", "**3**"); +insert into t1 (a,c) values(4, "**4**"); +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select * from t1; +a b c blob_a blob_b blob_c +1 generated NULL 1 generated NULL +2 *2* NULL 2 *2* NULL +3 *3* **3** 3 *3* **3** +4 generated **4** 4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select a,b,c from t1; +a b c +1 generated NULL +2 *2* NULL +3 *3* **3** +4 generated **4** +select @a,@b,@c; +@a @b @c +4 4 4 +select a,b,c,blob_a from t1; +a b c blob_a +1 generated NULL 1 +2 *2* NULL 2 +3 *3* **3** 3 +4 generated **4** 4 +select @a,@b,@c; +@a @b @c +4 4 4 +# updates +update t1 set a=a+100 where a=1; +update t1 set a=a+100, b="*102*" where a=2; +update t1 set a=a+100, b=NULL where a=3; +update t1 set a=a+100, b="invisible", c=NULL where a=4; +select * from t1; +a b c blob_a blob_b blob_c +101 generated generated before update 101 generated generated before update +102 generated generated before update 102 generated generated before update +103 generated generated before update 103 generated generated before update +104 generated generated before update 104 generated generated before update +drop trigger t1_ins; +drop trigger t1_update; +drop table t1; diff --git a/mysql-test/suite/vcol/t/not_supported.test b/mysql-test/suite/vcol/t/not_supported.test index b7544cb33a4..1ea7970523a 100644 --- a/mysql-test/suite/vcol/t/not_supported.test +++ b/mysql-test/suite/vcol/t/not_supported.test @@ -2,7 +2,7 @@ # MDEV-7113 difference between check_vcol_func_processor and check_partition_func_processor # -# the following functions must not be supported in virtual columns. +# the following functions must not be supported in persistent columns. # but for compatibility reasons it won't be done in a GA version, # we'll only fix most critical issues (inconsistent results, crashes) @@ -13,15 +13,13 @@ set time_zone='+10:00'; set div_precision_increment=20; create table t1 (a int, b int, v decimal(20,19) as (a/3)); ---error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED -create table t2 (a int, b int, v int as (a+@a)); +create table t2 (a int, b int, v int as (a+@a)); drop table t2; --error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t2 (a int, b int, v int as (a+@a) PERSISTENT); create table t3_ok (a int, b int, v int as (a+@@error_count)); --error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t3 (a int, b int, v int as (a+@@error_count) PERSISTENT); ---error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED -create table t4 (a int, b int, v int as (@a:=a)); +create table t4 (a int, b int, v int as (@a:=a)); drop table t4; --error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED create table t4 (a int, b int, v int as (@a:=a) PERSISTENT); create table t8 (a int, b int, v varchar(100) as (from_unixtime(a))); diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index 41ed1613448..9ae088405fa 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -359,6 +359,8 @@ insert into t1 (b) values(2); insert into t1 (a,b) values(3,4); select * from t1; drop table t1; +CREATE OR REPLACE TABLE t1 (a INT DEFAULT @v); drop table t1; +CREATE TABLE t1 (a INT DEFAULT @v:=1); drop table t1; --echo # --echo # Error handling @@ -407,12 +409,6 @@ CREATE TABLE t1 (a INT DEFAULT(?)); --error ER_EXPRESSION_REFERS_TO_UNINIT_FIELD CREATE TABLE t1 (a INT DEFAULT (b), b INT DEFAULT(a)); ---error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED -CREATE TABLE t1 (a INT DEFAULT @v); - ---error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED -CREATE TABLE t1 (a INT DEFAULT @v:=1); - --error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED CREATE TABLE t1 (a INT DEFAULT(NAME_CONST('xxx', 'yyy')); diff --git a/sql/field.h b/sql/field.h index 0d278968eb5..400d2ef0e5e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -3176,6 +3176,12 @@ protected: The 'value'-object is a cache fronting the storage engine. */ String value; + /** + Cache for blob values when reading a row with a virtual blob + field. This is needed to not destroy the old cached value when + updating the blob with a new value when creating the new row. + */ + String read_value; static void do_copy_blob(Copy_field *copy); static void do_conv_blob(Copy_field *copy); @@ -3279,7 +3285,7 @@ public: return (uint32) (((ulonglong) 1 << (packlength*8)) -1); } int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; } - void reset_fields() { bzero((uchar*) &value,sizeof(value)); } + void reset_fields() { bzero((uchar*) &value,sizeof(value)); bzero((uchar*) &read_value,sizeof(read_value)); } uint32 get_field_buffer_size(void) { return value.alloced_length(); } void store_length(uchar *i_ptr, uint i_packlength, uint32 i_number); inline void store_length(uint32 number) @@ -3332,13 +3338,41 @@ public: memcpy(ptr+packlength, &tmp, sizeof(char*)); return 0; } + /* store value for the duration of the current read record */ + inline void swap_value_and_read_value() + { + read_value.swap(value); + } + inline void set_value(uchar *data) + { + /* Set value pointer. Lengths are not important */ + value.reset((char*) data, 1, 1, &my_charset_bin); + } virtual uchar *pack(uchar *to, const uchar *from, uint max_length); virtual const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data); uint packed_col_length(const uchar *col_ptr, uint length); uint max_packed_col_length(uint max_length); - void free() { value.free(); } - inline void clear_temporary() { bzero((uchar*) &value, sizeof(value)); } + void free() + { + value.free(); + read_value.free(); + } + inline void clear_temporary() + { + uchar *tmp= get_ptr(); + if (likely(value.ptr() == (char*) tmp)) + bzero((uchar*) &value, sizeof(value)); + else + { + /* + Currently read_value should never point to tmp, the following code + is mainly here to make things future proof. + */ + if (unlikely(read_value.ptr() == (char*) tmp)) + bzero((uchar*) &read_value, sizeof(read_value)); + } + } uint size_of() const { return sizeof(*this); } bool has_charset(void) const { return charset() == &my_charset_bin ? FALSE : TRUE; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 8e912fe83c8..754ba9d261c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4580,7 +4580,7 @@ longlong Item_func_sleep::val_int() bool Item_func_user_var::check_vcol_func_processor(void *arg) { - return mark_unsupported_function("@", name.str, arg, VCOL_IMPOSSIBLE); + return mark_unsupported_function("@", name.str, arg, VCOL_NON_DETERMINISTIC); } #define extra_size sizeof(double) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b6cfd2f2cc1..46d7d07dbdf 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8043,17 +8043,14 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Re-calculate virtual fields to cater for cases when base columns are updated by the triggers. */ - List_iterator_fast f(fields); - Item *fld; - Item_field *item_field; - if (fields.elements) + if (table->vfield && fields.elements) { - fld= (Item_field*)f++; - item_field= fld->field_for_view_update(); - if (item_field && table->vfield) + Item *fld= (Item_field*) fields.head(); + Item_field *item_field= fld->field_for_view_update(); + if (item_field) { DBUG_ASSERT(table == item_field->field->table); - result= table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); + result|= table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); } } } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7b583e1ddec..cea42667c48 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1691,8 +1691,12 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) } if (table->vfield) { + /* + We have not yet called update_virtual_fields(VOL_UPDATE_FOR_READ) + in handler methods for the just read row in record[1]. + */ table->move_fields(table->field, table->record[1], table->record[0]); - table->update_virtual_fields(VCOL_UPDATE_INDEXED); + table->update_virtual_fields(VCOL_UPDATE_FOR_REPLACE); table->move_fields(table->field, table->record[0], table->record[1]); } if (info->handle_duplicates == DUP_UPDATE) @@ -2912,6 +2916,8 @@ pthread_handler_t handle_delayed_insert(void *arg) thd->mdl_context.set_needs_thr_lock_abort(TRUE); di->table->mark_columns_needed_for_insert(); + /* Mark all columns for write as we don't know which columns we get from user */ + bitmap_set_all(di->table->write_set); /* Now wait until we get an insert or lock to handle */ /* We will not abort as long as a client thread uses this thread */ @@ -3079,7 +3085,7 @@ pthread_handler_t handle_delayed_insert(void *arg) } -/* Remove pointers from temporary fields to allocated values */ +/* Remove all pointers to data for blob fields so that original table doesn't try to free them */ static void unlink_blobs(register TABLE *table) { @@ -3093,13 +3099,27 @@ static void unlink_blobs(register TABLE *table) /* Free blobs stored in current row */ static void free_delayed_insert_blobs(register TABLE *table) +{ + for (Field **ptr=table->field ; *ptr ; ptr++) + { + if ((*ptr)->flags & BLOB_FLAG) + ((Field_blob *) *ptr)->free(); + } +} + + +/* set value field for blobs to point to data in record */ + +static void set_delayed_insert_blobs(register TABLE *table) { for (Field **ptr=table->field ; *ptr ; ptr++) { if ((*ptr)->flags & BLOB_FLAG) { - my_free(((Field_blob *) (*ptr))->get_ptr()); - ((Field_blob *) (*ptr))->reset(); + Field_blob *blob= ((Field_blob *) *ptr); + uchar *data= blob->get_ptr(); + if (data) + blob->set_value(data); // Set value.ptr() to point to data } } } @@ -3157,6 +3177,8 @@ bool Delayed_insert::handle_inserts(void) stacked_inserts--; mysql_mutex_unlock(&mutex); memcpy(table->record[0],row->record,table->s->reclength); + if (table->s->blob_fields) + set_delayed_insert_blobs(table); thd.start_time=row->start_time; thd.query_start_used=row->query_start_used; @@ -3227,6 +3249,16 @@ bool Delayed_insert::handle_inserts(void) if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); thd.clear_error(); // reset error for binlog + + if (table->vfield) + { + /* + Virtual fields where not calculated by caller as the temporary TABLE object used + had vcol_set empty. Better to calculate them here to make the caller faster. + */ + table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); + } + if (write_record(&thd, table, &info)) { info.error_count++; // Ignore errors @@ -3348,6 +3380,7 @@ bool Delayed_insert::handle_inserts(void) if (table->s->blob_fields) { memcpy(table->record[0],row->record,table->s->reclength); + set_delayed_insert_blobs(table); free_delayed_insert_blobs(table); } delete row; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 14812d2f73b..2d1619018b2 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -2266,6 +2266,7 @@ void Table_triggers_list::mark_fields_used(trg_event_type event) { int action_time; Item_trigger_field *trg_field; + DBUG_ENTER("Table_triggers_list::mark_fields_used"); for (action_time= 0; action_time < (int)TRG_ACTION_MAX; action_time++) { @@ -2280,14 +2281,19 @@ void Table_triggers_list::mark_fields_used(trg_event_type event) /* We cannot mark fields which does not present in table. */ if (trg_field->field_idx != (uint)-1) { + DBUG_PRINT("info", ("marking field: %d", trg_field->field_idx)); bitmap_set_bit(trigger_table->read_set, trg_field->field_idx); if (trg_field->get_settable_routine_parameter()) bitmap_set_bit(trigger_table->write_set, trg_field->field_idx); + if (trigger_table->field[trg_field->field_idx]->vcol_info) + trigger_table->mark_virtual_col(trigger_table-> + field[trg_field->field_idx]); } } } } trigger_table->file->column_bitmaps_signal(); + DBUG_VOID_RETURN; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 05f7080609a..476d1a4e104 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -618,8 +618,6 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { explain->buf_tracker.on_record_read(); - if (table->vfield) - table->update_virtual_fields(VCOL_UPDATE_FOR_READ_WRITE); thd->inc_examined_row_count(1); if (!select || (error= select->skip_record(thd)) > 0) { @@ -735,8 +733,6 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { explain->tracker.on_record_read(); - if (table->vfield) - table->update_virtual_fields(VCOL_UPDATE_FOR_READ_WRITE); thd->inc_examined_row_count(1); if (!select || select->skip_record(thd) > 0) { @@ -2327,6 +2323,17 @@ int multi_update::do_updates() goto err; } table->file->extra(HA_EXTRA_NO_CACHE); + /* + We have to clear the base record, if we have virtual indexed + blob fields, as some storage engines will access the blob fields + to calculate the keys to see if they have changed. Without + clearing the blob pointers will contain random values which can + cause a crash. + This is a workaround for engines that access columns not present in + either read or write set. + */ + if (table->vfield) + empty_record(table); check_opt_it.rewind(); while(TABLE *tbl= check_opt_it++) diff --git a/sql/table.cc b/sql/table.cc index 5c9d4805943..b7f83a502b7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6572,6 +6572,7 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl) { Field **vfield_ptr, *tmp_vfield; bool bitmap_updated= false; + DBUG_ENTER("mark_virtual_columns_for_write"); for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) { @@ -6610,7 +6611,7 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl) } if (bitmap_updated) file->column_bitmaps_signal(); - return bitmap_updated; + DBUG_RETURN(bitmap_updated); } /* @@ -7324,6 +7325,7 @@ bool is_simple_order(ORDER *order) int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) { DBUG_ENTER("TABLE::update_virtual_fields"); + DBUG_PRINT("enter", ("update_mode: %d", update_mode)); Field **vfield_ptr, *vf; DBUG_ASSERT(vfield); @@ -7336,25 +7338,39 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) DBUG_ASSERT(vcol_info); DBUG_ASSERT(vcol_info->expr); - bool update; + bool update, swap_values= 0; switch (update_mode) { - case VCOL_UPDATE_FOR_READ_WRITE: - if (triggers) - { - update= true; - break; - } case VCOL_UPDATE_FOR_READ: update= !vcol_info->stored_in_db && !(key_read && vf->part_of_key.is_set(file->active_index)) && bitmap_is_set(vcol_set, vf->field_index); + swap_values= 1; break; case VCOL_UPDATE_FOR_WRITE: - update= triggers || bitmap_is_set(vcol_set, vf->field_index); + update= bitmap_is_set(vcol_set, vf->field_index); break; - case VCOL_UPDATE_INDEXED: + case VCOL_UPDATE_FOR_REPLACE: update= !vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) && bitmap_is_set(vcol_set, vf->field_index); + if (update && (vf->flags & BLOB_FLAG)) + { + /* + The row has been read into record[1] and Field_blob::value + contains the value for record[0]. Swap value and read_value + to ensure that the virtual column data for the read row will + be in read_value at the end of this function + */ + ((Field_blob*) vf)->swap_value_and_read_value(); + /* Ensure we call swap_value_and_read_value() after update */ + swap_values= 1; + } + break; + case VCOL_UPDATE_INDEXED: + /* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */ + update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) && + bitmap_is_set(vcol_set, vf->field_index) && + (key_read && vf->part_of_key.is_set(file->active_index))); + swap_values= 1; break; } @@ -7363,6 +7379,16 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) /* Compute the actual value of the virtual fields */ vcol_info->expr->save_in_field(vf, 0); DBUG_PRINT("info", ("field '%s' - updated", vf->field_name)); + if (swap_values && (vf->flags & BLOB_FLAG)) + { + /* + Remember the read value to allow other update_virtual_field() calls + for the same blob field for the row to be updated. + Field_blob->read_value always contains the virtual column data for + any read row. + */ + ((Field_blob*) vf)->swap_value_and_read_value(); + } } else { diff --git a/sql/table.h b/sql/table.h index b2d5599b740..facba06a3cc 100644 --- a/sql/table.h +++ b/sql/table.h @@ -327,9 +327,9 @@ enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP }; enum enum_vcol_update_mode { VCOL_UPDATE_FOR_READ= 0, - VCOL_UPDATE_FOR_READ_WRITE, VCOL_UPDATE_FOR_WRITE, - VCOL_UPDATE_INDEXED + VCOL_UPDATE_INDEXED, + VCOL_UPDATE_FOR_REPLACE }; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 53157258d2e..ca14542c9b5 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1913,7 +1913,7 @@ innobase_row_to_mysql( } if (table->vfield) { my_bitmap_map* old_vcol_set = tmp_use_all_columns(table, table->vcol_set); - table->update_virtual_fields(VCOL_UPDATE_FOR_READ_WRITE); + table->update_virtual_fields(VCOL_UPDATE_FOR_READ); tmp_restore_column_map(table->vcol_set, old_vcol_set); } } diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 9e09853871d..881e90d95c1 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -664,8 +664,12 @@ static int compute_vcols(MI_INFO *info, uchar *record, int keynum) TABLE *table= (TABLE*)(info->external_ref); table->move_fields(table->field, record, table->field[0]->record_ptr()); if (keynum == -1) // update all vcols - return table->update_virtual_fields(VCOL_UPDATE_INDEXED); - + { + int error= table->update_virtual_fields(VCOL_UPDATE_FOR_READ); + if (table->update_virtual_fields(VCOL_UPDATE_INDEXED)) + error= 1; + return error; + } // update only one key KEY *key= table->key_info + keynum; KEY_PART_INFO *kp= key->key_part, *end= kp + key->ext_key_parts; From 7567cf5aef9c21b2c8dc404cfe10b4a189851163 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 30 Dec 2016 11:23:45 +0200 Subject: [PATCH 054/167] Fixes for using ssl with BUILD scripts. Needed as GNUTLS can't be used by MariaDB on many systems, like OpenSuse 13.2 --- BUILD/SETUP.sh | 7 +++---- cmake/configure.pl | 17 +++++++++++------ mysql-test/valgrind.supp | 10 ++++++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 5f5b0250088..d25b9d9d891 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -120,10 +120,9 @@ path=`dirname $0` get_make_parallel_flag # SSL library to use.--with-ssl will select our bundled yaSSL -# implementation of SSL. To use OpenSSL you will need to specify -# the location of OpenSSL headers and libs on your system. -# Ex --with-ssl=/usr -SSL_LIBRARY=--with-ssl +# implementation of SSL. --with-ssl=yes will first try system library +# then the boundled one --with-ssl=system will use the system library. +SSL_LIBRARY=--with-ssl=system if [ "x$warning_mode" = "xpedantic" ]; then warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE" diff --git a/cmake/configure.pl b/cmake/configure.pl index 68baf436c1c..c502a172a22 100644 --- a/cmake/configure.pl +++ b/cmake/configure.pl @@ -165,21 +165,26 @@ foreach my $option (@ARGV) $cmakeargs = $cmakeargs." -DWITH_LIBEVENT=bundled"; next; } - if($option =~ /with-ssl=/) + if($option =~ /with-ssl=yes/) { $cmakeargs = $cmakeargs." -DWITH_SSL=yes"; next; } + if($option =~ /with-ssl=system/) + { + $cmakeargs = $cmakeargs." -DWITH_SSL=system"; + next; + } + if($option =~ /with-ssl$/) + { + $cmakeargs = $cmakeargs." -DWITH_SSL=bundled"; + next; + } if($option =~ /with-debug/) { $cmakeargs = $cmakeargs." -DCMAKE_BUILD_TYPE=Debug -DSECURITY_HARDENED=OFF"; next; } - if($option =~ /with-ssl/) - { - $cmakeargs = $cmakeargs." -DWITH_SSL=bundled"; - next; - } if($option =~ /prefix=/) { $cmake_install_prefix= substr($option, 7); diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 31b214d75f4..76c848dddad 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1077,6 +1077,16 @@ fun:SSL_library_init } +{ + OpenSSL still reachable. + Memcheck:Leak + fun:*alloc + fun:CRYPTO_malloc + fun:sk_new + fun:SSL_COMP_get_compression_methods + fun:SSL_library_init +} + { libcrypto 2.2.1 leak Memcheck:Leak From 00f462cf1be56d4cbac420b88c12dc95bc99579d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 2 Jan 2017 11:03:25 +0100 Subject: [PATCH 055/167] dgcov: import, rewrite to work with cmake and git --- .gitignore | 1 + mysql-test/dgcov.pl | 198 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100755 mysql-test/dgcov.pl diff --git a/.gitignore b/.gitignore index ee52f228ea2..737528ffdd4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.reject *.spec *.bak +*.dgcov *.rpm .*.swp *.ninja diff --git a/mysql-test/dgcov.pl b/mysql-test/dgcov.pl new file mode 100755 index 00000000000..27647eed056 --- /dev/null +++ b/mysql-test/dgcov.pl @@ -0,0 +1,198 @@ +#! /usr/bin/perl + +# Copyright (C) 2003,2008 MySQL AB +# Copyright (C) 2010,2017 Sergei Golubchik and MariaDB Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Run gcov and report test coverage on only those code lines touched by +# a given list of commits. + +use strict; +use warnings; + +use Getopt::Long; +use File::Find; +use Cwd qw/realpath/; + +my $opt_verbose=0; +my $opt_generate; +my $opt_help; +my $opt_purge; +my $opt_only_gcov; +my $opt_skip_gcov; + +my %cov; +my $file_no=0; + +GetOptions + ("v|verbose+" => \$opt_verbose, + "h|help" => \$opt_help, + "p|purge" => \$opt_purge, + "g|generate" => \$opt_generate, + "o|only-gcov" => \$opt_only_gcov, + "s|skip-gcov" => \$opt_skip_gcov, + ) or usage(); + +usage() if $opt_help; + +sub logv(@) { print STDERR @_,"\n" if $opt_verbose; } +sub gcov_prefix($) { defined($_[0]) ? $_[0] || '#####' : '-' } + +my $root= `git rev-parse --show-toplevel`; +chomp $root; + +die "Failed to find tree root" unless $root; +$root=realpath($root).'/'; +logv "Chdir $root"; +chdir $root or die "chdir($root): $!"; + +my $res; +my $cmd; +if ($opt_purge) +{ + $cmd= "find . -name '*.da' -o -name '*.gcda' -o -name '*.gcov' -o ". + "-name '*.dgcov' | grep -v 'README\.gcov' | xargs rm -f ''"; + logv "Running: $cmd"; + system($cmd)==0 or die "system($cmd): $? $!"; + exit 0; +} + +find(\&gcov_one_file, $root); +find(\&write_coverage, $root) if $opt_generate; +exit 0 if $opt_only_gcov; + +if (@ARGV) { + print_gcov_for_diff(@ARGV); +} else { + print_gcov_for_diff('HEAD') or print_gcov_for_diff('HEAD^'); +} +exit 0; + +sub print_gcov_for_diff { + $cmd="git diff --no-prefix --ignore-space-change @_"; + logv "Running: $cmd"; + open PIPE, '-|', $cmd or die "Failed to popen '$cmd': $!: $?"; + my ($lnum, $cnt, $fcov, $acc, $printme, $fname); + while () { + if (/^diff --git (.*) \1\n/) { + print $acc if $printme; + $fname=$1; + $acc="dgcov $fname"; + $acc=('*' x length($acc)) . "\n$acc\n" . ('*' x length($acc)); + $lnum=undef; + $fcov=$cov{realpath($fname)}; + $printme=0; + logv "File: $fname"; + next; + } + if (/^@@ -\d+,\d+ \+(\d+),(\d+) @@/ and $fcov) { + $lnum=$1; + $cnt=$2; + $acc.="\n@@ +$lnum,$cnt @\@$'"; + logv " lines: $lnum,",$lnum+$cnt; + next; + } + next unless $lnum and $cnt; + $acc.=sprintf '%9s:%5s:%s', '', $lnum, $' if /^ /; + ++$printme, $acc.=sprintf '%9s:%5s:%s', gcov_prefix($fcov->{$lnum}), $lnum, $' if /^\+/; + die "$_^^^ dying", unless /^[- +]/; + ++$lnum; + --$cnt; + } + print $acc if $printme; + close PIPE or die "command '$cmd' failed: $!: $?"; + return defined($fname); +} + +sub usage { + print <^ + +If no arguments are specified, it prints the coverage for all uncommitted +changes, if any, otherwise for the last commit. + +Options: + + -h --help This help. + -v --verbose Show commands run. + -p --purge Delete all test coverage information, to prepare for a + new coverage test. + -o --only-gcov Stop after running gcov, don't run git + -s --skip-gcov Do not run gcov, assume .gcov files are already in place + -g --generate Create .dgcov files for all source files + +Prior to running this tool, MariaDB should be built with + + cmake -DENABLE_GCOV=ON + +and the testsuite should be run. dgcov will report the coverage +for all lines modified in the specified commits. +END + + exit 1; +} + +sub gcov_one_file { + return unless /\.gcda$/; + unless ($opt_skip_gcov) { + $cmd= "gcov -i '$_' 2>/dev/null >/dev/null"; + print STDERR ++$file_no,"\r" if not $opt_verbose and -t STDERR; + logv "Running: $cmd"; + system($cmd)==0 or die "system($cmd): $? $!"; + } + + # now, read the generated file + open FH, '<', "$_.gcov" or die "open(<$_.gcov): $!"; + my $fname; + while () { + chomp; + if (/^function:/) { + next; + } + if (/^file:/) { + $fname=realpath($'); + next; + } + next if /^lcount:\d+,-\d+/; # whatever that means + unless (/^lcount:(\d+),(\d+)/ and $fname) { + warn "unknown line '$_' after running '$cmd'"; + next; + } + $cov{$fname}->{$1}+=$2; + } + close(FH); +} + +sub write_coverage { + my $fn=$File::Find::name; + my $h=$cov{$fn}; + return unless $h and $root eq substr $fn, 0, length($root); + open I, '<', $fn or die "open(<$fn): $!"; + open O, '>', "$fn.dgcov" or die "open(>$fn.dgcov): $!"; + logv "Annotating: ", substr $fn, length($root); + while () { + printf O '%9s:%5s:%s', gcov_prefix($h->{$.}), $., $_; + } + close I; + close O; +} From 53ae72e2ee657e3bdd348365db3b08844d24c3e3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 2 Jan 2017 21:28:15 +0100 Subject: [PATCH 056/167] mtr uses dgcov for --gcov option --- mysql-test/lib/mtr_gcov.pl | 71 ------------------------------------ mysql-test/mysql-test-run.pl | 29 +++++---------- 2 files changed, 9 insertions(+), 91 deletions(-) delete mode 100644 mysql-test/lib/mtr_gcov.pl diff --git a/mysql-test/lib/mtr_gcov.pl b/mysql-test/lib/mtr_gcov.pl deleted file mode 100644 index 4c260d089b2..00000000000 --- a/mysql-test/lib/mtr_gcov.pl +++ /dev/null @@ -1,71 +0,0 @@ -# -*- cperl -*- -# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -# This is a library file used by the Perl version of mysql-test-run, -# and is part of the translation of the Bourne shell script with the -# same name. - -use strict; - -our $basedir; - -sub gcov_prepare ($) { - my ($dir)= @_; - print "Purging gcov information from '$dir'...\n"; - - system("find $dir -name \*.gcov -o -name \*.da" - . " -o -name \*.gcda | xargs rm"); -} - -# -# Collect gcov statistics. -# Arguments: -# $dir basedir, normally build directory -# $gcov gcov utility program [path] name -# $gcov_msg message file name -# $gcov_err error file name -# -sub gcov_collect ($$$) { - my ($dir, $gcov, $gcov_msg, $gcov_err)= @_; - - # Get current directory to return to later. - my $start_dir= cwd(); - - print "Collecting source coverage info using '$gcov'...$basedir\n"; - -f "$dir/$gcov_msg" and unlink("$dir/$gcov_msg"); - -f "$dir/$gcov_err" and unlink("$dir/$gcov_err"); - - my @dirs= `find "$dir" -type d -print | sort`; - #print "List of directories:\n@dirs\n"; - - foreach my $d ( @dirs ) { - chomp($d); - chdir($d) or next; - - my @flist= glob("*.*.gcno"); - print ("Collecting in '$d'...\n") if @flist; - - foreach my $f (@flist) { - system("$gcov $f 2>>$dir/$gcov_err >>$dir/$gcov_msg"); - system("perl", "$basedir/mysql-test/lib/process-purecov-annotations.pl", "$f.gcov"); - } - chdir($start_dir); - } - print "gcov info in $dir/$gcov_msg, errors in $dir/$gcov_err\n"; -} - - -1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 9efc9035555..b3fe2d2f20a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -104,7 +104,6 @@ use IO::Select; require "mtr_process.pl"; require "mtr_io.pl"; -require "mtr_gcov.pl"; require "mtr_gprof.pl"; require "mtr_misc.pl"; @@ -248,11 +247,6 @@ our $opt_mem= $ENV{'MTR_MEM'}; our $opt_clean_vardir= $ENV{'MTR_CLEAN_VARDIR'}; our $opt_gcov; -our $opt_gcov_src_dir="."; -our $opt_gcov_exe= "gcov"; -our $opt_gcov_err= "mysql-test-gcov.err"; -our $opt_gcov_msg= "mysql-test-gcov.msg"; - our $opt_gprof; our %gprof_dirs; @@ -383,11 +377,6 @@ sub main { # --help will not reach here, so now it's safe to assume we have binaries My::SafeProcess::find_bin(); - if ( $opt_gcov ) { - gcov_prepare($basedir . "/" . $opt_gcov_src_dir); - } - - print "vardir: $opt_vardir\n"; initialize_servers(); init_timers(); @@ -431,6 +420,10 @@ sub main { exit 0; } + if ($opt_gcov) { + system './dgcov.pl --purge'; + } + ####################################################################### my $num_tests= @$tests; if ( $opt_parallel eq "auto" ) { @@ -555,15 +548,15 @@ sub main { mtr_print_line(); - if ( $opt_gcov ) { - gcov_collect($basedir . "/" . $opt_gcov_src_dir, $opt_gcov_exe, - $opt_gcov_msg, $opt_gcov_err); - } - print_total_times($opt_parallel) if $opt_report_times; mtr_report_stats($prefix, $fail, $completed, $extra_warnings); + if ($opt_gcov) { + mtr_report("Running dgcov"); + system "./dgcov.pl --generate > $opt_vardir/last_changes.dgcov"; + } + if ( @$completed != $num_tests) { mtr_error("Not all tests completed (only ". scalar(@$completed) . @@ -1148,7 +1141,6 @@ sub command_line_setup { # Coverage, profiling etc 'gcov' => \$opt_gcov, - 'gcov-src-dir=s' => \$opt_gcov_src_dir, 'gprof' => \$opt_gprof, 'valgrind|valgrind-all' => \$opt_valgrind, 'valgrind-mysqltest' => \$opt_valgrind_mysqltest, @@ -6180,9 +6172,6 @@ Misc options actions. Disable facility with NUM=0. gcov Collect coverage information after the test. The result is a gcov file per source and header file. - gcov-src-dir=subdir Collect coverage only within the given subdirectory. - For example, if you're only developing the SQL layer, - it makes sense to use --gcov-src-dir=sql gprof Collect profiling information using gprof. experimental= Refer to list of tests considered experimental; failures will be marked exp-fail instead of fail. From bf95970ec03e353f297c3b809219cee91ac40724 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 3 Jan 2017 15:47:17 +0200 Subject: [PATCH 057/167] Cleanups * Ensure that BUILD scripts cleans up things properly before new BUILD * MySQL -> MariaDB * Ignore wrong valgrind memleak --- BUILD/FINISH.sh | 4 ++-- BUILD/SETUP.sh | 2 +- mysql-test/valgrind.supp | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh index 86085fcc593..b41c5c5139d 100644 --- a/BUILD/FINISH.sh +++ b/BUILD/FINISH.sh @@ -32,9 +32,9 @@ then configure="$configure --verbose" fi +# git clean -fdX removes all ignored (build) files commands="\ -/bin/rm -rf configure; -/bin/rm -rf CMakeCache.txt CMakeFiles/ +git clean -fdX path=`dirname $0` . \"$path/autorun.sh\"" diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index d25b9d9d891..22357ce7fc8 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -42,7 +42,7 @@ Usage: $0 [-h|-n] [configure-options] Influences the debug flags. Old is default. --prefix=path Build with prefix 'path'. -Note: this script is intended for internal use by MySQL developers. +Note: this script is intended for internal use by MariaDB developers. EOF } diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 76c848dddad..20d4b124dd7 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -368,8 +368,6 @@ fun:_dl_init } - - # # dlclose can allocate memory for error message, the memory will be # freed by dlerror or other dl* function. From de22cd3fe5caa1db8839701e45f379b3b5be7328 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 4 Jan 2017 18:45:23 +0200 Subject: [PATCH 058/167] Fixes for failures in test scripts and removal of some compiler warnings - rpl_gtid_stop_start: Random failure - sysvars_innodb,32bit: Fixes for 32 bit --- .../suite/rpl/r/rpl_gtid_stop_start.result | 1 + .../suite/rpl/t/rpl_gtid_stop_start.test | 1 + .../sys_vars/r/sysvars_innodb,32bit.rdiff | 117 ++++++++++-------- sql/table.cc | 5 +- storage/innobase/lock/lock0lock.cc | 2 +- 5 files changed, 69 insertions(+), 57 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result index 3ba17822319..3f3b5e4344a 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result @@ -8,6 +8,7 @@ include/stop_slave.inc Master_Log_File = 'master-bin.000001' Using_Gtid = 'No' CHANGE MASTER TO master_use_gtid=current_pos; +FLUSH LOGS; connection server_1; FLUSH LOGS; include/wait_for_purge.inc "master-bin.000002" diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index 65b13b57f2d..09b35011f1f 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -28,6 +28,7 @@ CHANGE MASTER TO master_use_gtid=current_pos; --write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect wait EOF +FLUSH LOGS; --shutdown_server 30 --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff index b2556feb1ad..41ec54bb4fa 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff @@ -1,5 +1,5 @@ ---- r/sysvars_innodb.result -+++ r/sysvars_innodb,32bit.result~ +--- ./suite/sys_vars/r/sysvars_innodb.result 2017-01-03 12:06:25.401683053 +0200 ++++ ./suite/sys_vars/r/sysvars_innodb,32bit.reject 2017-01-04 18:26:46.741752657 +0200 @@ -53,7 +53,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 @@ -103,7 +103,7 @@ VARIABLE_COMMENT Helps in performance tuning in heavily concurrent environments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -543,7 +543,7 @@ +@@ -557,7 +557,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5 VARIABLE_SCOPE GLOBAL @@ -112,7 +112,7 @@ VARIABLE_COMMENT If the compression failure rate of a table is greater than this number more padding is added to the pages to reduce the failures. A value of zero implies no padding NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -571,7 +571,7 @@ +@@ -585,7 +585,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -121,7 +121,7 @@ VARIABLE_COMMENT Percentage of empty space on a data page that can be reserved to make the page compressible. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 75 -@@ -599,10 +599,10 @@ +@@ -613,10 +613,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5000 VARIABLE_SCOPE GLOBAL @@ -134,7 +134,16 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -837,7 +837,7 @@ +@@ -641,7 +641,7 @@ + GLOBAL_VALUE_ORIGIN COMPILE-TIME + DEFAULT_VALUE 0 + VARIABLE_SCOPE GLOBAL +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT InnoDB system tablespace size to be set in recovery. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 +@@ -865,7 +865,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 120 VARIABLE_SCOPE GLOBAL @@ -143,7 +152,7 @@ VARIABLE_COMMENT Number of pages reserved in doublewrite buffer for batch flushing NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 127 -@@ -921,7 +921,7 @@ +@@ -949,7 +949,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE GLOBAL @@ -152,7 +161,7 @@ VARIABLE_COMMENT Speeds up the shutdown process of the InnoDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like). NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2 -@@ -935,7 +935,7 @@ +@@ -963,7 +963,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 600 VARIABLE_SCOPE GLOBAL @@ -161,7 +170,7 @@ VARIABLE_COMMENT Maximum number of seconds that semaphore times out in InnoDB. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1005,7 +1005,7 @@ +@@ -1033,7 +1033,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -170,7 +179,7 @@ VARIABLE_COMMENT Percentage of B-tree page filled during bulk insert NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100 -@@ -1019,7 +1019,7 @@ +@@ -1047,7 +1047,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -179,7 +188,7 @@ VARIABLE_COMMENT Make the first page of the given tablespace dirty. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1033,7 +1033,7 @@ +@@ -1061,7 +1061,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE GLOBAL @@ -188,7 +197,7 @@ VARIABLE_COMMENT Number of iterations over which the background flushing is averaged. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1000 -@@ -1061,7 +1061,7 @@ +@@ -1089,7 +1089,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE GLOBAL @@ -197,7 +206,7 @@ VARIABLE_COMMENT Controls the durability/speed trade-off for commits. Set to 0 (write and flush redo log to disk only once per second), 1 (flush to disk at each commit), 2 (write to log at commit but flush to disk only once per second) or 3 (flush to disk at prepare and at commit, slower and usually redundant). 1 and 3 guarantees that after a crash, committed transactions will not be lost and will be consistent with the binlog and other transactional engines. 2 can get inconsistent and lose transactions if there is a power failure or kernel crash but not if mysqld crashes. 0 has no guarantees in case of crash. 0 and 2 can be faster than 1 or 3. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 3 -@@ -1089,7 +1089,7 @@ +@@ -1117,7 +1117,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE GLOBAL @@ -206,7 +215,7 @@ VARIABLE_COMMENT Set to 0 (don't flush neighbors from buffer pool), 1 (flush contiguous neighbors from buffer pool) or 2 (flush neighbors from buffer pool), when flushing a block NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2 -@@ -1145,7 +1145,7 @@ +@@ -1173,7 +1173,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -215,7 +224,7 @@ VARIABLE_COMMENT Helps to save your data in case the disk image of the database becomes corrupt. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 6 -@@ -1159,7 +1159,7 @@ +@@ -1187,7 +1187,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -224,7 +233,7 @@ VARIABLE_COMMENT Kills the server during crash recovery. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -1187,7 +1187,7 @@ +@@ -1215,7 +1215,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8000000 VARIABLE_SCOPE GLOBAL @@ -233,7 +242,7 @@ VARIABLE_COMMENT InnoDB Fulltext search cache size in bytes NUMERIC_MIN_VALUE 1600000 NUMERIC_MAX_VALUE 80000000 -@@ -1229,7 +1229,7 @@ +@@ -1257,7 +1257,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 84 VARIABLE_SCOPE GLOBAL @@ -242,7 +251,7 @@ VARIABLE_COMMENT InnoDB Fulltext search maximum token size in characters NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -1243,7 +1243,7 @@ +@@ -1271,7 +1271,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 3 VARIABLE_SCOPE GLOBAL @@ -251,7 +260,7 @@ VARIABLE_COMMENT InnoDB Fulltext search minimum token size in characters NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16 -@@ -1257,7 +1257,7 @@ +@@ -1285,7 +1285,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2000 VARIABLE_SCOPE GLOBAL @@ -260,7 +269,7 @@ VARIABLE_COMMENT InnoDB Fulltext search number of words to optimize for each optimize table call NUMERIC_MIN_VALUE 1000 NUMERIC_MAX_VALUE 10000 -@@ -1271,7 +1271,7 @@ +@@ -1299,7 +1299,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2000000000 VARIABLE_SCOPE GLOBAL @@ -269,7 +278,7 @@ VARIABLE_COMMENT InnoDB Fulltext search query result cache limit in bytes NUMERIC_MIN_VALUE 1000000 NUMERIC_MAX_VALUE 4294967295 -@@ -1299,7 +1299,7 @@ +@@ -1327,7 +1327,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -278,7 +287,7 @@ VARIABLE_COMMENT InnoDB Fulltext search parallel sort degree, will round up to nearest power of 2 number NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 16 -@@ -1313,7 +1313,7 @@ +@@ -1341,7 +1341,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 640000000 VARIABLE_SCOPE GLOBAL @@ -287,7 +296,7 @@ VARIABLE_COMMENT Total memory allocated for InnoDB Fulltext Search cache NUMERIC_MIN_VALUE 32000000 NUMERIC_MAX_VALUE 1600000000 -@@ -1341,7 +1341,7 @@ +@@ -1369,7 +1369,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -296,7 +305,7 @@ VARIABLE_COMMENT Up to what percentage of dirty pages should be flushed when innodb finds it has spare resources to do so. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -1383,10 +1383,10 @@ +@@ -1411,10 +1411,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 200 VARIABLE_SCOPE GLOBAL @@ -309,7 +318,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1395,12 +1395,12 @@ +@@ -1423,12 +1423,12 @@ SESSION_VALUE NULL GLOBAL_VALUE 2000 GLOBAL_VALUE_ORIGIN COMPILE-TIME @@ -325,7 +334,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1453,7 +1453,7 @@ +@@ -1495,7 +1495,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE SESSION @@ -334,7 +343,7 @@ VARIABLE_COMMENT Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1073741824 -@@ -1467,10 +1467,10 @@ +@@ -1509,10 +1509,10 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 16777216 VARIABLE_SCOPE GLOBAL @@ -347,7 +356,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -1523,7 +1523,7 @@ +@@ -1565,7 +1565,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -356,7 +365,7 @@ VARIABLE_COMMENT Number of log files in the log group. InnoDB writes to the files in a circular fashion. NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 100 -@@ -1565,7 +1565,7 @@ +@@ -1607,7 +1607,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8192 VARIABLE_SCOPE GLOBAL @@ -365,7 +374,7 @@ VARIABLE_COMMENT Redo log write ahead unit size to avoid read-on-write, it should match the OS cache block IO size NUMERIC_MIN_VALUE 512 NUMERIC_MAX_VALUE 16384 -@@ -1579,10 +1579,10 @@ +@@ -1621,10 +1621,10 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -378,7 +387,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1635,10 +1635,10 @@ +@@ -1677,10 +1677,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -391,7 +400,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1649,7 +1649,7 @@ +@@ -1691,7 +1691,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -400,7 +409,7 @@ VARIABLE_COMMENT Maximum delay of user threads in micro-seconds NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 10000000 -@@ -1747,7 +1747,7 @@ +@@ -1789,7 +1789,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL @@ -409,7 +418,7 @@ VARIABLE_COMMENT Number of multi-threaded flush threads NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 64 -@@ -1803,10 +1803,10 @@ +@@ -1845,10 +1845,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -422,7 +431,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -1831,7 +1831,7 @@ +@@ -1873,7 +1873,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4 VARIABLE_SCOPE GLOBAL @@ -431,7 +440,7 @@ VARIABLE_COMMENT Page cleaner threads can be from 1 to 64. Default is 4. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 64 -@@ -1859,7 +1859,7 @@ +@@ -1901,7 +1901,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16 VARIABLE_SCOPE GLOBAL @@ -440,7 +449,7 @@ VARIABLE_COMMENT Number of rw_locks protecting buffer pool page_hash. Rounded up to the next power of 2 NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -1873,7 +1873,7 @@ +@@ -1915,7 +1915,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE GLOBAL @@ -449,7 +458,7 @@ VARIABLE_COMMENT Page size to use for all InnoDB tablespaces. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 65536 -@@ -1915,7 +1915,7 @@ +@@ -1957,7 +1957,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 300 VARIABLE_SCOPE GLOBAL @@ -458,7 +467,7 @@ VARIABLE_COMMENT Number of UNDO log pages to purge in one batch from the history list. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5000 -@@ -1929,7 +1929,7 @@ +@@ -1971,7 +1971,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 128 VARIABLE_SCOPE GLOBAL @@ -467,7 +476,7 @@ VARIABLE_COMMENT Dictates rate at which UNDO records are purged. Value N means purge rollback segment(s) on every Nth iteration of purge invocation NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -1971,7 +1971,7 @@ +@@ -2013,7 +2013,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4 VARIABLE_SCOPE GLOBAL @@ -476,7 +485,7 @@ VARIABLE_COMMENT Purge threads can be from 1 to 32. Default is 4. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 32 -@@ -1999,7 +1999,7 @@ +@@ -2041,7 +2041,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 56 VARIABLE_SCOPE GLOBAL @@ -485,7 +494,7 @@ VARIABLE_COMMENT Number of pages that must be accessed sequentially for InnoDB to trigger a readahead. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 64 -@@ -2013,7 +2013,7 @@ +@@ -2055,7 +2055,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 4 VARIABLE_SCOPE GLOBAL @@ -494,7 +503,7 @@ VARIABLE_COMMENT Number of background read I/O threads in InnoDB. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 64 -@@ -2041,10 +2041,10 @@ +@@ -2083,10 +2083,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -507,7 +516,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2069,7 +2069,7 @@ +@@ -2111,7 +2111,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 128 VARIABLE_SCOPE GLOBAL @@ -516,7 +525,7 @@ VARIABLE_COMMENT Number of undo logs to use (deprecated). NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -2083,7 +2083,7 @@ +@@ -2125,7 +2125,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -525,7 +534,7 @@ VARIABLE_COMMENT An InnoDB page number. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2139,7 +2139,7 @@ +@@ -2181,7 +2181,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -534,7 +543,7 @@ VARIABLE_COMMENT Memory buffer size for index creation NUMERIC_MIN_VALUE 65536 NUMERIC_MAX_VALUE 67108864 -@@ -2153,10 +2153,10 @@ +@@ -2195,10 +2195,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL @@ -547,7 +556,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2349,7 +2349,7 @@ +@@ -2391,7 +2391,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE GLOBAL @@ -556,7 +565,7 @@ VARIABLE_COMMENT Size of the mutex/lock wait array. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2377,10 +2377,10 @@ +@@ -2419,10 +2419,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE GLOBAL @@ -569,7 +578,7 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2419,7 +2419,7 @@ +@@ -2461,7 +2461,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -578,7 +587,7 @@ VARIABLE_COMMENT Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -2433,7 +2433,7 @@ +@@ -2475,7 +2475,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10000 VARIABLE_SCOPE GLOBAL @@ -587,7 +596,7 @@ VARIABLE_COMMENT Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0 disable a sleep NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000000 -@@ -2503,7 +2503,7 @@ +@@ -2545,7 +2545,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 128 VARIABLE_SCOPE GLOBAL @@ -596,7 +605,7 @@ VARIABLE_COMMENT Number of undo logs to use. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 128 -@@ -2531,7 +2531,7 @@ +@@ -2573,7 +2573,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -605,7 +614,7 @@ VARIABLE_COMMENT Number of undo tablespaces to use. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 95 -@@ -2615,7 +2615,7 @@ +@@ -2657,7 +2657,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 4 VARIABLE_SCOPE GLOBAL diff --git a/sql/table.cc b/sql/table.cc index b7f83a502b7..41f764d1e59 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2410,8 +2410,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } } } - DBUG_ASSERT((table_check_constraints - share->check_constraints) == - share->table_check_constraints - share->field_check_constraints); + DBUG_ASSERT((uint) (table_check_constraints - share->check_constraints) == + (uint) (share->table_check_constraints - + share->field_check_constraints)); if (options) { diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 0a178abde37..5711a681e63 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4790,7 +4790,7 @@ lock_table( lock_mutex_enter(); DBUG_EXECUTE_IF("fatal-semaphore-timeout", - { os_thread_sleep(3600000000); }); + { os_thread_sleep(3600000000LL); }); /* We have to check if the new lock is compatible with any locks other transactions have in the table lock queue. */ From 135e144479c70d8e470e67fd95e4b17051127952 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 5 Jan 2017 01:07:03 +0200 Subject: [PATCH 059/167] MDEV-11598 Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed Found and fixed 2 problems: - Filesort addon fields didn't mark virtual columns properly - multi-range-read calculated vcol bitmap but was not using it. This caused wrong vcol field to be calculated on read, which caused the assert. --- mysql-test/suite/vcol/inc/vcol_keys.inc | 51 ++++++++++++++++++ .../suite/vcol/r/vcol_keys_innodb.result | 47 ++++++++++++++++ .../suite/vcol/r/vcol_keys_myisam.result | 47 ++++++++++++++++ sql/field.cc | 11 ++++ sql/field.h | 3 ++ sql/filesort.cc | 38 ++++++------- sql/opt_range.cc | 53 +++++++++++++------ sql/opt_range.h | 12 ++--- 8 files changed, 216 insertions(+), 46 deletions(-) diff --git a/mysql-test/suite/vcol/inc/vcol_keys.inc b/mysql-test/suite/vcol/inc/vcol_keys.inc index 4d4773ec3a6..7c9f60c0fb0 100644 --- a/mysql-test/suite/vcol/inc/vcol_keys.inc +++ b/mysql-test/suite/vcol/inc/vcol_keys.inc @@ -181,3 +181,54 @@ create table t1 (a int, b double as (rand())); --error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED alter table t1 add index (b); drop table t1; + +# +# MDEV-11598 Assertion `!table || (!table->read_set... failed +# + +CREATE OR REPLACE TABLE t1 ( + f2 DOUBLE NOT NULL DEFAULT '0', + f3 DOUBLE NOT NULL DEFAULT '0', + f4 DOUBLE, + f5 DOUBLE DEFAULT '0', + v4 DOUBLE AS (IF(f4,f3,f2)) VIRTUAL, + KEY (f5), + KEY (v4) +); + +INSERT INTO t1 (f2,f3,f4,f5) VALUES (5,4,1,0),(5,7,NULL,0); +INSERT INTO t1 (f2,f3,f4,f5) SELECT f2, f3, f5, f3 FROM t1; +INSERT INTO t1 (f2,f3,f4,f5) VALUES (5,0,NULL,1); +INSERT INTO t1 (f2,f3,f4,f5) SELECT f2, f5, f5, f3 FROM t1; +DELETE FROM t1 WHERE f5 = 1 OR v4 = 4 ORDER BY f5,v4 LIMIT 9; +SELECT * from t1; +DROP TABLE t1; + +# Another similar failure + +CREATE TABLE t1 ( + d DECIMAL(63,0) NOT NULL DEFAULT 0, + c VARCHAR(64) NOT NULL DEFAULT '', + vd DECIMAL(63,0) AS (d) VIRTUAL, + vc VARCHAR(2048) AS (c) VIRTUAL, + pk BIGINT AUTO_INCREMENT, + PRIMARY KEY(pk)); + +INSERT INTO t1 (d,c) VALUES (0.5,'foo'); +SELECT * FROM t1 WHERE vc != 'bar' ORDER BY vd; +DROP TABLE t1; + +# +# MDEV-11729: Crash when using partial indexed virtual fields +# + +CREATE TABLE t1 ( + pk BIGINT, + c CHAR(64) NOT NULL DEFAULT '', + vc CHAR(64) AS (c) VIRTUAL, + PRIMARY KEY(pk), + INDEX(vc(32)) +); +DELETE FROM t1 WHERE vc IS NULL ORDER BY pk; +DROP TABLE t1; + diff --git a/mysql-test/suite/vcol/r/vcol_keys_innodb.result b/mysql-test/suite/vcol/r/vcol_keys_innodb.result index 43c911118c2..19e0db00336 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result @@ -168,3 +168,50 @@ create table t1 (a int, b double as (rand())); alter table t1 add index (b); ERROR HY000: Function or expression 'rand()' cannot be used in the GENERATED ALWAYS AS clause of `b` drop table t1; +CREATE OR REPLACE TABLE t1 ( +f2 DOUBLE NOT NULL DEFAULT '0', +f3 DOUBLE NOT NULL DEFAULT '0', +f4 DOUBLE, +f5 DOUBLE DEFAULT '0', +v4 DOUBLE AS (IF(f4,f3,f2)) VIRTUAL, +KEY (f5), +KEY (v4) +); +INSERT INTO t1 (f2,f3,f4,f5) VALUES (5,4,1,0),(5,7,NULL,0); +INSERT INTO t1 (f2,f3,f4,f5) SELECT f2, f3, f5, f3 FROM t1; +INSERT INTO t1 (f2,f3,f4,f5) VALUES (5,0,NULL,1); +INSERT INTO t1 (f2,f3,f4,f5) SELECT f2, f5, f5, f3 FROM t1; +DELETE FROM t1 WHERE f5 = 1 OR v4 = 4 ORDER BY f5,v4 LIMIT 9; +SELECT * from t1; +f2 f3 f4 f5 v4 +5 7 NULL 0 5 +5 4 0 4 5 +5 7 0 7 5 +5 0 0 4 5 +5 0 0 7 5 +5 7 7 7 7 +5 1 1 0 1 +DROP TABLE t1; +CREATE TABLE t1 ( +d DECIMAL(63,0) NOT NULL DEFAULT 0, +c VARCHAR(64) NOT NULL DEFAULT '', +vd DECIMAL(63,0) AS (d) VIRTUAL, +vc VARCHAR(2048) AS (c) VIRTUAL, +pk BIGINT AUTO_INCREMENT, +PRIMARY KEY(pk)); +INSERT INTO t1 (d,c) VALUES (0.5,'foo'); +Warnings: +Note 1265 Data truncated for column 'd' at row 1 +SELECT * FROM t1 WHERE vc != 'bar' ORDER BY vd; +d c vd vc pk +1 foo 1 foo 1 +DROP TABLE t1; +CREATE TABLE t1 ( +pk BIGINT, +c CHAR(64) NOT NULL DEFAULT '', +vc CHAR(64) AS (c) VIRTUAL, +PRIMARY KEY(pk), +INDEX(vc(32)) +); +DELETE FROM t1 WHERE vc IS NULL ORDER BY pk; +DROP TABLE t1; diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index efca19db5bb..eebf0eacafb 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -278,3 +278,50 @@ create table t1 (a int, b double as (rand())); alter table t1 add index (b); ERROR HY000: Function or expression 'rand()' cannot be used in the GENERATED ALWAYS AS clause of `b` drop table t1; +CREATE OR REPLACE TABLE t1 ( +f2 DOUBLE NOT NULL DEFAULT '0', +f3 DOUBLE NOT NULL DEFAULT '0', +f4 DOUBLE, +f5 DOUBLE DEFAULT '0', +v4 DOUBLE AS (IF(f4,f3,f2)) VIRTUAL, +KEY (f5), +KEY (v4) +); +INSERT INTO t1 (f2,f3,f4,f5) VALUES (5,4,1,0),(5,7,NULL,0); +INSERT INTO t1 (f2,f3,f4,f5) SELECT f2, f3, f5, f3 FROM t1; +INSERT INTO t1 (f2,f3,f4,f5) VALUES (5,0,NULL,1); +INSERT INTO t1 (f2,f3,f4,f5) SELECT f2, f5, f5, f3 FROM t1; +DELETE FROM t1 WHERE f5 = 1 OR v4 = 4 ORDER BY f5,v4 LIMIT 9; +SELECT * from t1; +f2 f3 f4 f5 v4 +5 7 NULL 0 5 +5 4 0 4 5 +5 7 0 7 5 +5 0 0 4 5 +5 0 0 7 5 +5 7 7 7 7 +5 1 1 0 1 +DROP TABLE t1; +CREATE TABLE t1 ( +d DECIMAL(63,0) NOT NULL DEFAULT 0, +c VARCHAR(64) NOT NULL DEFAULT '', +vd DECIMAL(63,0) AS (d) VIRTUAL, +vc VARCHAR(2048) AS (c) VIRTUAL, +pk BIGINT AUTO_INCREMENT, +PRIMARY KEY(pk)); +INSERT INTO t1 (d,c) VALUES (0.5,'foo'); +Warnings: +Note 1265 Data truncated for column 'd' at row 1 +SELECT * FROM t1 WHERE vc != 'bar' ORDER BY vd; +d c vd vc pk +1 foo 1 foo 1 +DROP TABLE t1; +CREATE TABLE t1 ( +pk BIGINT, +c CHAR(64) NOT NULL DEFAULT '', +vc CHAR(64) AS (c) VIRTUAL, +PRIMARY KEY(pk), +INDEX(vc(32)) +); +DELETE FROM t1 WHERE vc IS NULL ORDER BY pk; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 8d53fca27d7..ff8b948ef62 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10864,3 +10864,14 @@ bool Field::save_in_field_ignore_value(bool view_error_processing) return save_in_field_default_value(view_error_processing); return 0; // ignore } + + +void Field::register_field_in_read_map() +{ + if (vcol_info) + { + Item *vcol_item= vcol_info->expr; + vcol_item->walk(&Item::register_field_in_read_map, 1, 0); + } + bitmap_set_bit(table->read_set, field_index); +} diff --git a/sql/field.h b/sql/field.h index 400d2ef0e5e..fd68ade1165 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1475,6 +1475,9 @@ public: bool save_in_field_default_value(bool view_eror_processing); bool save_in_field_ignore_value(bool view_error_processing); + /* Mark field in read map. Updates also virtual fields */ + void register_field_in_read_map(); + friend int cre_myisam(char * name, register TABLE *form, uint options, ulonglong auto_increment_value); friend class Copy_field; diff --git a/sql/filesort.cc b/sql/filesort.cc index 2210dc569df..6046693cba1 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -716,7 +716,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, TABLE *sort_form; handler *file; MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set; - + Item *sort_cond; DBUG_ENTER("find_all_keys"); DBUG_PRINT("info",("using: %s", (select ? select->quick ? "ranges" : "where": @@ -754,22 +754,22 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select, /* Remember original bitmaps */ save_read_set= sort_form->read_set; save_write_set= sort_form->write_set; - save_vcol_set= sort_form->vcol_set; + save_vcol_set= sort_form->vcol_set; + /* Set up temporary column read map for columns used by sort */ bitmap_clear_all(&sort_form->tmp_set); - /* Temporary set for register_used_fields and register_field_in_read_map */ - sort_form->read_set= &sort_form->tmp_set; - register_used_fields(param); - if (quick_select) - select->quick->add_used_key_part_to_set(sort_form->read_set); - - Item *sort_cond= !select ? - 0 : !select->pre_idx_push_select_cond ? - select->cond : select->pre_idx_push_select_cond; - if (sort_cond) - sort_cond->walk(&Item::register_field_in_read_map, 1, sort_form); sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set, &sort_form->tmp_set); + register_used_fields(param); + if (quick_select) + select->quick->add_used_key_part_to_set(); + + sort_cond= (!select ? 0 : + (!select->pre_idx_push_select_cond ? + select->cond : select->pre_idx_push_select_cond)); + if (sort_cond) + sort_cond->walk(&Item::register_field_in_read_map, 1, sort_form); + sort_form->file->column_bitmaps_signal(); if (quick_select) { @@ -1259,7 +1259,6 @@ static void register_used_fields(Sort_param *param) { reg1 SORT_FIELD *sort_field; TABLE *table=param->sort_form; - MY_BITMAP *bitmap= table->read_set; for (sort_field= param->local_sortorder ; sort_field != param->end ; @@ -1269,14 +1268,7 @@ static void register_used_fields(Sort_param *param) if ((field= sort_field->field)) { if (field->table == table) - { - if (field->vcol_info) - { - Item *vcol_item= field->vcol_info->expr; - vcol_item->walk(&Item::register_field_in_read_map, 1, 0); - } - bitmap_set_bit(bitmap, field->field_index); - } + field->register_field_in_read_map(); } else { // Item @@ -1289,7 +1281,7 @@ static void register_used_fields(Sort_param *param) SORT_ADDON_FIELD *addonf= param->addon_field; Field *field; for ( ; (field= addonf->field) ; addonf++) - bitmap_set_bit(bitmap, field->field_index); + field->register_field_in_read_map(); } else { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 01b836fddf7..8446da51926 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -11101,6 +11101,7 @@ int QUICK_RANGE_SELECT::reset() HANDLER_BUFFER empty_buf; MY_BITMAP * const save_read_set= head->read_set; MY_BITMAP * const save_write_set= head->write_set; + MY_BITMAP * const save_vcol_set= head->vcol_set; DBUG_ENTER("QUICK_RANGE_SELECT::reset"); last_range= NULL; cur_range= (QUICK_RANGE**) ranges.buffer; @@ -11114,7 +11115,8 @@ int QUICK_RANGE_SELECT::reset() } if (in_ror_merged_scan) - head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap); + head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, + &column_bitmap); if (file->inited == handler::NONE) { @@ -11157,8 +11159,8 @@ int QUICK_RANGE_SELECT::reset() err: /* Restore bitmaps set on entry */ if (in_ror_merged_scan) - head->column_bitmaps_set_no_signal(save_read_set, save_write_set); - + head->column_bitmaps_set_no_signal(save_read_set, save_write_set, + save_vcol_set); DBUG_RETURN(error); } @@ -11189,13 +11191,16 @@ int QUICK_RANGE_SELECT::get_next() MY_BITMAP * const save_read_set= head->read_set; MY_BITMAP * const save_write_set= head->write_set; + MY_BITMAP * const save_vcol_set= head->vcol_set; /* We don't need to signal the bitmap change as the bitmap is always the same for this head->file */ - head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap); + head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, + &column_bitmap); result= file->multi_range_read_next(&dummy); - head->column_bitmaps_set_no_signal(save_read_set, save_write_set); + head->column_bitmaps_set_no_signal(save_read_set, save_write_set, + save_vcol_set); DBUG_RETURN(result); } @@ -11372,7 +11377,7 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, used_key_parts (used_key_parts_arg) { QUICK_RANGE *r; - /* + /* Use default MRR implementation for reverse scans. No table engine currently can do an MRR scan with output in reverse index order. */ @@ -11847,62 +11852,76 @@ void QUICK_ROR_UNION_SELECT::add_keys_and_lengths(String *key_names, } -void QUICK_RANGE_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set) +void QUICK_RANGE_SELECT::add_used_key_part_to_set() { uint key_len; KEY_PART *part= key_parts; for (key_len=0; key_len < max_used_key_length; key_len += (part++)->store_length) { - bitmap_set_bit(col_set, part->field->field_index); + /* + We have to use field_index instead of part->field + as for partial fields, part->field points to + a temporary field that is only part of the original + field. field_index always points to the original field + */ + Field *field= head->field[part->field->field_index]; + field->register_field_in_read_map(); } } -void QUICK_GROUP_MIN_MAX_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set) +void QUICK_GROUP_MIN_MAX_SELECT::add_used_key_part_to_set() { uint key_len; KEY_PART_INFO *part= index_info->key_part; for (key_len=0; key_len < max_used_key_length; key_len += (part++)->store_length) { - bitmap_set_bit(col_set, part->field->field_index); + /* + We have to use field_index instead of part->field + as for partial fields, part->field points to + a temporary field that is only part of the original + field. field_index always points to the original field + */ + Field *field= head->field[part->field->field_index]; + field->register_field_in_read_map(); } } -void QUICK_ROR_INTERSECT_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set) +void QUICK_ROR_INTERSECT_SELECT::add_used_key_part_to_set() { List_iterator_fast it(quick_selects); QUICK_SELECT_WITH_RECORD *quick; while ((quick= it++)) { - quick->quick->add_used_key_part_to_set(col_set); + quick->quick->add_used_key_part_to_set(); } } -void QUICK_INDEX_SORT_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set) +void QUICK_INDEX_SORT_SELECT::add_used_key_part_to_set() { QUICK_RANGE_SELECT *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - quick->add_used_key_part_to_set(col_set); + quick->add_used_key_part_to_set(); } if (pk_quick_select) - pk_quick_select->add_used_key_part_to_set(col_set); + pk_quick_select->add_used_key_part_to_set(); } -void QUICK_ROR_UNION_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set) +void QUICK_ROR_UNION_SELECT::add_used_key_part_to_set() { QUICK_SELECT_I *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - quick->add_used_key_part_to_set(col_set); + quick->add_used_key_part_to_set(); } } diff --git a/sql/opt_range.h b/sql/opt_range.h index 6970b87f6d8..9e4521a9437 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -1006,7 +1006,7 @@ public: This is used by an optimization in filesort. */ - virtual void add_used_key_part_to_set(MY_BITMAP *col_set)=0; + virtual void add_used_key_part_to_set()=0; }; @@ -1097,7 +1097,7 @@ public: virtual void replace_handler(handler *new_file) { file= new_file; } QUICK_SELECT_I *make_reverse(uint used_key_parts_arg); - virtual void add_used_key_part_to_set(MY_BITMAP *col_set); + virtual void add_used_key_part_to_set(); private: /* Default copy ctor used by QUICK_SELECT_DESC */ @@ -1261,7 +1261,7 @@ public: /* used to get rows collected in Unique */ READ_RECORD read_record; - virtual void add_used_key_part_to_set(MY_BITMAP *col_set); + virtual void add_used_key_part_to_set(); }; @@ -1336,7 +1336,7 @@ public: void add_keys_and_lengths(String *key_names, String *used_lengths); Explain_quick_select *get_explain(MEM_ROOT *alloc); bool is_keys_used(const MY_BITMAP *fields); - void add_used_key_part_to_set(MY_BITMAP *col_set); + void add_used_key_part_to_set(); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif @@ -1416,7 +1416,7 @@ public: void add_keys_and_lengths(String *key_names, String *used_lengths); Explain_quick_select *get_explain(MEM_ROOT *alloc); bool is_keys_used(const MY_BITMAP *fields); - void add_used_key_part_to_set(MY_BITMAP *col_set); + void add_used_key_part_to_set(); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif @@ -1560,7 +1560,7 @@ public: bool unique_key_range() { return false; } int get_type() { return QS_TYPE_GROUP_MIN_MAX; } void add_keys_and_lengths(String *key_names, String *used_lengths); - void add_used_key_part_to_set(MY_BITMAP *col_set); + void add_used_key_part_to_set(); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif From 6c5c98316f6c5e4ad84ce5b4cb657459828e805d Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 5 Jan 2017 14:36:44 +0200 Subject: [PATCH 060/167] Updated mysql-test/README with information about KB --- mysql-test/README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mysql-test/README b/mysql-test/README index 0fba1cc07e3..28b8203b2dc 100644 --- a/mysql-test/README +++ b/mysql-test/README @@ -76,3 +76,9 @@ then put your .test file and .result file(s) into a tar.gz archive, add a README that explains the problem, ftp the archive to ftp://ftp.askmonty.org/private and submit a report to http://mariadb.org/jira about it. + +The latest information about mysql-test-run can be found at: +https://mariadb.com/kb/en/mariadb/mysqltest/ + +If you want to create .rdiff files, check +https://mariadb.com/kb/en/mariadb/mysql-test-auxiliary-files/ From c9b3e4535bb4b6d2aa0f7bc1ce71730e6aceca8b Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 9 Jan 2017 18:46:20 +0200 Subject: [PATCH 061/167] MDEV-11737 Failing assertion: block->magic_n == MEM_BLOCK_MAGIC_N Issue was that the m_prebuilt array was reused without resetting a counter, which caused a memory overrun. Adjusted test case to 79 characters --- .../suite/vcol/r/vcol_keys_innodb.result | 10 ++++ mysql-test/suite/vcol/t/vcol_keys_innodb.test | 59 +++++++++++-------- storage/innobase/handler/ha_innodb.cc | 3 + 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/mysql-test/suite/vcol/r/vcol_keys_innodb.result b/mysql-test/suite/vcol/r/vcol_keys_innodb.result index 19e0db00336..5053b5105cf 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result @@ -215,3 +215,13 @@ INDEX(vc(32)) ); DELETE FROM t1 WHERE vc IS NULL ORDER BY pk; DROP TABLE t1; +# +# MDEV-11737 Failing assertion: block->magic_n == MEM_BLOCK_MAGIC_N +# +CREATE TABLE t1 (i INT PRIMARY KEY, vi INT AS (i*2) VIRTUAL UNIQUE) +ENGINE=InnoDB; +CREATE TABLE t2 (i INT) ENGINE=InnoDB; +ALTER TABLE t1 ADD COLUMN col INT; +SELECT * FROM t1 WHERE vi < 2; +i vi col +DROP TABLE t1, t2; diff --git a/mysql-test/suite/vcol/t/vcol_keys_innodb.test b/mysql-test/suite/vcol/t/vcol_keys_innodb.test index 8eeef96b43f..c872a9a6fe0 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_keys_innodb.test @@ -1,34 +1,34 @@ -################################################################################ -# t/vcol_keys_innodb.test # -# # -# Purpose: # -# Testing keys, indexes defined upon virtual columns. # -# # -# InnoDB branch # -# # -#------------------------------------------------------------------------------# -# Original Author: Andrey Zhakov # -# Original Date: 2008-09-04 # -# Change Author: # -# Change Date: # -# Change: # -################################################################################ +############################################################################### +# t/vcol_keys_innodb.test # +# # +# Purpose: # +# Testing keys, indexes defined upon virtual columns. # +# # +# InnoDB branch # +# # +#-----------------------------------------------------------------------------# +# Original Author: Andrey Zhakov # +# Original Date: 2008-09-04 # +# Change Author: # +# Change Date: # +# Change: # +############################################################################### # -# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE ! +# NOTE: PLEASE DO NOT ADD NOT INNODB SPECIFIC TESTCASES HERE ! # TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN # THE SOURCED FILES ONLY. # -#------------------------------------------------------------------------------# +#-----------------------------------------------------------------------------# # General not engine specific settings and requirements --source suite/vcol/inc/vcol_init_vars.pre -#------------------------------------------------------------------------------# +#-----------------------------------------------------------------------------# # Cleanup --source suite/vcol/inc/vcol_cleanup.inc -#------------------------------------------------------------------------------# +#-----------------------------------------------------------------------------# # Engine specific settings and requirements ##### Storage engine to be tested @@ -39,14 +39,25 @@ SET @@session.storage_engine = 'InnoDB'; ##### Workarounds for known open engine specific bugs # none -#------------------------------------------------------------------------------# +#-----------------------------------------------------------------------------# # Execute the tests to be applied to all storage engines let $with_foreign_keys = 1; --source suite/vcol/inc/vcol_keys.inc -#------------------------------------------------------------------------------# -# Execute storage engine specific tests - -#------------------------------------------------------------------------------# # Cleanup --source suite/vcol/inc/vcol_cleanup.inc + +#-----------------------------------------------------------------------------# +# Execute storage engine specific tests +#-----------------------------------------------------------------------------# + +--echo # +--echo # MDEV-11737 Failing assertion: block->magic_n == MEM_BLOCK_MAGIC_N +--echo # + +CREATE TABLE t1 (i INT PRIMARY KEY, vi INT AS (i*2) VIRTUAL UNIQUE) +ENGINE=InnoDB; +CREATE TABLE t2 (i INT) ENGINE=InnoDB; +ALTER TABLE t1 ADD COLUMN col INT; +SELECT * FROM t1 WHERE vi < 2; +DROP TABLE t1, t2; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ff80d967092..d9c32f286e6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8497,7 +8497,10 @@ ha_innobase::build_template( index_contains = dict_index_contains_col_or_prefix( index, num_v, true); if (index_contains) + { + m_prebuilt->n_template = 0; goto no_icp; + } } else { index_contains = dict_index_contains_col_or_prefix( index, i - num_v, false); From 177c191ff4b9c0033665a292fdb5907095ddb823 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 9 Jan 2017 19:31:21 +0200 Subject: [PATCH 062/167] MDEV-11606 Server crashes in mi_make_key / sort_key_read Problem was that one internal record buffer in MYISAM was not big enough to handle virtual fields. Fixed by extending buffer. Fixed test case to 79 characters --- .../suite/vcol/r/vcol_keys_myisam.result | 270 ++++++++++-------- mysql-test/suite/vcol/t/vcol_keys_myisam.test | 245 ++++++++++++---- storage/myisam/mi_check.c | 2 +- storage/myisam/mi_open.c | 1 + 4 files changed, 351 insertions(+), 167 deletions(-) diff --git a/mysql-test/suite/vcol/r/vcol_keys_myisam.result b/mysql-test/suite/vcol/r/vcol_keys_myisam.result index eebf0eacafb..078d6cfff1c 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_keys_myisam.result @@ -1,119 +1,3 @@ -create table t1 (a int, b int as (a+1), c int, index(b)); -insert t1 (a,c) values (0x7890abcd, 0x76543210); -insert t1 (a,c) select seq, sin(seq)*10000 from seq_1_to_1000; -explain select * from t1 where b=10; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref b b 5 const 1 -select * from t1 where b=10; -a b c -9 10 4121 - -MyISAM file: datadir/test/t1 -Record format: Fixed length -Character set: latin1_swedish_ci (8) -Data records: 1001 Deleted blocks: 0 -Recordlength: 9 - -table description: -Key Start Len Index Type -1 10 4 multip. long NULL -update t1 set a=20 where b=10; -select * from t1 where b=10; -a b c -select * from t1 where b=21; -a b c -20 21 4121 -20 21 9129 -delete from t1 where b=21; -select * from t1 where b=21; -a b c -alter table t1 add column d char(20) as (concat(a,c)); -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -create index i on t1 (d); -check table t1; -Table Op Msg_type Msg_text -test.t1 check status OK -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -check table t1 quick; -Table Op Msg_type Msg_text -test.t1 check status OK -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -check table t1 medium; -Table Op Msg_type Msg_text -test.t1 check status OK -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -check table t1 extended; -Table Op Msg_type Msg_text -test.t1 check status OK -show keys from t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 1 b 1 b A 999 NULL NULL YES BTREE -t1 1 i 1 d A 999 NULL NULL YES BTREE -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -delete from t1 where b=12; -analyze table t1; -Table Op Msg_type Msg_text -test.t1 analyze status OK -show keys from t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 1 b 1 b A 998 NULL NULL YES BTREE -t1 1 i 1 d A 998 NULL NULL YES BTREE -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -show keys from t1; -Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment -t1 1 b 1 b A 998 NULL NULL YES BTREE -t1 1 i 1 d A 998 NULL NULL YES BTREE -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -repair table t1; -Table Op Msg_type Msg_text -test.t1 repair status OK -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -repair table t1 quick; -Table Op Msg_type Msg_text -test.t1 repair status OK -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -repair table t1 extended; -Table Op Msg_type Msg_text -test.t1 repair status OK -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -repair table t1 use_frm; -Table Op Msg_type Msg_text -test.t1 repair warning Number of rows changed from 0 to 998 -test.t1 repair status OK -select * from t1 where b=11; -a b c d -10 11 -5440 10-5440 -update t1 set a=30 where b=11; -select * from t1 where b=11; -a b c d -select * from t1 where b=31; -a b c d -30 31 -5440 30-5440 -30 31 -9880 30-9880 -drop table t1; SET @@session.storage_engine = 'MyISAM'; # - UNIQUE KEY # - INDEX @@ -325,3 +209,157 @@ INDEX(vc(32)) ); DELETE FROM t1 WHERE vc IS NULL ORDER BY pk; DROP TABLE t1; +# +# Original test +# +create table t1 (a int, b int as (a+1), c int, index(b)); +insert t1 (a,c) values (0x7890abcd, 0x76543210); +insert t1 (a,c) select seq, sin(seq)*10000 from seq_1_to_1000; +explain select * from t1 where b=10; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref b b 5 const 1 +select * from t1 where b=10; +a b c +9 10 4121 + +MyISAM file: datadir/test/t1 +Record format: Fixed length +Character set: latin1_swedish_ci (8) +Data records: 1001 Deleted blocks: 0 +Recordlength: 9 + +table description: +Key Start Len Index Type +1 10 4 multip. long NULL +update t1 set a=20 where b=10; +select * from t1 where b=10; +a b c +select * from t1 where b=21; +a b c +20 21 4121 +20 21 9129 +delete from t1 where b=21; +select * from t1 where b=21; +a b c +alter table t1 add column d char(20) as (concat(a,c)); +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +create index i on t1 (d); +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +check table t1 quick; +Table Op Msg_type Msg_text +test.t1 check status OK +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +check table t1 medium; +Table Op Msg_type Msg_text +test.t1 check status OK +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +check table t1 extended; +Table Op Msg_type Msg_text +test.t1 check status OK +show keys from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 b 1 b A 999 NULL NULL YES BTREE +t1 1 i 1 d A 999 NULL NULL YES BTREE +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +delete from t1 where b=12; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +show keys from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 b 1 b A 998 NULL NULL YES BTREE +t1 1 i 1 d A 998 NULL NULL YES BTREE +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +show keys from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t1 1 b 1 b A 998 NULL NULL YES BTREE +t1 1 i 1 d A 998 NULL NULL YES BTREE +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +repair table t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +repair table t1 quick; +Table Op Msg_type Msg_text +test.t1 repair status OK +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +repair table t1 extended; +Table Op Msg_type Msg_text +test.t1 repair status OK +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair warning Number of rows changed from 0 to 998 +test.t1 repair status OK +select * from t1 where b=11; +a b c d +10 11 -5440 10-5440 +update t1 set a=30 where b=11; +select * from t1 where b=11; +a b c d +select * from t1 where b=31; +a b c d +30 31 -5440 30-5440 +30 31 -9880 30-9880 +drop table t1; +# +# MDEV-11606 Server crashes in mi_make_key / sort_key_read +# +CREATE TABLE t1 ( +pk BIGINT AUTO_INCREMENT, +col_date DATE NULL, +col_datetime DATETIME(1) NULL, +col_int TINYINT(13) UNSIGNED ZEROFILL NULL, +col_varchar VARBINARY(2222) NULL, +col_timestamp TIMESTAMP(2) NULL, +col_bit BIT(64) NOT NULL DEFAULT 0, +col_blob MEDIUMBLOB NULL, +col_dec DECIMAL(10,9) ZEROFILL NOT NULL DEFAULT 0, +col_time TIME(4) NULL, +col_year YEAR NOT NULL DEFAULT '1970', +col_char CHAR(129) NULL, +col_enum SET('','a','b','c','d','e','f','foo','bar') NULL, +vcol_dec DECIMAL(50,18) ZEROFILL AS (col_dec) VIRTUAL, +vcol_bit BIT(48) AS (col_bit) VIRTUAL, +vcol_char CHAR(224) AS (col_char) VIRTUAL, +vcol_datetime DATETIME(4) AS (col_datetime) VIRTUAL, +vcol_year YEAR AS (col_year) VIRTUAL, +vcol_varchar VARBINARY(356) AS (col_varchar) VIRTUAL, +vcol_blob MEDIUMBLOB AS (col_blob) VIRTUAL, +vcol_timestamp TIMESTAMP(5) AS (col_timestamp) VIRTUAL, +vcol_int BIGINT(46) AS (col_int) VIRTUAL, +vcol_time TIME(1) AS (col_time) VIRTUAL, +vcol_date DATE AS (col_date) VIRTUAL, +vcol_enum SET('','a','b','c','d','e','f','foo','bar') AS (col_enum) VIRTUAL, +UNIQUE(pk), +PRIMARY KEY(pk) +) ENGINE=MyISAM; +ALTER TABLE t1 ADD INDEX(col_enum,vcol_int); +ALTER TABLE t1 ADD INDEX(col_year); +DROP TABLE t1; diff --git a/mysql-test/suite/vcol/t/vcol_keys_myisam.test b/mysql-test/suite/vcol/t/vcol_keys_myisam.test index 68fd7e1731b..049037216dc 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_myisam.test +++ b/mysql-test/suite/vcol/t/vcol_keys_myisam.test @@ -1,6 +1,59 @@ - --source include/have_sequence.inc --let $datadir= `select @@datadir` +############################################################################### +# t/vcol_keys_myisam.test # +# # +# Purpose: # +# Testing keys, indexes defined upon virtual columns. # +# # +# MyISAM branch # +# # +#-----------------------------------------------------------------------------# +# Original Author: Andrey Zhakov # +# Original Date: 2008-09-04 # +# Change Author: # +# Change Date: # +# Change: # +############################################################################### + +# +# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE ! +# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN +# THE SOURCED FILES ONLY. +# + +#------------------------------------------------------------------------------ +# General not engine specific settings and requirements +--source suite/vcol/inc/vcol_init_vars.pre + +#------------------------------------------------------------------------------ +# Cleanup +--source suite/vcol/inc/vcol_cleanup.inc + +#------------------------------------------------------------------------------ +# Engine specific settings and requirements + +##### Storage engine to be tested +# Set the session storage engine +SET @@session.storage_engine = 'MyISAM'; + +##### Workarounds for known open engine specific bugs +# none + +#------------------------------------------------------------------------------ +# Execute the tests to be applied to all storage engines +--source suite/vcol/inc/vcol_keys.inc + +# Cleanup +--source suite/vcol/inc/vcol_cleanup.inc + +#-----------------------------------------------------------------------------# +# Execute storage engine specific test +#-----------------------------------------------------------------------------# + +--echo # +--echo # Original test +--echo # create table t1 (a int, b int as (a+1), c int, index(b)); insert t1 (a,c) values (0x7890abcd, 0x76543210); @@ -49,56 +102,148 @@ select * from t1 where b=31; --exec $MYISAMCHK $datadir/test/t1 --error 1 --exec $MYISAMCHK -r $datadir/test/t1 - drop table t1; -################################################################################ -# t/vcol_keys_myisam.test # -# # -# Purpose: # -# Testing keys, indexes defined upon virtual columns. # -# # -# MyISAM branch # -# # -#------------------------------------------------------------------------------# -# Original Author: Andrey Zhakov # -# Original Date: 2008-09-04 # -# Change Author: # -# Change Date: # -# Change: # -################################################################################ +--echo # +--echo # MDEV-11606 Server crashes in mi_make_key / sort_key_read +--echo # -# -# NOTE: PLEASE DO NOT ADD NOT MYISAM SPECIFIC TESTCASES HERE ! -# TESTCASES WHICH MUST BE APPLIED TO ALL STORAGE ENGINES MUST BE ADDED IN -# THE SOURCED FILES ONLY. -# +CREATE TABLE t1 ( + pk BIGINT AUTO_INCREMENT, + col_date DATE NULL, + col_datetime DATETIME(1) NULL, + col_int TINYINT(13) UNSIGNED ZEROFILL NULL, + col_varchar VARBINARY(2222) NULL, + col_timestamp TIMESTAMP(2) NULL, + col_bit BIT(64) NOT NULL DEFAULT 0, + col_blob MEDIUMBLOB NULL, + col_dec DECIMAL(10,9) ZEROFILL NOT NULL DEFAULT 0, + col_time TIME(4) NULL, + col_year YEAR NOT NULL DEFAULT '1970', + col_char CHAR(129) NULL, + col_enum SET('','a','b','c','d','e','f','foo','bar') NULL, + vcol_dec DECIMAL(50,18) ZEROFILL AS (col_dec) VIRTUAL, + vcol_bit BIT(48) AS (col_bit) VIRTUAL, + vcol_char CHAR(224) AS (col_char) VIRTUAL, + vcol_datetime DATETIME(4) AS (col_datetime) VIRTUAL, + vcol_year YEAR AS (col_year) VIRTUAL, + vcol_varchar VARBINARY(356) AS (col_varchar) VIRTUAL, + vcol_blob MEDIUMBLOB AS (col_blob) VIRTUAL, + vcol_timestamp TIMESTAMP(5) AS (col_timestamp) VIRTUAL, + vcol_int BIGINT(46) AS (col_int) VIRTUAL, + vcol_time TIME(1) AS (col_time) VIRTUAL, + vcol_date DATE AS (col_date) VIRTUAL, + vcol_enum SET('','a','b','c','d','e','f','foo','bar') AS (col_enum) VIRTUAL, + UNIQUE(pk), + PRIMARY KEY(pk) + ) ENGINE=MyISAM; -#------------------------------------------------------------------------------# -# General not engine specific settings and requirements ---source suite/vcol/inc/vcol_init_vars.pre - -#------------------------------------------------------------------------------# -# Cleanup ---source suite/vcol/inc/vcol_cleanup.inc - -#------------------------------------------------------------------------------# -# Engine specific settings and requirements - -##### Storage engine to be tested -# Set the session storage engine -SET @@session.storage_engine = 'MyISAM'; - -##### Workarounds for known open engine specific bugs -# none - -#------------------------------------------------------------------------------# -# Execute the tests to be applied to all storage engines ---source suite/vcol/inc/vcol_keys.inc - -#------------------------------------------------------------------------------# -# Execute storage engine specific tests - -#------------------------------------------------------------------------------# -# Cleanup ---source suite/vcol/inc/vcol_cleanup.inc +--disable_query_log +INSERT INTO t1 (col_date,col_datetime,col_int,col_varchar,col_timestamp,col_bit,col_blob,col_dec,col_time,col_year,col_char,col_enum) VALUES + (NULL,'2011-04-17 15:46:11.056462',6,'rsprn','1980-01-01 00:00:00',b'0001011111000111001110000110100110010101101','spr',0.0,'00:00:00',1988,'p',''), + ('2007-05-18',NULL,5,'rnwg','2009-07-07 23:46:32.052699',b'01010','n',0.6,'04:35:56.018027',1995,'wgrpq',''), + ('1994-03-16','2006-03-15 22:48:25.013225',7,'grpquarw','2034-05-17 10:51:23.048265',b'0001011101001011000111101','rp',0.3,'15:13:22.043368',2004,'pq',''), + ('1980-01-01','1987-06-01 04:14:04.027480',1,'qu','1989-07-05 09:46:16.038513',b'001111011000100011100111010100101010000100010100101','uar',0.6,'11:56:35.031314',1986,'',''), + ('2014-08-16','2021-01-08 20:59:16.041252',0,'arw','2022-12-20 22:48:53.014627',b'110110101100001011001110110100','m',0.6,'17:26:26.039855',2008,'rw',''), + ('1981-12-02','1992-02-10 09:29:41.028674',6,'wk','2017-09-25 10:37:25.043516',b'010101001110111010101001101000101010',NULL,0.7,'00:00:00',2035,'kaz',''), + ('2022-11-11','2029-03-07 17:24:19.043489',122,'a','1980-01-01 00:00:00',b'0001100111011','z',0.0,'10:23:45.050733',2018,'a',''), + ('2004-03-12','1979-02-18 00:00:00',0,'zjeiwvd','1998-07-03 16:09:05.053954',b'0000110101111001001110100100111001111111100001110','',0.4,'07:43:46.015324',2028,'je',''), + ('2016-08-08','1986-03-10 00:00:00',3,'eiwv','2025-08-07 12:24:53.040869',b'010001101110100111111','iw',0.3,'02:48:45.058781',2020,'',''), + ('1979-02-25',NULL,2,'wvd','1980-01-01 00:00:00',b'010','vdm',0.1,'13:35:24.021296',1995,'dmd',''), + ('2012-04-19','2034-10-06 23:29:21.057367',9,'mdiv','2022-05-16 05:28:40.005808',b'110111111101000010011011001','divj',0.3,'11:24:50.017885',1997,'iv',''), + ('2009-10-13','1997-01-21 13:04:34.011524',1,'vjqs','1980-01-01 00:00:00',b'11110011100101011100001110110000101001100010000011110110011','j',0.7,'00:00:00',2008,'qsxmh',''), + ('2012-01-01','2011-06-23 06:11:33.014723',9,'r','2022-04-27 05:29:32.023395',b'1001011010101100100111','',0.5,'03:34:01.048002',1976,'sx',''), + ('2007-08-24','2012-01-24 22:16:53.014811',2,'fpp','2005-10-11 08:58:32.021273',b'011011111011',NULL,0.4,'18:11:17.036115',2026,'m',''), + (NULL,'1985-05-28 00:00:00',7,'hjw','2030-06-10 10:15:54.061818',b'0011110101001100011011000101010','',0.5,'02:03:21.020237',1994,'z',''), + ('2006-09-09','2002-11-10 06:16:27.008631',0,'jw','2030-07-16 00:00:00',b'11101110111101000010101110000010001110110001001101110100','wa',0.8,'00:00:00',1974,'',''), + ('1993-04-22','1980-01-01 00:00:00',3,'a','2020-02-06 08:11:00.051515',b'001110110010','gew',0.4,'11:59:05.013933',1998,NULL,''), + ('1985-11-05','2019-12-24 04:13:43.062741',7,'foo','1986-07-02 00:00:00',b'10100110001010100011111111101011011101001110010110101100110000','',0.5,'17:32:55.060182',1978,'w',''), + ('2007-02-20','2033-10-16 18:47:42.006517',1,'clc','1971-10-14 00:00:00',b'100001010','',0.1,'20:38:42.062598',2004,'lcfy',''), + ('1979-12-10','1972-08-04 00:00:00',8,'','2021-12-24 04:51:09.011443',b'011010010010010010011101000010110011110110110010100010','e',0.1,'23:08:10.014396',2026,'cfykywl',''), + ('2002-07-04',NULL,NULL,'fyky','1980-11-02 00:00:00',b'10000010111010000110','f',0.6,'13:07:14.014203',1979,'ykywl',''), + ('2019-02-15','2004-08-28 10:16:46.053753',8,'kywl','2004-12-01 00:00:00',b'010111010110001110110011000010110111011','ywlcne',0.2,'09:10:39.028897',2031,'wlcnemiuaab',''), + ('1989-05-15','1973-09-04 00:00:00',2,'lcne',NULL,b'100001100101110110000011110','',0.9,'19:22:16.015548',2013,'cnemiuaa',''), + ('2023-04-20','2018-12-04 04:19:46.040664',8,NULL,'1985-04-18 05:32:12.013509',b'111011011111100100000001','nem',0.1,'23:18:05.007794',2026,'emiua',''), + (NULL,'2024-08-10 03:52:31.047182',2,'miua','2035-09-03 06:07:22.008308',b'000111','',0.1,'03:58:02.003946',1988,'iua',''), + ('1977-09-01','1987-02-01 03:44:00.061840',5,'u','1997-11-27 04:02:13.014551',b'111110001001100101101000100010001011101000011',NULL,0.3,'00:00:00',1985,'aab',''), + (NULL,'1980-01-01 00:00:00',6,'a','1989-03-02 09:07:11.058643',b'10101001011110110010111010010100001010000110000110010',NULL,0.8,'17:41:15.057101',1975,'br',''), + ('1980-01-01','2019-02-10 20:56:51.063985',NULL,'rr','2000-02-28 01:38:27.004468',b'0101001011110001010001','rifnhu',0.5,'20:55:57.029281',1973,'if',''), + (NULL,'2019-04-15 02:13:03.019581',7,'fnhu','2000-03-25 18:48:46.063113',b'011000110','nhuu',0.0,'00:00:00',2030,'h',''), + ('1997-04-01',NULL,3,NULL,'1976-05-22 04:48:42.013754',b'101110101010000111101',NULL,0.1,'12:09:48.030076',2031,'u',''), + (NULL,'1993-10-10 15:11:03.021823',NULL,'ufzasunkrcpvasdqkxbwptigbpnesqigwegcnfeuvrgnecpthm','1986-06-12 04:29:01.017855',b'11110','fza',0.9,NULL,1994,'zasun',''), + ('1997-02-13','2001-04-08 02:01:53.018388',0,'as','1975-09-18 00:00:00',b'00111000101001001101001000100100010101110011010111000001011011','su',0.3,'15:15:31.011102',1972,'unk',''), + ('1975-07-26','2022-12-24 00:00:00',0,'foo','1986-01-22 21:27:38.024505',b'1111110000000001000010111','krc',0.9,'05:46:08.055789',1996,'rcp',''), + ('2000-08-04','1980-01-01 00:00:00',48,'foo','2015-12-21 17:04:06.008790',b'0100001110011001011101011101110110100010000101101100011010','g',0.7,'18:31:50.046211',2025,'pvasdq',''), + ('2001-03-26','2032-03-19 13:15:13.063368',NULL,'foo','2026-09-05 02:46:10.026919',b'11','a',0.3,'03:12:20.039599',2019,'sdqkx',''), + ('2035-01-14','1987-09-15 05:46:00.041527',4,'p','1980-01-01 00:00:00',b'1111100111','dqkxbwpt',0.0,'09:57:41.059145',1995,'q',''), + ('2035-07-13','2011-04-13 04:05:14.025091',212,'kxbw','1985-02-14 11:58:32.002055',b'1010100011110101011111111011010','x',0.2,'19:35:02.024655',1975,'bwptig',''), + ('2026-02-08','2015-05-04 09:31:22.017074',4,'wpt','2024-01-26 11:06:03.057899',b'011000010000100000011000011011000100101111001100000111011010','ptig',0.0,'00:00:00',1977,'tig',''), + ('1981-05-11',NULL,NULL,'foo','1981-12-09 10:10:34.008107',b'01000100100100110011111','gbp',0.0,'13:05:42.035253',2019,'bpn',''), + ('1977-05-16',NULL,9,'pne',NULL,b'001101100111001110110010111001110100','s',0.0,'15:09:37.063819',1998,'ne',''), + ('1980-01-01','2018-12-02 00:27:35.056455',2,'','1981-07-07 23:39:32.028644',b'0000101001010111010001101000','es',0.3,'15:43:30.016638',2013,NULL,''), + ('2027-09-05','1998-05-14 04:15:42.009728',1,'s','2015-07-16 00:00:00',b'01011101101010000110011010000111001000001000011','',0.6,'08:39:24.041879',2035,'qigweg',''), + ('2005-02-04',NULL,2,'i','1974-01-11 11:02:16.024653',b'01001101110001001101101010011001001101010010000','gw',0.6,'03:28:30.012172',1978,'weg',''), + (NULL,'1976-06-21 00:00:00',5,NULL,'2023-11-25 15:49:52.021725',b'101011010001100','e',0.1,'00:00:00',1977,'gcn',''), + ('1989-07-13',NULL,1,'c','1978-02-22 02:55:14.047104',b'01101010100001100110111011101000111011101101110011','f',0.8,NULL,1987,'nfeu',''), + ('2004-04-27','2019-06-28 08:04:35.039213',0,'f','1990-01-09 14:22:27.065127',b'00101001011','eu',0.0,'13:33:09.039791',2007,'uvrgne',''), + ('2008-09-08','1990-11-05 00:00:00',1,'w','2026-12-23 00:00:00',b'0001101','vrgnec',0.3,'19:13:14.037732',1983,'d',''), + ('2026-08-12','2026-11-23 11:18:35.012315',4,'rgnec','1988-09-06 07:11:55.057710',b'11010111001001101100100010110011100001000100001011000000000010','',0.9,NULL,1982,'gnecpth',''), + ('1992-12-03','2033-08-18 04:47:11.033829',65,'n','1989-11-21 17:42:13.012747',b'11011011110000000',NULL,0.9,'10:08:34.006377',1971,'ecpth',''), + ('1976-10-11','1975-05-18 00:00:00',3,'c','2017-11-06 03:33:38.002741',b'0111100010000111000111111100111100111000101100111111100','p',0.7,'03:28:07.039921',2014,'thmhf',''), + ('2014-04-19','2023-08-07 16:18:59.024013',0,'','2006-05-04 23:01:46.019351',b'0101101011011101101011101110000001001000110100101000011001110','h',0.5,'00:00:00',1995,'m',''), + ('1990-07-16','1980-01-01 00:00:00',8,'hffqbythjwpukqubzpomntrddrwhzjtqvb','1985-08-04 05:33:20.030471',b'001101111111100110101111000011100','ff',0.0,'00:00:00',2002,'fqbythj',''), + (NULL,'2019-01-12 00:00:00',0,NULL,'2009-01-25 00:00:00',b'100111111010000110010011100100000011101001010101111','qb',0.4,'20:35:33.059895',1981,'byt',''), + ('1991-10-07',NULL,2,'yt','2027-04-19 06:38:46.020191',b'001','t',0.4,'10:02:06.014126',2004,'h',''), + (NULL,'2009-07-05 00:00:00',241,'j','1981-06-26 12:35:20.061910',b'10101110001101001000011010010111000','wpukqu',0.5,'00:00:00',1973,'pukqu',''), + ('2001-05-26','2007-01-06 00:57:02.048605',0,'u',NULL,b'111100','k',0.7,'03:19:10.052988',2026,'q',NULL), + ('2008-03-15','1990-09-11 00:00:00',5,'ubz','1980-01-01 00:00:00',b'11010111011110001101111000000011000111101100111','b',0.5,'00:34:27.006616',2013,NULL,''), + ('1984-08-01','2000-09-20 09:35:47.025609',3,'zp','2016-11-22 19:38:52.053299',b'00000010','po',0.7,'19:47:19.014687',1996,'o',''), + ('1978-02-05','1978-05-08 04:30:57.023271',7,'foo','2000-04-06 08:42:13.019650',b'11000110111100101010001110111101111000001101','n',0.8,NULL,1980,'trdd',''), + ('2017-04-11','2002-09-26 12:59:43.051659',8,'rd','1972-03-27 13:09:07.017459',b'00011110001001001000000100110100101010','ddrwh',0.7,'00:00:00',2021,'drwhzj',''), + ('1980-01-01','1986-05-04 05:15:19.008418',0,'r','2005-10-04 09:21:09.020131',b'1101100010101001010011010001011101001111110010101111011','wh',0.0,'00:00:00',1975,'hzjtqv',''), + ('2035-12-12','1980-01-01 00:00:00',0,'x',NULL,b'0010000101010110111100000110000010001000100001000110111000010110','zjt',0.4,'15:51:12.040679',1984,'jtqvbji',''), + ('1993-05-12','2000-11-11 20:54:49.053753',0,'tqvb','2022-02-26 14:26:36.004981',b'110000101110000111011','qv',0.7,'00:00:00',1972,'v',''), + ('1971-08-22','2029-02-15 16:39:35.007278',2,NULL,'2033-09-22 08:28:19.057517',b'11111101011101110111100011011111001','bji',0.8,'08:34:37.000701',2000,'o',''), + (NULL,NULL,5,'foo','1982-02-24 00:00:00',b'00111111000111111111010111010111011101','iklce',0.8,'01:23:11.014485',2021,'klcek',''), + (NULL,NULL,8,'lce','1988-07-28 11:48:23.011427',b'101101000101010000000100000001011','',0.3,'17:15:34.034697',1991,'cekxqy',''), + ('2029-12-07','1993-12-24 00:45:29.060155',3,'ekx','1980-01-01 00:00:00',b'01001010110110000100100100111010110000000101001011111110001100','q',0.7,'10:39:47.004022',2006,'foo',''), + ('2015-10-20','1980-01-01 00:00:00',189,'xqy','2028-12-19 00:00:00',b'101001011011100101110010101000101110100110','qy',0.5,'15:16:59.059052',1993,'foo',''), + ('1998-08-07','2017-08-07 01:53:34.056737',5,'oxsolbx',NULL,b'1000111010110010110','xsolbxth',0.3,'22:56:09.003450',2014,'s',''), + ('2016-01-25','2000-09-14 22:35:41.048328',6,'foo','2004-10-11 00:00:00',b'001','olbxt',0.0,'14:15:54.033066',1983,'lbxt',''), + ('1979-09-02','2027-01-19 09:34:15.034597',4,'bxth','1989-10-23 09:11:09.055445',b'011011001110000011011011',NULL,0.8,'05:31:31.006489',1978,'xthdc',''), + ('1980-01-01',NULL,8,'th','2012-02-07 00:00:00',b'00101011001100111001101011010110','hdc',0.0,'22:09:17.054381',2013,'dcprs',''), + (NULL,'2018-08-03 17:37:14.049040',2,'cprswpj','1990-07-28 07:56:50.026324',b'0000010111011110100100010010011011010010001111011010000010011101','',0.1,NULL,1971,'prswpjx',''), + ('1984-05-07','2012-05-07 00:00:00',1,'rswp','2030-05-09 07:42:25.003848',b'1001','swp',0.4,'13:27:32.040813',1997,'wpj',''), + (NULL,'2030-03-22 14:03:46.000742',7,'pjxixm','2022-05-11 00:00:00',b'00111110011001010010001111010001111110010010000111','j',0.8,'00:00:00',1996,'x',NULL), + ('2000-12-03','2020-08-13 16:03:09.041436',8,'ix','1985-05-19 11:28:09.002728',b'11011010000101000110111111010111','xmvfwm',0.9,'19:06:00.002417',1976,'m',''), + ('1990-03-13','2035-09-08 21:29:04.011731',5,'vfwmsys','2029-11-03 04:28:54.058532',b'0110001011001010100','fw',0.6,'20:30:32.032224',1994,'wmsys',''), + ('2035-06-04','2027-06-07 11:27:21.038934',8,'ms','1987-09-02 00:00:00',b'001101101101111110010110110011','syse',0.1,'01:10:53.060943',2027,'yse',''), + (NULL,'1993-06-06 07:29:56.029103',NULL,'','1971-06-08 23:51:55.054403',b'11001110001111111001001010101110111011000100111010','se',0.2,'10:24:53.013058',1995,'eb',''), + ('2018-06-12','2020-08-06 23:47:35.060301',5,NULL,NULL,b'110011110111010111','blwc',0.6,NULL,1971,'lwc',''), + ('2005-02-03','2016-10-11 00:00:00',0,'w','2005-03-25 00:00:00',b'0101001001001','',0.2,'21:56:26.025743',1971,'c',''), + ('2025-10-10',NULL,1,'vumvyv','2034-05-06 18:17:26.004829',b'10110101101100100001000011001111100100111101100','um',0.3,'19:42:29.005509',1992,'m',''), + ('2014-01-27','1980-01-01 00:00:00',2,'vyvb','1975-04-08 10:13:06.052060',b'111011110111111010011111011011101111','yv',0.4,'15:13:32.059509',2011,NULL,''), + ('2016-08-04','2008-12-03 01:55:41.030042',6,'vb','1993-09-08 00:01:40.016566',b'000101110101100111001101010110','b',0.5,'08:39:05.055786',1993,'it',''), + ('1980-01-01','1980-01-01 00:00:00',9,'tx','1991-07-19 05:37:43.056696',b'110110111010111101010001100010111100110011111010100100100','k',0.9,'00:00:00',1999,'h',''), + (NULL,'2007-06-14 15:47:29.017306',9,'foo',NULL,b'0100111000001011111000111010000011011000011000101010','qjxdzd',0.3,'13:52:31.035851',2001,'jxdzd',''), + (NULL,'2022-04-28 18:27:19.060240',4,'foo','2018-02-28 02:49:16.013066',b'10000100000000110011011110101110100001100011101110011011100','d',0.0,'15:01:48.022368',1987,'zdytun',''), + ('1987-10-10','1975-06-02 02:47:57.012240',9,'dy','1980-06-10 00:00:00',b'110000111','',0.7,'08:13:44.003967',1981,'',''), + ('2015-09-28',NULL,4,'d','2005-08-09 08:35:04.039832',b'00','b',0.1,'00:47:43.048164',1973,'yt',''), + ('2030-01-18','2011-12-09 00:00:00',6,NULL,'1982-05-13 00:00:00',b'111110100001000010001110110010111100001011010','v',0.2,'00:39:24.001557',2027,'tun',''), + ('1980-06-28','2016-04-07 00:00:00',8,'y','1980-01-01 00:00:00',b'01011100100001010110101110111110110','unq',0.7,'00:00:00',2016,'foo',''), + ('2018-09-16','1975-01-03 00:00:00',NULL,'qv','2028-05-10 00:00:00',b'0001100101001011100110','vv',0.0,'23:54:42.064230',2000,'vr',''), + ('2033-12-11','2021-07-23 12:20:17.025201',3,'rm','1996-07-16 00:00:00',b'1011001110','mpyx',0.7,'04:04:01.055956',2009,'pyx',''), + ('1982-12-18','1996-09-16 00:00:00',9,'yx','2003-10-14 03:54:44.012072',b'11001011011000001111011000101111101110100101','x',0.9,NULL,1981,'rencqh',''), + ('1980-01-01','2009-01-17 12:11:34.030449',7,'encqh','1980-01-01 00:00:00',b'1101001101001000101010001100100100','ncq',0.4,'23:44:22.012217',2030,'b',''), + ('2015-05-03','1987-03-19 17:37:53.053429',6,'','2012-08-03 00:00:00',b'0','cq',0.0,'17:16:43.030750',2035,'qh',NULL), + (NULL,'1980-01-01 00:00:00',1,'huyr','2012-02-11 14:15:13.004778',b'110011001100010100001101011001011110010000011001110101','',0.7,'09:33:00.034425',2024,'uyr',''), + ('2019-06-05','2020-08-05 23:53:07.028129',1,'yr',NULL,b'1001011110101010001111101000011001011111100','rflu',0.3,NULL,2016,'fluezqe',''), + ('1980-01-10','2025-05-12 08:22:39.039097',1,'lu','1975-07-24 00:00:00',b'10100111001111101001110000110011','',0.1,'23:58:28.031575',2005,NULL,''), + ('2008-03-17','1982-05-27 11:44:53.038339',NULL,'uezqe','2024-10-12 02:16:04.063095',b'1001010110101101000101011011000011','e',0.9,'19:37:29.063243',1987,'zqekmq','') +; +--enable_query_log +--disable_warnings +ALTER TABLE t1 ADD INDEX(col_enum,vcol_int); +ALTER TABLE t1 ADD INDEX(col_year); +--enable_warnings +DROP TABLE t1; diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 8de200f5e72..8711b9ff9aa 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -2781,7 +2781,7 @@ int mi_repair_parallel(HA_CHECK *param, register MI_INFO *info, del=info->state->del; param->glob_crc=0; /* for compressed tables */ - max_pack_reclength= share->base.pack_reclength; + max_pack_reclength= MY_MAX(share->base.pack_reclength, share->vreclength); if (share->options & HA_OPTION_COMPRESS_RECORD) set_if_bigger(max_pack_reclength, share->max_pack_length); if (!(sort_param=(MI_SORT_PARAM *) diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index 01a13a6225c..604dd1674ae 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -740,6 +740,7 @@ uchar *mi_alloc_rec_buff(MI_INFO *info, ulong length, uchar **buf) else length= info->s->base.pack_reclength; length= MY_MAX(length, info->s->base.max_key_length); + length= MY_MAX(length, info->s->vreclength); /* Avoid unnecessary realloc */ if (newptr && length == old_length) return newptr; From 5f0c31f928338e8a6ffde098b7ffd3d1a8b02903 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 10 Jan 2017 18:28:24 +0200 Subject: [PATCH 063/167] MDEV-11597 Assertion when doing select from virtual column with impossible value - Changed error handlers interface so that they can change error level in the handler - Give warnings and errors when calculating virtual columns - On insert/update error is fatal in strict mode. - SELECT and DELETE will only give a warning if a virtual field generates an error - Added VCOL_UPDATE_FOR_DELETE and VCOL_UPDATE_INDEX_FOR_REPLACE to be able to easily detect in update_virtual_fields() if we should use an error handler to mask errors or not. --- mysql-test/suite/vcol/inc/vcol_ins_upd.inc | 65 +++++ .../suite/vcol/r/vcol_ins_upd_innodb.result | 220 ++++++++++++++++ .../suite/vcol/r/vcol_ins_upd_myisam.result | 237 ++++++++++++++++++ sql/handler.cc | 4 +- sql/item_func.cc | 4 +- sql/log.cc | 4 +- sql/sp.cc | 13 +- sql/sql_acl.cc | 6 +- sql/sql_base.cc | 16 +- sql/sql_base.h | 2 +- sql/sql_class.cc | 22 +- sql/sql_class.h | 11 +- sql/sql_delete.cc | 5 +- sql/sql_insert.cc | 11 +- sql/sql_show.cc | 6 +- sql/sql_trigger.cc | 2 +- sql/sql_update.cc | 3 +- sql/table.cc | 49 +++- sql/table.h | 2 + storage/federated/ha_federated.cc | 2 +- storage/federatedx/ha_federatedx.cc | 2 +- 21 files changed, 628 insertions(+), 58 deletions(-) diff --git a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc index d9a1e062870..a7a43aae529 100644 --- a/mysql-test/suite/vcol/inc/vcol_ins_upd.inc +++ b/mysql-test/suite/vcol/inc/vcol_ins_upd.inc @@ -314,3 +314,68 @@ select * from t1; drop table t1,t2; +--echo # +--echo # Test error handling with virtual columns +--echo # + +CREATE TABLE IF NOT EXISTS t1 ( + f1 DOUBLE, + f2 DOUBLE NOT NULL DEFAULT '0', + f3 DOUBLE, + f4 DOUBLE NOT NULL DEFAULT '0', + v1 DOUBLE AS ( ( f1 DIV ( f1 ) ) <= f2 ) VIRTUAL, + v2 DOUBLE AS ( ( f2 DIV ( f2 ) ) <= f2 ) VIRTUAL, + KEY (v2) +); + +set sql_mode='strict_all_tables,error_for_division_by_zero'; +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +INSERT IGNORE INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; + +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); + +--error ER_DIVISION_BY_ZERO +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +select count(*) from t1; +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +select count(*) from t1; +select * from t1; +--error ER_BAD_NULL_ERROR +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1 where f2 !=0; +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +SELECT * FROM t1; +TRUNCATE TABLE t1; + +set sql_mode='error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; + +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); + +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +select count(*) from t1; +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +select count(*) from t1; +select * from t1; +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +drop table t1; +set sql_mode=@@global.sql_mode; diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result index d6793e22668..e3853156b4d 100644 --- a/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_ins_upd_innodb.result @@ -451,3 +451,223 @@ id name name_hash 2050 name1 9b46b0dd3a8083c070c3b9953bb5f3f95c5ab4da 2051 name2+1 fd4f236320db3956a5ec073c5ec39707d7f05708 drop table t1,t2; +# +# Test error handling with virtual columns +# +CREATE TABLE IF NOT EXISTS t1 ( +f1 DOUBLE, +f2 DOUBLE NOT NULL DEFAULT '0', +f3 DOUBLE, +f4 DOUBLE NOT NULL DEFAULT '0', +v1 DOUBLE AS ( ( f1 DIV ( f1 ) ) <= f2 ) VIRTUAL, +v2 DOUBLE AS ( ( f2 DIV ( f2 ) ) <= f2 ) VIRTUAL, +KEY (v2) +); +set sql_mode='strict_all_tables,error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +ERROR 22012: Division by 0 +INSERT IGNORE INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +ERROR 22012: Division by 0 +select count(*) from t1; +count(*) +6 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +3 +select * from t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +6 6 0 0 1 1 +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +ERROR 23000: Column 'f2' cannot be null +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1 where f2 !=0; +Warnings: +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +SELECT * FROM t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +6 6 0 0 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +Warnings: +Warning 1365 Division by 0 +TRUNCATE TABLE t1; +set sql_mode='error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +NULL +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +22 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +15 +select * from t1; +f1 f2 f3 f4 v1 v2 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 0 1 1 0 NULL +0 0 0 0 NULL NULL +5 5 5 5 1 1 +1 0 0 0 0 NULL +6 6 0 0 1 1 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +0 0 0 0 NULL NULL +5 5 5 5 1 1 +0 0 0 0 NULL NULL +0 0 0 0 NULL NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +drop table t1; +set sql_mode=@@global.sql_mode; diff --git a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result index 97f6b9be563..dcf957becae 100644 --- a/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result +++ b/mysql-test/suite/vcol/r/vcol_ins_upd_myisam.result @@ -389,3 +389,240 @@ id name name_hash 2051 name2+1 fd4f236320db3956a5ec073c5ec39707d7f05708 2041 name3+1 93c9096df48221428de46e146abc9f4f94bf7d2e drop table t1,t2; +# +# Test error handling with virtual columns +# +CREATE TABLE IF NOT EXISTS t1 ( +f1 DOUBLE, +f2 DOUBLE NOT NULL DEFAULT '0', +f3 DOUBLE, +f4 DOUBLE NOT NULL DEFAULT '0', +v1 DOUBLE AS ( ( f1 DIV ( f1 ) ) <= f2 ) VIRTUAL, +v2 DOUBLE AS ( ( f2 DIV ( f2 ) ) <= f2 ) VIRTUAL, +KEY (v2) +); +set sql_mode='strict_all_tables,error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +ERROR 22012: Division by 0 +INSERT IGNORE INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +ERROR 22012: Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +ERROR 22012: Division by 0 +select count(*) from t1; +count(*) +13 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +8 +select * from t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +5 5 5 5 1 1 +6 6 0 0 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +5 5 5 5 1 1 +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +ERROR 23000: Column 'f2' cannot be null +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1 where f2 !=0; +Warnings: +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +SELECT * FROM t1; +f1 f2 f3 f4 v1 v2 +1 1 1 1 1 1 +1 0 1 1 0 NULL +1 1 10 10 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +5 5 5 5 1 1 +6 6 0 0 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +5 5 5 5 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +1 1 10 10 1 1 +Warnings: +Warning 1365 Division by 0 +TRUNCATE TABLE t1; +set sql_mode='error_for_division_by_zero'; +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 0, 0, 0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 1, 1, 1); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (1, 0, 1, 1); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0, 1, 1, 1); +select v1 from t1; +v1 +NULL +1 +0 +NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (0,0,0,0), (2,2,2,2); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (3,3,3,3), (4,4,4,4); +INSERT INTO t1 (f1, f2, f3, f4) VALUES (5,5,5,5), (1,0,0,0); +Warnings: +Warning 1365 Division by 0 +INSERT INTO t1 (f1, f2, f3, f4) VALUES (6,6,0,0); +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT f3, f4, f3, f4 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +22 +DELETE FROM t1 WHERE v2 != f1 and f1 < 5; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +select count(*) from t1; +count(*) +15 +select * from t1; +f1 f2 f3 f4 v1 v2 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 0 1 1 0 NULL +0 0 0 0 NULL NULL +5 5 5 5 1 1 +1 0 0 0 0 NULL +6 6 0 0 1 1 +0 0 0 0 NULL NULL +1 1 1 1 1 1 +1 1 1 1 1 1 +1 1 1 1 1 1 +0 0 0 0 NULL NULL +5 5 5 5 1 1 +0 0 0 0 NULL NULL +0 0 0 0 NULL NULL +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +INSERT INTO t1 ( f1, f2, f3, f4 ) SELECT v1, v2, 10,10 FROM t1; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +Warning 1048 Column 'f2' cannot be null +Warning 1365 Division by 0 +UPDATE t1 SET f3 = v1 WHERE f2 = 2 AND v2 is null; +Warnings: +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +Warning 1365 Division by 0 +drop table t1; +set sql_mode=@@global.sql_mode; diff --git a/sql/handler.cc b/sql/handler.cc index a91a97598d6..f06c5d71a5e 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4974,7 +4974,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -4987,7 +4987,7 @@ public: return TRUE; } - if (level == Sql_condition::WARN_LEVEL_ERROR) + if (*level == Sql_condition::WARN_LEVEL_ERROR) m_unhandled_errors++; return FALSE; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 754ba9d261c..f6162b54806 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4127,7 +4127,7 @@ public: bool handle_condition(THD * /* thd */, uint sql_errno, const char * /* sqlstate */, - Sql_condition::enum_warning_level /* level */, + Sql_condition::enum_warning_level* /* level */, const char *message, Sql_condition ** /* cond_hdl */); }; @@ -4136,7 +4136,7 @@ bool Lock_wait_timeout_handler:: handle_condition(THD *thd, uint sql_errno, const char * /* sqlstate */, - Sql_condition::enum_warning_level /* level */, + Sql_condition::enum_warning_level* /* level */, const char *message, Sql_condition ** /* cond_hdl */) { diff --git a/sql/log.cc b/sql/log.cc index 57984bd03f4..23326532388 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -195,7 +195,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sql_state, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); const char *message() const { return m_message; } @@ -205,7 +205,7 @@ bool Silence_log_table_errors::handle_condition(THD *, uint, const char*, - Sql_condition::enum_warning_level, + Sql_condition::enum_warning_level*, const char* msg, Sql_condition ** cond_hdl) { diff --git a/sql/sp.cc b/sql/sp.cc index 05f075390c1..a1662cefb9e 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -691,7 +691,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); }; @@ -701,13 +701,13 @@ Silence_deprecated_warning::handle_condition( THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char*, Sql_condition ** cond_hdl) { *cond_hdl= NULL; if (sql_errno == ER_WARN_DEPRECATED_SYNTAX && - level == Sql_condition::WARN_LEVEL_WARN) + *level == Sql_condition::WARN_LEVEL_WARN) return TRUE; return FALSE; @@ -780,7 +780,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* message, Sql_condition ** cond_hdl); @@ -794,7 +794,8 @@ bool Bad_db_error_handler::handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level + *level, const char* message, Sql_condition ** cond_hdl) { @@ -1477,7 +1478,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index d2840a81e7e..4a3c9ae75e7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -10155,7 +10155,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -10170,12 +10170,12 @@ Silence_routine_definer_errors::handle_condition( THD *thd, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { *cond_hdl= NULL; - if (level == Sql_condition::WARN_LEVEL_ERROR) + if (*level == Sql_condition::WARN_LEVEL_ERROR) { switch (sql_errno) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 46d7d07dbdf..ac4b8a45107 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -68,7 +68,7 @@ bool No_such_table_error_handler::handle_condition(THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char*, Sql_condition ** cond_hdl) { @@ -79,7 +79,7 @@ No_such_table_error_handler::handle_condition(THD *, return TRUE; } - if (level == Sql_condition::WARN_LEVEL_ERROR) + if (*level == Sql_condition::WARN_LEVEL_ERROR) m_unhandled_errors++; return FALSE; } @@ -112,7 +112,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -142,7 +142,7 @@ bool Repair_mrg_table_error_handler::handle_condition(THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char*, Sql_condition ** cond_hdl) { @@ -1254,7 +1254,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -1273,7 +1273,7 @@ private: bool MDL_deadlock_handler::handle_condition(THD *, uint sql_errno, const char*, - Sql_condition::enum_warning_level, + Sql_condition::enum_warning_level*, const char*, Sql_condition ** cond_hdl) { @@ -2834,7 +2834,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -7900,7 +7900,6 @@ fill_record(THD *thd, TABLE *table_arg, List &fields, List &values, table_arg->update_default_fields(0, ignore_errors)) goto err; /* Update virtual fields */ - thd->abort_on_warning= FALSE; if (table_arg->vfield && table_arg->update_virtual_fields(VCOL_UPDATE_FOR_WRITE)) goto err; @@ -7908,6 +7907,7 @@ fill_record(THD *thd, TABLE *table_arg, List &fields, List &values, thd->no_errors= save_no_errors; DBUG_RETURN(thd->is_error()); err: + DBUG_PRINT("error",("got error")); thd->abort_on_warning= save_abort_on_warning; thd->no_errors= save_no_errors; if (fields.elements) diff --git a/sql/sql_base.h b/sql/sql_base.h index 8f363a73863..374ac56c3d8 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -624,7 +624,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 1837f2878c7..5c7cfdce657 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -640,7 +640,7 @@ char *thd_security_context(THD *thd, bool Drop_table_error_handler::handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -660,7 +660,7 @@ MDL_deadlock_and_lock_abort_error_handler:: handle_condition(THD *thd, uint sql_errno, const char *sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition **cond_hdl) { @@ -945,7 +945,7 @@ void THD::push_internal_handler(Internal_error_handler *handler) bool THD::handle_condition(uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -1072,6 +1072,7 @@ Sql_condition* THD::raise_condition(uint sql_errno, Diagnostics_area *da= get_stmt_da(); Sql_condition *cond= NULL; DBUG_ENTER("THD::raise_condition"); + DBUG_ASSERT(level < Sql_condition::WARN_LEVEL_END); if (!(variables.option_bits & OPTION_SQL_NOTES) && (level == Sql_condition::WARN_LEVEL_NOTE)) @@ -1099,24 +1100,23 @@ Sql_condition* THD::raise_condition(uint sql_errno, push_warning and strict SQL_MODE case. */ level= Sql_condition::WARN_LEVEL_ERROR; - killed= KILL_BAD_DATA; } - switch (level) - { + if (handle_condition(sql_errno, sqlstate, &level, msg, &cond)) + DBUG_RETURN(cond); + + switch (level) { case Sql_condition::WARN_LEVEL_NOTE: case Sql_condition::WARN_LEVEL_WARN: got_warning= 1; break; case Sql_condition::WARN_LEVEL_ERROR: break; - default: - DBUG_ASSERT(FALSE); + case Sql_condition::WARN_LEVEL_END: + /* Impossible */ + break; } - if (handle_condition(sql_errno, sqlstate, level, msg, &cond)) - DBUG_RETURN(cond); - if (level == Sql_condition::WARN_LEVEL_ERROR) { mysql_audit_general(this, MYSQL_AUDIT_GENERAL_ERROR, sql_errno, msg); diff --git a/sql/sql_class.h b/sql/sql_class.h index a55e1739318..3a7454e0a89 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1558,6 +1558,7 @@ show_system_thread(enum_thread_type thread) Internal error handlers are exception handlers used by the server implementation. */ + class Internal_error_handler { protected: @@ -1595,7 +1596,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) = 0; @@ -1616,7 +1617,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -1643,7 +1644,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); @@ -1664,7 +1665,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char *sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition **cond_hdl); @@ -3818,7 +3819,7 @@ private: */ bool handle_condition(uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e9a3be30060..2f4c2d9a6f8 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -560,10 +560,9 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ! thd->is_error()) { explain->tracker.on_record_read(); - if (table->vfield) - table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); thd->inc_examined_row_count(1); - // thd->is_error() is tested to disallow delete row on error + if (table->vfield) + (void) table->update_virtual_fields(VCOL_UPDATE_FOR_DELETE); if (!select || select->skip_record(thd) > 0) { explain->tracker.on_record_after_where(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index cea42667c48..b9c1dcebee9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3174,6 +3174,7 @@ bool Delayed_insert::handle_inserts(void) while ((row=rows.get())) { + int tmp_error; stacked_inserts--; mysql_mutex_unlock(&mutex); memcpy(table->record[0],row->record,table->s->reclength); @@ -3250,16 +3251,18 @@ bool Delayed_insert::handle_inserts(void) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); thd.clear_error(); // reset error for binlog + tmp_error= 0; if (table->vfield) { /* - Virtual fields where not calculated by caller as the temporary TABLE object used - had vcol_set empty. Better to calculate them here to make the caller faster. + Virtual fields where not calculated by caller as the temporary + TABLE object used had vcol_set empty. Better to calculate them + here to make the caller faster. */ - table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); + tmp_error= table->update_virtual_fields(VCOL_UPDATE_FOR_WRITE); } - if (write_record(&thd, table, &info)) + if (tmp_error || write_record(&thd, table, &info)) { info.error_count++; // Ignore errors thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 0a2dab91c14..58fc2edc6f2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1069,7 +1069,7 @@ public: } bool handle_condition(THD *thd, uint sql_errno, const char * /* sqlstate */, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char *message, Sql_condition ** /* cond_hdl */) { /* @@ -4675,7 +4675,7 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { @@ -4684,7 +4684,7 @@ public: sql_errno == ER_TRG_NO_CREATION_CTX) return true; - if (level != Sql_condition::WARN_LEVEL_ERROR) + if (*level != Sql_condition::WARN_LEVEL_ERROR) return false; if (!thd->get_stmt_da()->is_error()) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 2d1619018b2..bd02289b135 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -308,7 +308,7 @@ public: virtual bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* message, Sql_condition ** cond_hdl) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 476d1a4e104..c46b80f798b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2403,7 +2403,8 @@ int multi_update::do_updates() field_num++; } while ((tbl= check_opt_it++)); - if (table->vfield && table->update_virtual_fields(VCOL_UPDATE_INDEXED)) + if (table->vfield && + table->update_virtual_fields(VCOL_UPDATE_INDEXED_FOR_UPDATE)) goto err2; table->status|= STATUS_UPDATED; diff --git a/sql/table.cc b/sql/table.cc index 41f764d1e59..4242b870d55 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4932,7 +4932,7 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type) void TABLE_LIST::hide_view_error(THD *thd) { - if (thd->killed || thd->get_internal_handler()) + if ((thd->killed && !thd->is_error())|| thd->get_internal_handler()) return; /* Hide "Unknown column" or "Unknown function" error */ DBUG_ASSERT(thd->is_error()); @@ -7308,6 +7308,24 @@ bool is_simple_order(ORDER *order) return TRUE; } +class Turn_errors_to_warnings_handler : public Internal_error_handler +{ +public: + Turn_errors_to_warnings_handler() {} + bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + Sql_condition::enum_warning_level *level, + const char* msg, + Sql_condition ** cond_hdl) + { + *cond_hdl= NULL; + if (*level == Sql_condition::WARN_LEVEL_ERROR) + *level= Sql_condition::WARN_LEVEL_WARN; + return(0); + } +}; + /* @brief Compute values for virtual columns used in query @@ -7328,9 +7346,22 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) DBUG_ENTER("TABLE::update_virtual_fields"); DBUG_PRINT("enter", ("update_mode: %d", update_mode)); Field **vfield_ptr, *vf; + Turn_errors_to_warnings_handler Suppress_errors; + int error; + bool handler_pushed= 0; DBUG_ASSERT(vfield); + error= 0; in_use->reset_arena_for_cached_items(expr_arena); + + /* When reading or deleting row, ignore errors from virtual columns */ + if (update_mode == VCOL_UPDATE_FOR_READ || + update_mode == VCOL_UPDATE_FOR_DELETE || + update_mode == VCOL_UPDATE_INDEXED) + { + in_use->push_internal_handler(&Suppress_errors); + handler_pushed= 1; + } /* Iterate over virtual fields in the table */ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++) { @@ -7347,6 +7378,8 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) && bitmap_is_set(vcol_set, vf->field_index); swap_values= 1; break; + case VCOL_UPDATE_FOR_DELETE: + /* Fall trough */ case VCOL_UPDATE_FOR_WRITE: update= bitmap_is_set(vcol_set, vf->field_index); break; @@ -7367,6 +7400,7 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) } break; case VCOL_UPDATE_INDEXED: + case VCOL_UPDATE_INDEXED_FOR_UPDATE: /* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */ update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) && bitmap_is_set(vcol_set, vf->field_index) && @@ -7377,9 +7411,12 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) if (update) { + int field_error __attribute__((unused)) = 0; /* Compute the actual value of the virtual fields */ - vcol_info->expr->save_in_field(vf, 0); - DBUG_PRINT("info", ("field '%s' - updated", vf->field_name)); + if (vcol_info->expr->save_in_field(vf, 0)) + field_error= error= 1; + DBUG_PRINT("info", ("field '%s' - updated error: %d", + vf->field_name, field_error)); if (swap_values && (vf->flags & BLOB_FLAG)) { /* @@ -7396,8 +7433,12 @@ int TABLE::update_virtual_fields(enum_vcol_update_mode update_mode) DBUG_PRINT("info", ("field '%s' - skipped", vf->field_name)); } } + if (handler_pushed) + in_use->pop_internal_handler(); in_use->reset_arena_for_cached_items(0); - DBUG_RETURN(0); + + /* Return 1 only of we got a fatal error, not a warning */ + DBUG_RETURN(in_use->is_error()); } int TABLE::update_virtual_field(Field *vf) diff --git a/sql/table.h b/sql/table.h index facba06a3cc..3b8086dd09f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -328,7 +328,9 @@ enum enum_vcol_update_mode { VCOL_UPDATE_FOR_READ= 0, VCOL_UPDATE_FOR_WRITE, + VCOL_UPDATE_FOR_DELETE, VCOL_UPDATE_INDEXED, + VCOL_UPDATE_INDEXED_FOR_UPDATE, VCOL_UPDATE_FOR_REPLACE }; diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 038415cc188..879a17782aa 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -1653,7 +1653,7 @@ public: public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { return sql_errno >= ER_ABORTING_CONNECTION && diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index a4da84ddaf3..e3506e1a4df 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1786,7 +1786,7 @@ public: public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { return sql_errno >= ER_ABORTING_CONNECTION && From 833fda8f1a0c415ced1f2b8c1851809383bcc639 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 11 Jan 2017 14:13:30 +0200 Subject: [PATCH 064/167] InnoDB: Enable UNIV_DEBUG_VALGRIND for cmake -DWITH_VALGRIND The symbol HAVE_VALGRIND_MEMCHECK_H was never defined. Instead, the symbol HAVE_VALGRIND should have been used. --- storage/innobase/include/univ.i | 3 ++- storage/xtradb/include/univ.i | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index e6ddf45faba..7b867edfb22 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -171,7 +172,7 @@ command. Not tested on Windows. */ #define UNIV_COMPILE_TEST_FUNCS */ -#if defined(HAVE_valgrind)&& defined(HAVE_VALGRIND_MEMCHECK_H) +#if defined HAVE_valgrind && defined HAVE_VALGRIND # define UNIV_DEBUG_VALGRIND #endif /* HAVE_VALGRIND */ #if 0 diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 397843d309c..3444cbb1e7f 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -183,7 +184,7 @@ command. Not tested on Windows. */ #define UNIV_COMPILE_TEST_FUNCS */ -#if defined(HAVE_valgrind)&& defined(HAVE_VALGRIND_MEMCHECK_H) +#if defined HAVE_valgrind && defined HAVE_VALGRIND # define UNIV_DEBUG_VALGRIND #endif #if 0 From 4507f1e5d4fbfc2a638417683fc71d1768729cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 11 Jan 2017 14:26:30 +0200 Subject: [PATCH 065/167] Remove an excessive copyright message. --- storage/innobase/include/univ.i | 1 - storage/xtradb/include/univ.i | 1 - 2 files changed, 2 deletions(-) diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 1a5004549b9..53be1cf1ffe 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -3,7 +3,6 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2017, MariaDB Corporation. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index e3c79e9b826..ad0565a0290 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -3,7 +3,6 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2013, 2017, MariaDB Corporation. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2015, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described From 2dc5d8bb7e087a340edb989c045070b808e0da57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 12 Jan 2017 12:33:46 +0200 Subject: [PATCH 066/167] Improve an MDEV-9011 test of innodb_encrypt_log. Test crash recovery from an encrypted redo log with innodb_encrypt_log=0. Previously, we did a clean shutdown, so only the log checkpoint information would have been read from the redo log. With this change, we will be reading and applying encrypted redo log records. include/start_mysqld.inc: Observe $restart_parameters. encryption.innodb-log-encrypt: Remove some unnecessary statements, and instead of restarting the server and concurrently accessing the files while the server is running, kill the server, check the files, and finally start up the server. innodb.log_data_file_size: Use start_mysqld.inc with $restart_parameters. --- mysql-test/include/start_mysqld.inc | 9 ++++++- .../encryption/r/innodb-log-encrypt.result | 4 +-- .../encryption/t/innodb-log-encrypt.test | 25 +++---------------- .../suite/innodb/t/log_data_file_size.test | 11 +++----- 4 files changed, 18 insertions(+), 31 deletions(-) diff --git a/mysql-test/include/start_mysqld.inc b/mysql-test/include/start_mysqld.inc index 983c566821e..e31f26aad8c 100644 --- a/mysql-test/include/start_mysqld.inc +++ b/mysql-test/include/start_mysqld.inc @@ -1,7 +1,14 @@ # Include this script only after using shutdown_mysqld.inc # where $_expect_file_name was initialized. # Write file to make mysql-test-run.pl start up the server again ---exec echo "restart" > $_expect_file_name +if ($restart_parameters) +{ + --exec echo "restart: $restart_parameters" > $_expect_file_name +} +if (!$restart_parameters) +{ + --exec echo "restart" > $_expect_file_name +} # Turn on reconnect --enable_reconnect diff --git a/mysql-test/suite/encryption/r/innodb-log-encrypt.result b/mysql-test/suite/encryption/r/innodb-log-encrypt.result index 655e3023f7a..98fc277e513 100644 --- a/mysql-test/suite/encryption/r/innodb-log-encrypt.result +++ b/mysql-test/suite/encryption/r/innodb-log-encrypt.result @@ -13,14 +13,14 @@ set current_num = current_num + 1; end while; end// commit; -set autocommit=0; +begin; call innodb_insert_proc(2000); commit; -set autocommit=1; update t1 set c1 = c1 +1; select count(*) from t1; count(*) 2000 +# Kill the server # ibdata1 yes on expecting NOT FOUND NOT FOUND /privatejanprivate/ in ibdata1 # t1 yes on expecting NOT FOUND diff --git a/mysql-test/suite/encryption/t/innodb-log-encrypt.test b/mysql-test/suite/encryption/t/innodb-log-encrypt.test index 7c2e6f847b1..0555f9d49aa 100644 --- a/mysql-test/suite/encryption/t/innodb-log-encrypt.test +++ b/mysql-test/suite/encryption/t/innodb-log-encrypt.test @@ -6,16 +6,6 @@ # MDEV-9011: Redo log encryption does not work # ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - SET GLOBAL innodb_file_format = `Barracuda`; SET GLOBAL innodb_file_per_table = ON; @@ -35,16 +25,13 @@ end// delimiter ;// commit; -set autocommit=0; +begin; call innodb_insert_proc(2000); commit; -set autocommit=1; update t1 set c1 = c1 +1; select count(*) from t1; --- source include/restart_mysqld.inc - --let $MYSQLD_DATADIR=`select @@datadir` --let ib1_IBD = $MYSQLD_DATADIR/ibdata1 --let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd @@ -53,6 +40,8 @@ select count(*) from t1; --let SEARCH_RANGE = 10000000 --let SEARCH_PATTERN=privatejanprivate +-- source include/kill_mysqld.inc + --echo # ibdata1 yes on expecting NOT FOUND -- let SEARCH_FILE=$ib1_IBD -- source include/search_pattern_in_file.inc @@ -68,7 +57,7 @@ select count(*) from t1; --echo # Restart mysqld --innodb_encrypt_log=0 -- let $restart_parameters=--innodb_encrypt_log=0 --- source include/restart_mysqld.inc +-- source include/start_mysqld.inc insert into t1 values(5000, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); insert into t1 values(5001, substring(MD5(RAND()), -64), REPEAT('publicmessage',10)); @@ -106,9 +95,3 @@ insert into t1 values(5004, substring(MD5(RAND()), -64), REPEAT('publicmessage', drop procedure innodb_insert_proc; drop table t1; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/log_data_file_size.test b/mysql-test/suite/innodb/t/log_data_file_size.test index 23f1ede483f..9328f3bbe6d 100644 --- a/mysql-test/suite/innodb/t/log_data_file_size.test +++ b/mysql-test/suite/innodb/t/log_data_file_size.test @@ -23,7 +23,7 @@ perl; use Fcntl 'SEEK_CUR', 'SEEK_END'; my $page_size = $ENV{'INNODB_PAGE_SIZE'}; -my $restart = 'restart'; +my $restart; if ($ENV{'MYSQLD_IS_DEBUG'}) { # It is impractical to ensure that CREATE TABLE t will extend ibdata1. @@ -37,17 +37,14 @@ if ($ENV{'MYSQLD_IS_DEBUG'}) while() { unless (/\0*/gso) { $empty_tail= 0; last } } if ($empty_tail) { - $restart = 'restart: --innodb-data-file-size-debug=' . $size; + $restart = "--innodb-data-file-size-debug=$size"; truncate(FILE, $page_size * $root); } close FILE; } open(FILE, ">$ENV{MYSQLTEST_VARDIR}/log/start_mysqld.txt") || die; -print FILE '--exec echo "', $restart, '" > $_expect_file_name ---enable_reconnect ---source include/wait_until_connected_again.inc ---disable_reconnect -'; +print FILE "--let \$restart_parameters=$restart\n" if $restart; +print FILE "--source include/start_mysqld.inc\n"; close FILE; open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}test/ibd4.ibd") or die; truncate(FILE, $page_size * 4); From 1ba7234b211b4deec1e71f9b2d7db16543ece0e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 12 Jan 2017 13:30:10 +0200 Subject: [PATCH 067/167] Follow-up to MDEV-11713: Make more use of DBUG_LOG --- storage/innobase/buf/buf0flu.cc | 18 ++++------------ storage/innobase/fil/fil0fil.cc | 19 +++++++++-------- storage/innobase/fil/fil0pagecompress.cc | 6 ++---- storage/innobase/handler/ha_innodb.cc | 10 ++++----- storage/innobase/lock/lock0lock.cc | 21 +++++++++---------- storage/innobase/row/row0purge.cc | 24 +++++++++++----------- storage/innobase/trx/trx0purge.cc | 7 +++---- storage/innobase/trx/trx0trx.cc | 26 ++++++++++-------------- 8 files changed, 58 insertions(+), 73 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 0f901363596..2738fbd0ec7 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -3761,9 +3761,7 @@ FlushObserver::FlushObserver( m_removed->at(i) = 0; } -#ifdef FLUSH_LIST_OBSERVER_DEBUG - ib::info() << "FlushObserver constructor: " << m_trx->id; -#endif /* FLUSH_LIST_OBSERVER_DEBUG */ + DBUG_LOG("flush", "FlushObserver(): trx->id=" << m_trx->id); } /** FlushObserver deconstructor */ @@ -3774,9 +3772,7 @@ FlushObserver::~FlushObserver() UT_DELETE(m_flushed); UT_DELETE(m_removed); -#ifdef FLUSH_LIST_OBSERVER_DEBUG - ib::info() << "FlushObserver deconstructor: " << m_trx->id; -#endif /* FLUSH_LIST_OBSERVER_DEBUG */ + DBUG_LOG("flush", "~FlushObserver(): trx->id=" << m_trx->id); } /** Check whether trx is interrupted @@ -3809,10 +3805,7 @@ FlushObserver::notify_flush( m_stage->inc(); } -#ifdef FLUSH_LIST_OBSERVER_DEBUG - ib::info() << "Flush <" << bpage->id.space() - << ", " << bpage->id.page_no() << ">"; -#endif /* FLUSH_LIST_OBSERVER_DEBUG */ + DBUG_LOG("flush", "Flush " << bpage->id); } /** Notify observer of a remove @@ -3827,10 +3820,7 @@ FlushObserver::notify_remove( m_removed->at(buf_pool->instance_no)++; -#ifdef FLUSH_LIST_OBSERVER_DEBUG - ib::info() << "Remove <" << bpage->id.space() - << ", " << bpage->id.page_no() << ">"; -#endif /* FLUSH_LIST_OBSERVER_DEBUG */ + DBUG_LOG("flush", "Remove " << bpage->id); } /** Flush dirty pages and wait. */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index f104112eb7a..773eb0406ae 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -7376,14 +7376,17 @@ fil_space_get_crypt_data( space->crypt_data = fil_space_read_crypt_data(space_id, page, offset); ut_free(buf); -#ifdef UNIV_DEBUG - ib::info() << "Read page 0 from tablespace for" - << "space " << space_id - << " name " << space->name - << " key_id " << (space->crypt_data ? space->crypt_data->key_id : 0) - << " encryption " << (space->crypt_data ? space->crypt_data->encryption : 0) - << " handle " << node->handle; -#endif + DBUG_LOG("crypt", + "Read page 0 from" + << " tablespace " << space_id + << " name " << space->name + << " key_id " << (space->crypt_data + ? space->crypt_data->key_id + : 0) + << " encryption " + << (space->crypt_data + ? space->crypt_data->encryption : 0) + << " handle " << node->handle); ut_a(space->id == space_id); diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 98d732a9f9d..cd2c62e00c1 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -487,10 +487,8 @@ fil_decompress_page( *write_size = actual_size; } -#ifdef UNIV_PAGECOMPRESS_DEBUG - ib::info() << "Preparing for decompress for len " - << actual_size << "."; -#endif /* UNIV_PAGECOMPRESS_DEBUG */ + DBUG_LOG("compress", "Preparing for decompress for len " + << actual_size << "."); switch(compression_alg) { case PAGE_ZLIB_ALGORITHM: diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d9c32f286e6..9e9a6a5994d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5255,13 +5255,13 @@ innobase_rollback( error = trx_rollback_for_mysql(trx); if (trx->state == TRX_STATE_FORCED_ROLLBACK) { -#ifdef UNIV_DEBUG +#ifndef DBUG_OFF char buffer[1024]; - ib::info() << "Forced rollback : " - << thd_get_error_context_description(thd, - buffer, sizeof(buffer), 512); -#endif /* UNIV_DEBUG */ + DBUG_LOG("trx", "Forced rollback: " + << thd_get_error_context_description( + thd, buffer, sizeof buffer, 512)); +#endif /* !DBUG_OFF */ trx->state = TRX_STATE_NOT_STARTED; } diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 5711a681e63..379d00b00d7 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -2780,12 +2780,10 @@ RecLock::jump_queue( ut_ad(conflict_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT); ut_ad(conflict_lock->trx->lock.wait_lock == conflict_lock); -#ifdef UNIV_DEBUG - ib::info() << "Granting High Priority Transaction (ID): " - << lock->trx->id << " the lock jumping over" - << " waiting Transaction (ID): " - << conflict_lock->trx->id; -#endif /* UNIV_DEBUG */ + DBUG_LOG("trx", + "Granting High Priority Transaction " + << lock->trx->id << " a lock jumping over" + << " waiting Transaction " << conflict_lock->trx->id); lock_reset_lock_and_trx_wait(lock); return(true); @@ -2954,11 +2952,12 @@ RecLock::make_trx_hit_list( /* Assert that it is not waiting for current record. */ ut_ad(trx->lock.wait_lock != next); -#ifdef UNIV_DEBUG - ib::info() << "High Priority Transaction (ID): " - << lock->trx->id << " waking up blocking" - << " transaction (ID): " << trx->id; -#endif /* UNIV_DEBUG */ + + DBUG_LOG("trx", "High Priority Transaction " + << lock->trx->id + << " waking up blocking transaction " + << trx->id); + trx->lock.was_chosen_as_deadlock_victim = true; lock_cancel_waiting_and_release(trx->lock.wait_lock); trx_mutex_exit(trx); diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 23e08c38cdd..b41e3642cf0 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -515,22 +515,22 @@ row_purge_remove_sec_if_poss_leaf( page = btr_cur_get_page(btr_cur); if (!lock_test_prdt_page_lock( - trx, - page_get_space_id(page), - page_get_page_no(page)) - && page_get_n_recs(page) < 2 - && page_get_page_no(page) != - dict_index_get_page(index)) { + trx, + page_get_space_id(page), + page_get_page_no(page)) + && page_get_n_recs(page) < 2 + && btr_cur_get_block(btr_cur) + ->page.id.page_no() != + dict_index_get_page(index)) { /* this is the last record on page, and it has a "page" lock on it, which mean search is still depending on it, so do not delete */ -#ifdef UNIV_DEBUG - ib::info() << "skip purging last" - " record on page " - << page_get_page_no(page) - << "."; -#endif /* UNIV_DEBUG */ + DBUG_LOG("purge", + "skip purging last" + " record on page " + << btr_cur_get_block(btr_cur) + ->page.id); btr_pcur_close(&pcur); mtr_commit(&mtr); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 3526db99e79..acde762a0b7 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -933,10 +933,9 @@ trx_purge_mark_undo_for_truncate( return; } -#ifdef UNIV_DEBUG - ib::info() << "UNDO tablespace with space identifier " - << undo_trunc->get_marked_space_id() << " marked for truncate"; -#endif /* UNIV_DEBUG */ + DBUG_LOG("undo", + "marking for truncate UNDO tablespace " + << undo_trunc->get_marked_space_id()); /* Step-3: Iterate over all the rsegs of selected UNDO tablespace and mark them temporarily unavailable for allocation.*/ diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 68a0ad53550..3d1ac5172b3 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -3379,24 +3379,20 @@ trx_kill_blocking(trx_t* trx) trx_mutex_exit(victim_trx); -#ifdef UNIV_DEBUG +#ifndef DBUG_OFF char buffer[1024]; - char* thr_text; - trx_id_t id; +#endif /* !DBUG_OFF */ + + DBUG_LOG("trx", + "High Priority Transaction " + << trx->id << " killed transaction " + << victim_trx->id << " in hit list" + << " - " + << thd_get_error_context_description( + victim_trx->mysql_thd, + buffer, sizeof(buffer), 512)); - thr_text = thd_get_error_context_description(victim_trx->mysql_thd, - buffer, sizeof(buffer), - 512); - id = victim_trx->id; -#endif /* UNIV_DEBUG */ trx_rollback_for_mysql(victim_trx); - -#ifdef UNIV_DEBUG - ib::info() << "High Priority Transaction (ID): " - << trx->id << " killed transaction (ID): " - << id << " in hit list" - << " - " << thr_text; -#endif /* UNIV_DEBUG */ trx_mutex_enter(victim_trx); version++; From ebb8c9fb26f86cff8c0d81bd2415f415cef952bb Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 12 Jan 2017 15:16:45 +0400 Subject: [PATCH 068/167] MDEV-11030 Assertion `precision > 0' failed in decimal_bin_size Fixing Item::decimal_precision() to return at least one digit. This fixes the problem reported in MDEV. Also, fixing Item_func_signed::fix_length_and_dec() to reserve space for at least one digit (plus one character for an optional sign). This is needed to have CONVERT(expr,SIGNED) and CONVERT(expr,UNSIGNED) create correct string fields when they appear in string context, e.g.: CREATE TABLE t1 AS SELECT CONCAT(CONVERT('',SIGNED)); --- mysql-test/r/cast.result | 73 +++++++++++++++++++++++++++++++++++++++- mysql-test/t/cast.test | 39 +++++++++++++++++++++ sql/item.cc | 9 ++++- sql/item_func.h | 11 ++++-- 4 files changed, 128 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 4c9f257fdf2..ab784b5afc2 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -583,7 +583,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `cast(1 as unsigned)` int(1) unsigned NOT NULL, - `cast(1 as signed)` int(1) NOT NULL, + `cast(1 as signed)` int(2) NOT NULL, `cast(1 as double(5,2))` double(5,2) DEFAULT NULL, `cast(1 as decimal(5,3))` decimal(5,3) NOT NULL, `cast("A" as binary)` varbinary(1) NOT NULL, @@ -819,3 +819,74 @@ utf8_bin select collation(cast("a" as char(10) binary ascii)); collation(cast("a" as char(10) binary ascii)) latin1_bin +# +# MDEV-11030 Assertion `precision > 0' failed in decimal_bin_size +# +SELECT * FROM (SELECT IFNULL(CONVERT(NULL, UNSIGNED), NULL)) sq; +IFNULL(CONVERT(NULL, UNSIGNED), NULL) +NULL +CREATE TABLE t1 AS SELECT IFNULL(CONVERT(NULL, UNSIGNED), NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `IFNULL(CONVERT(NULL, UNSIGNED), NULL)` decimal(1,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 AS SELECT COALESCE(CONVERT(NULL, UNSIGNED), NULL); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `COALESCE(CONVERT(NULL, UNSIGNED), NULL)` decimal(1,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 AS SELECT CASE WHEN TRUE THEN CONVERT(NULL, UNSIGNED) ELSE NULL END; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `CASE WHEN TRUE THEN CONVERT(NULL, UNSIGNED) ELSE NULL END` decimal(1,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 AS SELECT IFNULL(CONVERT(NULL,SIGNED),CONVERT(NULL,UNSIGNED)) AS a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` decimal(1,0) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 AS SELECT +-1, +CONVERT(NULL,SIGNED), +CONCAT(CONVERT(NULL,SIGNED)), +1, +CONVERT(NULL,UNSIGNED), +CONCAT(CONVERT(NULL,UNSIGNED)); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `-1` int(2) NOT NULL, + `CONVERT(NULL,SIGNED)` int(2) DEFAULT NULL, + `CONCAT(CONVERT(NULL,SIGNED))` varchar(2) DEFAULT NULL, + `1` int(1) NOT NULL, + `CONVERT(NULL,UNSIGNED)` int(1) unsigned DEFAULT NULL, + `CONCAT(CONVERT(NULL,UNSIGNED))` varchar(1) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1 AS SELECT +CONVERT('',SIGNED), +CONCAT(CONVERT('',SIGNED)), +CONVERT('',UNSIGNED), +CONCAT(CONVERT('',UNSIGNED)); +Warnings: +Warning 1292 Truncated incorrect INTEGER value: '' +Warning 1292 Truncated incorrect INTEGER value: '' +Warning 1292 Truncated incorrect INTEGER value: '' +Warning 1292 Truncated incorrect INTEGER value: '' +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `CONVERT('',SIGNED)` int(2) NOT NULL, + `CONCAT(CONVERT('',SIGNED))` varchar(2) NOT NULL, + `CONVERT('',UNSIGNED)` int(1) unsigned NOT NULL, + `CONCAT(CONVERT('',UNSIGNED))` varchar(1) NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 58f91571ebb..5316c12c857 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -472,3 +472,42 @@ select collation(cast("a" as char(10) ascii binary)); select collation(cast("a" as char(10) binary charset utf8)); select collation(cast("a" as char(10) binary ascii)); +--echo # +--echo # MDEV-11030 Assertion `precision > 0' failed in decimal_bin_size +--echo # + +SELECT * FROM (SELECT IFNULL(CONVERT(NULL, UNSIGNED), NULL)) sq; + +CREATE TABLE t1 AS SELECT IFNULL(CONVERT(NULL, UNSIGNED), NULL); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 AS SELECT COALESCE(CONVERT(NULL, UNSIGNED), NULL); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 AS SELECT CASE WHEN TRUE THEN CONVERT(NULL, UNSIGNED) ELSE NULL END; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 AS SELECT IFNULL(CONVERT(NULL,SIGNED),CONVERT(NULL,UNSIGNED)) AS a; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 AS SELECT + -1, + CONVERT(NULL,SIGNED), + CONCAT(CONVERT(NULL,SIGNED)), + 1, + CONVERT(NULL,UNSIGNED), + CONCAT(CONVERT(NULL,UNSIGNED)); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1 AS SELECT + CONVERT('',SIGNED), + CONCAT(CONVERT('',SIGNED)), + CONVERT('',UNSIGNED), + CONCAT(CONVERT('',UNSIGNED)); +SHOW CREATE TABLE t1; +DROP TABLE t1; diff --git a/sql/item.cc b/sql/item.cc index 08599f1d486..015f5591c5d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -533,7 +533,14 @@ uint Item::decimal_precision() const unsigned_flag); return MY_MIN(prec, DECIMAL_MAX_PRECISION); } - return MY_MIN(max_char_length(), DECIMAL_MAX_PRECISION); + uint res= max_char_length(); + /* + Return at least one decimal digit, even if Item::max_char_length() + returned 0. This is important to avoid attempts to create fields of types + INT(0) or DECIMAL(0,0) when converting NULL or empty strings to INT/DECIMAL: + CREATE TABLE t1 AS SELECT CONVERT(NULL,SIGNED) AS a; + */ + return res ? MY_MIN(res, DECIMAL_MAX_PRECISION) : 1; } diff --git a/sql/item_func.h b/sql/item_func.h index 4a55bd68453..56d7c190181 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -626,8 +626,15 @@ public: longlong val_int_from_str(int *error); void fix_length_and_dec() { - fix_char_length(MY_MIN(args[0]->max_char_length(), - MY_INT64_NUM_DECIMAL_DIGITS)); + uint32 char_length= MY_MIN(args[0]->max_char_length(), + MY_INT64_NUM_DECIMAL_DIGITS); + /* + args[0]->max_char_length() can return 0. + Reserve max_length to fit at least one character for one digit, + plus one character for the sign (if signed). + */ + set_if_bigger(char_length, 1 + (unsigned_flag ? 0 : 1)); + fix_char_length(char_length); } virtual void print(String *str, enum_query_type query_type); uint decimal_precision() const { return args[0]->decimal_precision(); } From 1282eb694c9fb18cac6bace643b4ce275a6a5689 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 11 Dec 2016 17:16:15 +0100 Subject: [PATCH 069/167] cleanup: make malloc_size_cb_func always defined --- mysys/my_malloc.c | 17 +++++++++-------- sql/mysqld.cc | 5 ++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index e533230106e..dc02d3896bd 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -48,7 +48,6 @@ static inline size_t malloc_size_and_flag(void *p, my_bool *is_thread_specific) #define MALLOC_FIX_POINTER_FOR_FREE(p) (((char*) (p)) - MALLOC_PREFIX_SIZE) #endif /* SAFEMALLOC */ -static MALLOC_SIZE_CB malloc_size_cb_func= NULL; /** Inform application that memory usage has changed @@ -59,17 +58,19 @@ static MALLOC_SIZE_CB malloc_size_cb_func= NULL; The type os size is long long, to be able to handle negative numbers to decrement the memory usage -*/ -static void update_malloc_size(long long size, my_bool is_thread_specific) -{ - if (malloc_size_cb_func) - malloc_size_cb_func(size, is_thread_specific); -} + @return 0 - ok + 1 - failure, abort the allocation +*/ +static void dummy(long long size __attribute__((unused)), + my_bool is_thread_specific __attribute__((unused))) +{} + +static MALLOC_SIZE_CB update_malloc_size= dummy; void set_malloc_size_cb(MALLOC_SIZE_CB func) { - malloc_size_cb_func= func; + update_malloc_size= func ? func : dummy; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index adb1b273b80..96baaf25287 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3989,7 +3989,7 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) { THD *thd= current_thd; - if (likely(is_thread_specific)) /* If thread specific memory */ + if (is_thread_specific) /* If thread specific memory */ { /* When thread specfic is set, both mysqld_server_initialized and thd @@ -4006,8 +4006,7 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) else if (likely(thd)) { DBUG_PRINT("info", ("global thd memory_used: %lld size: %lld", - (longlong) thd->status_var.global_memory_used, - size)); + (longlong) thd->status_var.global_memory_used, size)); thd->status_var.global_memory_used+= size; } else From ab3388c3c44caecbec9974f54a2f30dd06237eee Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 12 Dec 2016 01:00:45 +0100 Subject: [PATCH 070/167] bugfix: mutex order violation in embedded safe_mutex: Found wrong usage of mutex 'LOCK_thread_count' and 'LOCK_status' Mutex currently locked (in reverse order): LOCK_status sql/sql_class.h line 3873 LOCK_thread_count libmysqld/lib_sql.cc line 432 --- libmysqld/lib_sql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 63424af27f6..0dfb1a1ad9a 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -434,8 +434,8 @@ static void emb_free_embedded_thd(MYSQL *mysql) thread_count--; thd->store_globals(); thd->unlink(); - delete thd; mysql_mutex_unlock(&LOCK_thread_count); + delete thd; my_pthread_setspecific_ptr(THR_THD, 0); mysql->thd=0; } From 7e2f9d092dd1fb6b0fa1a8fdd5d1f3af68b56f45 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 12 Dec 2016 01:01:56 +0100 Subject: [PATCH 071/167] max_session_mem_used server variable --- mysql-test/r/mysqld--help.result | 5 + .../r/sysvars_server_embedded,32bit.rdiff | 168 ++++++++--------- .../sys_vars/r/sysvars_server_embedded.result | 14 ++ .../r/sysvars_server_notembedded,32bit.rdiff | 176 +++++++++--------- .../r/sysvars_server_notembedded.result | 14 ++ sql/mysqld.cc | 9 + sql/sql_class.cc | 6 +- sql/sql_class.h | 1 + sql/sys_vars.cc | 7 + 9 files changed, 226 insertions(+), 174 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 93027e2bba4..340fa21f0df 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -457,6 +457,10 @@ The following options may be given as the first argument: --max-seeks-for-key=# Limit assumed max number of seeks when looking up rows based on a key + --max-session-mem-used=# + Amount of memory a single user session is allowed to + allocate. This limits the value of the session variable + MEM_USED --max-sort-length=# The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) @@ -1266,6 +1270,7 @@ max-long-data-size 4194304 max-prepared-stmt-count 16382 max-relay-log-size 1073741824 max-seeks-for-key 18446744073709551615 +max-session-mem-used 9223372036854775807 max-sort-length 1024 max-sp-recursion-depth 0 max-statement-time 0 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index 13fa9b8e2b4..8a5a2d771b0 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1,5 +1,5 @@ ---- suite/sys_vars/r/sysvars_server_embedded.result 2016-03-23 01:02:33.000000000 +0100 -+++ suite/sys_vars/r/sysvars_server_embedded.reject 2016-03-23 01:09:44.000000000 +0100 +--- sysvars_server_embedded.result ++++ sysvars_server_embedded,32bit.result~ @@ -57,7 +57,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1 @@ -476,7 +476,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2045,7 +2045,7 @@ +@@ -2059,7 +2059,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE SESSION @@ -485,7 +485,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2073,7 +2073,7 @@ +@@ -2087,7 +2087,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE GLOBAL @@ -494,7 +494,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2087,7 +2087,7 @@ +@@ -2101,7 +2101,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -503,7 +503,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2101,7 +2101,7 @@ +@@ -2115,7 +2115,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL @@ -512,7 +512,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2115,7 +2115,7 @@ +@@ -2129,7 +2129,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -521,7 +521,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2129,7 +2129,7 @@ +@@ -2143,7 +2143,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -530,7 +530,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2143,10 +2143,10 @@ +@@ -2157,10 +2157,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE SESSION @@ -543,7 +543,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2157,7 +2157,7 @@ +@@ -2171,7 +2171,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -552,7 +552,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2171,7 +2171,7 @@ +@@ -2185,7 +2185,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL @@ -561,7 +561,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2181,9 +2181,9 @@ +@@ -2195,9 +2195,9 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE SESSION_VALUE NULL @@ -573,7 +573,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this -@@ -2195,14 +2195,14 @@ +@@ -2209,14 +2209,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MMAP_SIZE SESSION_VALUE NULL @@ -591,7 +591,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2227,10 +2227,10 @@ +@@ -2241,10 +2241,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -604,7 +604,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2244,7 +2244,7 @@ +@@ -2258,7 +2258,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -613,7 +613,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2297,7 +2297,7 @@ +@@ -2311,7 +2311,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -622,7 +622,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2311,7 +2311,7 @@ +@@ -2325,7 +2325,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE SESSION @@ -631,7 +631,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2325,7 +2325,7 @@ +@@ -2339,7 +2339,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE SESSION @@ -640,7 +640,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2339,7 +2339,7 @@ +@@ -2353,7 +2353,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 60 VARIABLE_SCOPE SESSION @@ -649,7 +649,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2409,7 +2409,7 @@ +@@ -2423,7 +2423,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -658,7 +658,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2423,7 +2423,7 @@ +@@ -2437,7 +2437,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 62 VARIABLE_SCOPE SESSION @@ -667,7 +667,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to 63, the optimizer will switch to the original find_best search. NOTE: The value 63 and its associated behaviour is deprecated NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 63 -@@ -2437,7 +2437,7 @@ +@@ -2451,7 +2451,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE SESSION @@ -676,7 +676,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2465,7 +2465,7 @@ +@@ -2479,7 +2479,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -685,7 +685,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2493,7 +2493,7 @@ +@@ -2507,7 +2507,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -694,7 +694,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2507,7 +2507,7 @@ +@@ -2521,7 +2521,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -703,7 +703,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 200 -@@ -2521,7 +2521,7 @@ +@@ -2535,7 +2535,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -712,7 +712,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2535,7 +2535,7 @@ +@@ -2549,7 +2549,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -721,7 +721,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2549,7 +2549,7 @@ +@@ -2563,7 +2563,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -730,7 +730,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2563,7 +2563,7 @@ +@@ -2577,7 +2577,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -739,7 +739,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2577,7 +2577,7 @@ +@@ -2591,7 +2591,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -748,7 +748,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2591,7 +2591,7 @@ +@@ -2605,7 +2605,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -757,7 +757,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2605,7 +2605,7 @@ +@@ -2619,7 +2619,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -766,7 +766,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2619,7 +2619,7 @@ +@@ -2633,7 +2633,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 80 VARIABLE_SCOPE GLOBAL @@ -775,7 +775,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2633,7 +2633,7 @@ +@@ -2647,7 +2647,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -784,7 +784,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2647,7 +2647,7 @@ +@@ -2661,7 +2661,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -793,7 +793,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2661,7 +2661,7 @@ +@@ -2675,7 +2675,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -802,7 +802,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2675,7 +2675,7 @@ +@@ -2689,7 +2689,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE GLOBAL @@ -811,7 +811,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2689,7 +2689,7 @@ +@@ -2703,7 +2703,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -820,7 +820,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2703,7 +2703,7 @@ +@@ -2717,7 +2717,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 200 VARIABLE_SCOPE GLOBAL @@ -829,7 +829,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2717,7 +2717,7 @@ +@@ -2731,7 +2731,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -838,7 +838,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2731,7 +2731,7 @@ +@@ -2745,7 +2745,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 40 VARIABLE_SCOPE GLOBAL @@ -847,7 +847,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2745,7 +2745,7 @@ +@@ -2759,7 +2759,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -856,7 +856,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2759,7 +2759,7 @@ +@@ -2773,7 +2773,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -865,7 +865,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2773,7 +2773,7 @@ +@@ -2787,7 +2787,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -874,7 +874,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2787,7 +2787,7 @@ +@@ -2801,7 +2801,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 150 VARIABLE_SCOPE GLOBAL @@ -883,7 +883,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2801,7 +2801,7 @@ +@@ -2815,7 +2815,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 178 VARIABLE_SCOPE GLOBAL @@ -892,7 +892,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2815,7 +2815,7 @@ +@@ -2829,7 +2829,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -901,7 +901,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2829,7 +2829,7 @@ +@@ -2843,7 +2843,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -910,7 +910,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2843,7 +2843,7 @@ +@@ -2857,7 +2857,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -919,7 +919,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2857,7 +2857,7 @@ +@@ -2871,7 +2871,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -928,7 +928,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2871,7 +2871,7 @@ +@@ -2885,7 +2885,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -937,7 +937,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2885,7 +2885,7 @@ +@@ -2899,7 +2899,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -946,7 +946,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -2899,7 +2899,7 @@ +@@ -2913,7 +2913,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -955,7 +955,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2913,7 +2913,7 @@ +@@ -2927,7 +2927,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -964,7 +964,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2983,7 +2983,7 @@ +@@ -2997,7 +2997,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE SESSION @@ -973,7 +973,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3011,7 +3011,7 @@ +@@ -3025,7 +3025,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -982,7 +982,7 @@ VARIABLE_COMMENT Limit of query profiling memory NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3025,7 +3025,7 @@ +@@ -3039,7 +3039,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5 VARIABLE_SCOPE SESSION @@ -991,7 +991,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3081,10 +3081,10 @@ +@@ -3095,10 +3095,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION ONLY @@ -1004,7 +1004,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3095,7 +3095,7 @@ +@@ -3109,7 +3109,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -1013,7 +1013,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3109,7 +3109,7 @@ +@@ -3123,7 +3123,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -1022,7 +1022,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3123,7 +3123,7 @@ +@@ -3137,7 +3137,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE GLOBAL @@ -1031,7 +1031,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3140,7 +3140,7 @@ +@@ -3154,7 +3154,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1040,7 +1040,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3193,7 +3193,7 @@ +@@ -3207,7 +3207,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 24576 VARIABLE_SCOPE SESSION @@ -1049,7 +1049,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3207,7 +3207,7 @@ +@@ -3221,7 +3221,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1058,7 +1058,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3221,7 +3221,7 @@ +@@ -3235,7 +3235,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE SESSION @@ -1067,7 +1067,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3249,7 +3249,7 @@ +@@ -3263,7 +3263,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -1076,7 +1076,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3263,10 +3263,10 @@ +@@ -3277,10 +3277,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8388608 VARIABLE_SCOPE SESSION @@ -1089,7 +1089,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3305,7 +3305,7 @@ +@@ -3319,7 +3319,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -1098,7 +1098,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3403,7 +3403,7 @@ +@@ -3417,7 +3417,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -1107,7 +1107,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3417,7 +3417,7 @@ +@@ -3431,7 +3431,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -1116,7 +1116,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3476,7 +3476,7 @@ +@@ -3490,7 +3490,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1125,7 +1125,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3753,7 +3753,7 @@ +@@ -3767,7 +3767,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1134,7 +1134,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -3823,7 +3823,7 @@ +@@ -3837,7 +3837,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 400 VARIABLE_SCOPE GLOBAL @@ -1143,7 +1143,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 524288 -@@ -3837,7 +3837,7 @@ +@@ -3851,7 +3851,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2000 VARIABLE_SCOPE GLOBAL @@ -1152,7 +1152,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -3851,7 +3851,7 @@ +@@ -3865,7 +3865,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1161,7 +1161,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -3865,7 +3865,7 @@ +@@ -3879,7 +3879,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1170,7 +1170,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -3980,7 +3980,7 @@ +@@ -3994,7 +3994,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM or Aria table NUMERIC_MIN_VALUE 1024 @@ -1179,7 +1179,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3991,7 +3991,7 @@ +@@ -4005,7 +4005,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8192 VARIABLE_SCOPE SESSION @@ -1188,7 +1188,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4005,7 +4005,7 @@ +@@ -4019,7 +4019,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1197,7 +1197,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4103,7 +4103,7 @@ +@@ -4117,7 +4117,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -1206,7 +1206,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4207,7 +4207,7 @@ +@@ -4221,7 +4221,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -1215,7 +1215,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4220,7 +4220,7 @@ +@@ -4234,7 +4234,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1224,7 +1224,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4230,7 +4230,7 @@ +@@ -4244,7 +4244,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1233,7 +1233,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4315,7 +4315,7 @@ +@@ -4329,7 +4329,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index dfac2966558..7d728bc89dc 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -1997,6 +1997,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME MAX_SESSION_MEM_USED +SESSION_VALUE 9223372036854775807 +GLOBAL_VALUE 9223372036854775807 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 9223372036854775807 +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Amount of memory a single user session is allowed to allocate. This limits the value of the session variable MEM_USED +NUMERIC_MIN_VALUE 8192 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH SESSION_VALUE 1024 GLOBAL_VALUE 1024 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index 2246560d45a..918bee1e007 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1,5 +1,5 @@ ---- suite/sys_vars/r/sysvars_server_notembedded.result 2016-03-22 21:25:49.000000000 +0100 -+++ suite/sys_vars/r/sysvars_server_notembedded.reject 2016-03-23 01:11:50.000000000 +0100 +--- sysvars_server_notembedded.result ++++ sysvars_server_notembedded,32bit.result~ @@ -57,7 +57,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1 @@ -476,7 +476,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2241,7 +2241,7 @@ +@@ -2255,7 +2255,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE SESSION @@ -485,7 +485,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2269,7 +2269,7 @@ +@@ -2283,7 +2283,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE GLOBAL @@ -494,7 +494,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2283,7 +2283,7 @@ +@@ -2297,7 +2297,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -503,7 +503,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2297,7 +2297,7 @@ +@@ -2311,7 +2311,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL @@ -512,7 +512,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2311,7 +2311,7 @@ +@@ -2325,7 +2325,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -521,7 +521,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2325,7 +2325,7 @@ +@@ -2339,7 +2339,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -530,7 +530,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2339,10 +2339,10 @@ +@@ -2353,10 +2353,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE SESSION @@ -543,7 +543,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2353,7 +2353,7 @@ +@@ -2367,7 +2367,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -552,7 +552,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2367,7 +2367,7 @@ +@@ -2381,7 +2381,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL @@ -561,7 +561,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2377,9 +2377,9 @@ +@@ -2391,9 +2391,9 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE SESSION_VALUE NULL @@ -573,7 +573,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this -@@ -2391,14 +2391,14 @@ +@@ -2405,14 +2405,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MMAP_SIZE SESSION_VALUE NULL @@ -591,7 +591,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2423,10 +2423,10 @@ +@@ -2437,10 +2437,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -604,7 +604,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2440,7 +2440,7 @@ +@@ -2454,7 +2454,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -613,7 +613,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2493,7 +2493,7 @@ +@@ -2507,7 +2507,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -622,7 +622,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2507,7 +2507,7 @@ +@@ -2521,7 +2521,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE SESSION @@ -631,7 +631,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2521,7 +2521,7 @@ +@@ -2535,7 +2535,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE SESSION @@ -640,7 +640,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2535,7 +2535,7 @@ +@@ -2549,7 +2549,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 60 VARIABLE_SCOPE SESSION @@ -649,7 +649,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2605,7 +2605,7 @@ +@@ -2619,7 +2619,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -658,7 +658,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2619,7 +2619,7 @@ +@@ -2633,7 +2633,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 62 VARIABLE_SCOPE SESSION @@ -667,7 +667,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to 63, the optimizer will switch to the original find_best search. NOTE: The value 63 and its associated behaviour is deprecated NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 63 -@@ -2633,7 +2633,7 @@ +@@ -2647,7 +2647,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE SESSION @@ -676,7 +676,7 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2661,7 +2661,7 @@ +@@ -2675,7 +2675,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -685,7 +685,7 @@ VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2689,7 +2689,7 @@ +@@ -2703,7 +2703,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -694,7 +694,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2703,7 +2703,7 @@ +@@ -2717,7 +2717,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -703,7 +703,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 200 -@@ -2717,7 +2717,7 @@ +@@ -2731,7 +2731,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -712,7 +712,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2731,7 +2731,7 @@ +@@ -2745,7 +2745,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -721,7 +721,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2745,7 +2745,7 @@ +@@ -2759,7 +2759,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -730,7 +730,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2759,7 +2759,7 @@ +@@ -2773,7 +2773,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -739,7 +739,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2773,7 +2773,7 @@ +@@ -2787,7 +2787,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -748,7 +748,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2787,7 +2787,7 @@ +@@ -2801,7 +2801,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -757,7 +757,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2801,7 +2801,7 @@ +@@ -2815,7 +2815,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -766,7 +766,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2815,7 +2815,7 @@ +@@ -2829,7 +2829,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 80 VARIABLE_SCOPE GLOBAL @@ -775,7 +775,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2829,7 +2829,7 @@ +@@ -2843,7 +2843,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -784,7 +784,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2843,7 +2843,7 @@ +@@ -2857,7 +2857,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -793,7 +793,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2857,7 +2857,7 @@ +@@ -2871,7 +2871,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -802,7 +802,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2871,7 +2871,7 @@ +@@ -2885,7 +2885,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE GLOBAL @@ -811,7 +811,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2885,7 +2885,7 @@ +@@ -2899,7 +2899,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -820,7 +820,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2899,7 +2899,7 @@ +@@ -2913,7 +2913,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 200 VARIABLE_SCOPE GLOBAL @@ -829,7 +829,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2913,7 +2913,7 @@ +@@ -2927,7 +2927,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -838,7 +838,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2927,7 +2927,7 @@ +@@ -2941,7 +2941,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 40 VARIABLE_SCOPE GLOBAL @@ -847,7 +847,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2941,7 +2941,7 @@ +@@ -2955,7 +2955,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -856,7 +856,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2955,7 +2955,7 @@ +@@ -2969,7 +2969,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -865,7 +865,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2969,7 +2969,7 @@ +@@ -2983,7 +2983,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -874,7 +874,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2983,7 +2983,7 @@ +@@ -2997,7 +2997,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 150 VARIABLE_SCOPE GLOBAL @@ -883,7 +883,7 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2997,7 +2997,7 @@ +@@ -3011,7 +3011,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 178 VARIABLE_SCOPE GLOBAL @@ -892,7 +892,7 @@ VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3011,7 +3011,7 @@ +@@ -3025,7 +3025,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -901,7 +901,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3025,7 +3025,7 @@ +@@ -3039,7 +3039,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -910,7 +910,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3039,7 +3039,7 @@ +@@ -3053,7 +3053,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -919,7 +919,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3053,7 +3053,7 @@ +@@ -3067,7 +3067,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -928,7 +928,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3067,7 +3067,7 @@ +@@ -3081,7 +3081,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -937,7 +937,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3081,7 +3081,7 @@ +@@ -3095,7 +3095,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -946,7 +946,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -3095,7 +3095,7 @@ +@@ -3109,7 +3109,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -955,7 +955,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -3109,7 +3109,7 @@ +@@ -3123,7 +3123,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -964,7 +964,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3179,7 +3179,7 @@ +@@ -3193,7 +3193,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE SESSION @@ -973,7 +973,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3207,7 +3207,7 @@ +@@ -3221,7 +3221,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -982,7 +982,7 @@ VARIABLE_COMMENT Limit of query profiling memory NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3221,7 +3221,7 @@ +@@ -3235,7 +3235,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5 VARIABLE_SCOPE SESSION @@ -991,7 +991,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3277,10 +3277,10 @@ +@@ -3291,10 +3291,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION ONLY @@ -1004,7 +1004,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3291,7 +3291,7 @@ +@@ -3305,7 +3305,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -1013,7 +1013,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3305,7 +3305,7 @@ +@@ -3319,7 +3319,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -1022,7 +1022,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3319,7 +3319,7 @@ +@@ -3333,7 +3333,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE GLOBAL @@ -1031,7 +1031,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3336,7 +3336,7 @@ +@@ -3350,7 +3350,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1040,7 +1040,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3389,7 +3389,7 @@ +@@ -3403,7 +3403,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 24576 VARIABLE_SCOPE SESSION @@ -1049,7 +1049,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3403,7 +3403,7 @@ +@@ -3417,7 +3417,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1058,7 +1058,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3417,7 +3417,7 @@ +@@ -3431,7 +3431,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE SESSION @@ -1067,7 +1067,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3445,7 +3445,7 @@ +@@ -3459,7 +3459,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -1076,7 +1076,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3725,10 +3725,10 @@ +@@ -3739,10 +3739,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8388608 VARIABLE_SCOPE SESSION @@ -1089,7 +1089,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3767,7 +3767,7 @@ +@@ -3781,7 +3781,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -1098,7 +1098,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3893,7 +3893,7 @@ +@@ -3907,7 +3907,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1107,7 +1107,7 @@ VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -3935,7 +3935,7 @@ +@@ -3949,7 +3949,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -1116,7 +1116,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3963,7 +3963,7 @@ +@@ -3977,7 +3977,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE GLOBAL @@ -1125,7 +1125,7 @@ VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2147483647 -@@ -3991,7 +3991,7 @@ +@@ -4005,7 +4005,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1134,7 +1134,7 @@ VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -4047,7 +4047,7 @@ +@@ -4061,7 +4061,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1143,7 +1143,7 @@ VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout, before giving up and stopping NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4075,7 +4075,7 @@ +@@ -4089,7 +4089,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -1152,7 +1152,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -4134,7 +4134,7 @@ +@@ -4148,7 +4148,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1161,7 +1161,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4425,7 +4425,7 @@ +@@ -4439,7 +4439,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1170,7 +1170,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -4523,7 +4523,7 @@ +@@ -4537,7 +4537,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 400 VARIABLE_SCOPE GLOBAL @@ -1179,7 +1179,7 @@ VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 NUMERIC_MAX_VALUE 524288 -@@ -4537,7 +4537,7 @@ +@@ -4551,7 +4551,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2000 VARIABLE_SCOPE GLOBAL @@ -1188,7 +1188,7 @@ VARIABLE_COMMENT The number of cached open tables NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -4551,7 +4551,7 @@ +@@ -4565,7 +4565,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1197,7 +1197,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -4565,7 +4565,7 @@ +@@ -4579,7 +4579,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1206,7 +1206,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -4750,7 +4750,7 @@ +@@ -4764,7 +4764,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MySQL will automatically convert it to an on-disk MyISAM or Aria table NUMERIC_MIN_VALUE 1024 @@ -1215,7 +1215,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4761,7 +4761,7 @@ +@@ -4775,7 +4775,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8192 VARIABLE_SCOPE SESSION @@ -1224,7 +1224,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4775,7 +4775,7 @@ +@@ -4789,7 +4789,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1233,7 +1233,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4873,7 +4873,7 @@ +@@ -4887,7 +4887,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -1242,7 +1242,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4977,7 +4977,7 @@ +@@ -4991,7 +4991,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -1251,7 +1251,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4990,7 +4990,7 @@ +@@ -5004,7 +5004,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1260,7 +1260,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5000,7 +5000,7 @@ +@@ -5014,7 +5014,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1269,7 +1269,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5085,7 +5085,7 @@ +@@ -5099,7 +5099,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 33d1f9722df..d6c4050545d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -2193,6 +2193,20 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME MAX_SESSION_MEM_USED +SESSION_VALUE 9223372036854775807 +GLOBAL_VALUE 9223372036854775807 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 9223372036854775807 +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Amount of memory a single user session is allowed to allocate. This limits the value of the session variable MEM_USED +NUMERIC_MIN_VALUE 8192 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_SORT_LENGTH SESSION_VALUE 1024 GLOBAL_VALUE 1024 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 96baaf25287..fcb6697fed6 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4001,6 +4001,15 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) (longlong) thd->status_var.local_memory_used, size)); thd->status_var.local_memory_used+= size; + if (thd->status_var.local_memory_used > (int64)thd->variables.max_mem_used && + !thd->killed) + { + char buf[1024]; + thd->killed= KILL_QUERY; + my_snprintf(buf, sizeof(buf), "--max-thread-mem-used=%llu", + thd->variables.max_mem_used); + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), buf); + } DBUG_ASSERT((longlong) thd->status_var.local_memory_used >= 0); } else if (likely(thd)) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4143d2cc419..c9592df1b65 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -906,8 +906,8 @@ THD::THD(bool is_wsrep_applier) #endif { ulong tmp; + bzero(&variables, sizeof(variables)); - mdl_context.init(this); /* We set THR_THD to temporally point to this THD to register all the variables that allocates memory for this THD @@ -916,8 +916,11 @@ THD::THD(bool is_wsrep_applier) set_current_thd(this); status_var.local_memory_used= sizeof(THD); status_var.global_memory_used= 0; + variables.max_mem_used= global_system_variables.max_mem_used; main_da.init(); + mdl_context.init(this); + /* Pass nominal parameters to init_alloc_root only to ensure that the destructor works OK in case of an error. The main_mem_root @@ -964,7 +967,6 @@ THD::THD(bool is_wsrep_applier) connection_name.str= 0; connection_name.length= 0; - bzero(&variables, sizeof(variables)); file_id = 0; query_id= 0; query_name_consts= 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index da885c3dbac..3058d81496c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -540,6 +540,7 @@ typedef struct system_variables ulonglong sortbuff_size; ulonglong group_concat_max_len; ulonglong default_regex_flags; + ulonglong max_mem_used; /** Place holders to store Multi-source variables in sys_var.cc during diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index bb349e78724..641f8306f98 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5401,3 +5401,10 @@ static Sys_var_ulong Sys_log_tc_size( DEFAULT(my_getpagesize() * 6), BLOCK_SIZE(my_getpagesize())); #endif + +static Sys_var_ulonglong Sys_max_thread_mem( + "max_session_mem_used", "Amount of memory a single user session " + "is allowed to allocate. This limits the value of the " + "session variable MEM_USED", SESSION_VAR(max_mem_used), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(8192, ULONGLONG_MAX), + DEFAULT(LONGLONG_MAX), BLOCK_SIZE(1)); From 5dfab33c4ec54082daf034da99c4a796410fe4f3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 12 Jan 2017 00:33:21 +0100 Subject: [PATCH 072/167] MDEV-11551 Server crashes in Field::is_real_null sometimes table->s->stored_fields is less than table->s->null_fields --- mysql-test/r/trigger_null-8605.result | 10 ++++++++++ mysql-test/t/trigger_null-8605.test | 14 ++++++++++++++ sql/sql_trigger.cc | 2 +- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/trigger_null-8605.result b/mysql-test/r/trigger_null-8605.result index b187fc19554..10315988708 100644 --- a/mysql-test/r/trigger_null-8605.result +++ b/mysql-test/r/trigger_null-8605.result @@ -354,3 +354,13 @@ show columns from t1; Field Type Null Key Default Extra a int(11) NO PRI NULL drop table t1; +create table t1 ( +pk int primary key, +i int, +v1 int as (i) virtual, +v2 int as (i) virtual +); +create trigger tr before update on t1 for each row set @a = 1; +insert into t1 (pk, i) values (null, null); +ERROR 23000: Column 'pk' cannot be null +drop table t1; diff --git a/mysql-test/t/trigger_null-8605.test b/mysql-test/t/trigger_null-8605.test index 748768a1849..34a57654b48 100644 --- a/mysql-test/t/trigger_null-8605.test +++ b/mysql-test/t/trigger_null-8605.test @@ -373,3 +373,17 @@ show columns from t1; insert into t1 (a) values (3); show columns from t1; drop table t1; + +# +# MDEV-11551 Server crashes in Field::is_real_null +# +create table t1 ( + pk int primary key, + i int, + v1 int as (i) virtual, + v2 int as (i) virtual +); +create trigger tr before update on t1 for each row set @a = 1; +--error ER_BAD_NULL_ERROR +insert into t1 (pk, i) values (null, null); +drop table t1; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 7a61279fc9c..7bfc1e950b5 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1082,7 +1082,7 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table) && (table->s->stored_fields != table->s->null_fields)) { - int null_bytes= (table->s->stored_fields - table->s->null_fields + 7)/8; + int null_bytes= (table->s->fields - table->s->null_fields + 7)/8; if (!(extra_null_bitmap= (uchar*)alloc_root(&table->mem_root, null_bytes))) return 1; if (!(record0_field= (Field **)alloc_root(&table->mem_root, From 9b99d9bebd32b0280e7c7514c7fe65531316ad98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 14 Jan 2017 17:52:33 +0200 Subject: [PATCH 073/167] MDEV-8139: Disable a randomly failing test until the code is fixed. --- mysql-test/suite/encryption/disabled.def | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/encryption/disabled.def b/mysql-test/suite/encryption/disabled.def index 348e4c979ea..d92d3495cb8 100644 --- a/mysql-test/suite/encryption/disabled.def +++ b/mysql-test/suite/encryption/disabled.def @@ -10,4 +10,5 @@ # ############################################################################## -innodb_scrub_background : MDEV-8139 background scrubbing does not work reliably +innodb_scrub : MDEV-8139 scrubbing does not work reliably +innodb_scrub_background : MDEV-8139 scrubbing does not work reliably From a9d00db15559749e54fd9d55cf0ff90f83604e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sun, 15 Jan 2017 14:20:16 +0200 Subject: [PATCH 074/167] MDEV-11799 InnoDB can abort if the doublewrite buffer contains a bad and a good copy Clean up the InnoDB doublewrite buffer code. buf_dblwr_init_or_load_pages(): Do not add empty pages to the buffer. buf_dblwr_process(): Do consider changes to pages that are all zero. Do not abort when finding a corrupted copy of a page in the doublewrite buffer, because there could be multiple copies in the doublewrite buffer, and only one of them needs to be good. --- .../suite/innodb/r/group_commit_crash.result | 1 - ...oup_commit_crash_no_optimize_thread.result | 1 - .../innodb/r/innodb-alter-tempfile.result | 4 - .../suite/innodb/r/innodb_bug14147491.result | 1 - mysql-test/suite/innodb/r/xa_recovery.result | 2 +- .../suite/innodb/t/group_commit_crash.test | 2 - ...group_commit_crash_no_optimize_thread.test | 2 - .../suite/innodb/t/innodb-alter-tempfile.test | 7 - .../suite/innodb/t/innodb_bug14147491.test | 1 - mysql-test/suite/innodb/t/xa_recovery.test | 16 +- mysql-test/suite/rpl/r/rpl_gtid_crash.result | 1 - mysql-test/suite/rpl/t/rpl_gtid_crash.test | 5 - storage/innobase/buf/buf0dblwr.cc | 238 ++++++++---------- storage/xtradb/buf/buf0dblwr.cc | 237 ++++++++--------- 14 files changed, 207 insertions(+), 311 deletions(-) diff --git a/mysql-test/suite/innodb/r/group_commit_crash.result b/mysql-test/suite/innodb/r/group_commit_crash.result index 5d5dffab33e..005049df281 100644 --- a/mysql-test/suite/innodb/r/group_commit_crash.result +++ b/mysql-test/suite/innodb/r/group_commit_crash.result @@ -1,4 +1,3 @@ -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); CREATE TABLE t1(a CHAR(255), b CHAR(255), c CHAR(255), diff --git a/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result b/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result index 542ce9d496e..846500ad2b1 100644 --- a/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result +++ b/mysql-test/suite/innodb/r/group_commit_crash_no_optimize_thread.result @@ -1,4 +1,3 @@ -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); CREATE TABLE t1(a CHAR(255), b CHAR(255), c CHAR(255), diff --git a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result index 3cc973ca3a3..ce13ad0978b 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-tempfile.result +++ b/mysql-test/suite/innodb/r/innodb-alter-tempfile.result @@ -4,10 +4,6 @@ # Temporary tablename will be unique. This makes sure that future # in-place ALTERs of the same table will not be blocked due to # temporary tablename. -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed -"); -call mtr.add_suppression("InnoDB: file read of space .* page .*"); -call mtr.add_suppression("InnoDB: Trying to recover it from the doublewrite buffer."); # Crash the server in ha_innobase::commit_inplace_alter_table() CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL) ENGINE=innodb; SET debug='d,innodb_alter_commit_crash_before_commit'; diff --git a/mysql-test/suite/innodb/r/innodb_bug14147491.result b/mysql-test/suite/innodb/r/innodb_bug14147491.result index bd3c388fae1..5ff6f652f9e 100644 --- a/mysql-test/suite/innodb/r/innodb_bug14147491.result +++ b/mysql-test/suite/innodb/r/innodb_bug14147491.result @@ -1,6 +1,5 @@ call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed.*"); CALL mtr.add_suppression("InnoDB: Error: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); -CALL mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); CALL mtr.add_suppression("InnoDB: Database page corruption on disk or a failed"); CALL mtr.add_suppression("InnoDB: Space .* file test/t1 read of page .*"); CALL mtr.add_suppression("InnoDB: You may have to recover from a backup."); diff --git a/mysql-test/suite/innodb/r/xa_recovery.result b/mysql-test/suite/innodb/r/xa_recovery.result index e65f702c488..f429808b8dd 100644 --- a/mysql-test/suite/innodb/r/xa_recovery.result +++ b/mysql-test/suite/innodb/r/xa_recovery.result @@ -1,4 +1,3 @@ -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); CREATE TABLE t1 (a INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); XA START 'x'; @@ -6,6 +5,7 @@ UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; call mtr.add_suppression("Found 1 prepared XA transactions"); +# Kill the server SELECT * FROM t1 LOCK IN SHARE MODE; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t1; diff --git a/mysql-test/suite/innodb/t/group_commit_crash.test b/mysql-test/suite/innodb/t/group_commit_crash.test index cad349819bd..7ad0d9d1e74 100644 --- a/mysql-test/suite/innodb/t/group_commit_crash.test +++ b/mysql-test/suite/innodb/t/group_commit_crash.test @@ -9,8 +9,6 @@ --source include/have_debug.inc --source include/have_log_bin.inc -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); - let $file_format_max=`SELECT @@innodb_file_format_max`; CREATE TABLE t1(a CHAR(255), b CHAR(255), diff --git a/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test b/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test index 8d1f460b64b..9dc2557e687 100644 --- a/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test +++ b/mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test @@ -9,8 +9,6 @@ --source include/have_debug.inc --source include/have_log_bin.inc -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); - let $file_format_max=`SELECT @@innodb_file_format_max`; CREATE TABLE t1(a CHAR(255), b CHAR(255), diff --git a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test index e1e736fc678..ec1ea35f1cf 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-tempfile.test +++ b/mysql-test/suite/innodb/t/innodb-alter-tempfile.test @@ -20,13 +20,6 @@ --echo # in-place ALTERs of the same table will not be blocked due to --echo # temporary tablename. -# As we intentionally crash below, there could be partially written -# pages that are then recovered from the doublewrite buffer -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed -"); -call mtr.add_suppression("InnoDB: file read of space .* page .*"); -call mtr.add_suppression("InnoDB: Trying to recover it from the doublewrite buffer."); - let datadir= `select @@datadir`; --let $_server_id= `SELECT @@server_id` diff --git a/mysql-test/suite/innodb/t/innodb_bug14147491.test b/mysql-test/suite/innodb/t/innodb_bug14147491.test index 16e88826c85..d48fa074147 100644 --- a/mysql-test/suite/innodb/t/innodb_bug14147491.test +++ b/mysql-test/suite/innodb/t/innodb_bug14147491.test @@ -21,7 +21,6 @@ source include/have_debug.inc; source include/not_windows.inc; CALL mtr.add_suppression("InnoDB: Error: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); -CALL mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); CALL mtr.add_suppression("InnoDB: Database page corruption on disk or a failed"); CALL mtr.add_suppression("InnoDB: Space .* file test/t1 read of page .*"); CALL mtr.add_suppression("InnoDB: You may have to recover from a backup."); diff --git a/mysql-test/suite/innodb/t/xa_recovery.test b/mysql-test/suite/innodb/t/xa_recovery.test index 32373d63d14..9f25e4d1f30 100644 --- a/mysql-test/suite/innodb/t/xa_recovery.test +++ b/mysql-test/suite/innodb/t/xa_recovery.test @@ -12,11 +12,6 @@ if (`select plugin_auth_version <= "5.6.24" from information_schema.plugins wher FLUSH TABLES; --enable_query_log -# -# We kill server belown with timeout 0 that is not fully safe -# -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); - CREATE TABLE t1 (a INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connect (con1,localhost,root); @@ -25,15 +20,8 @@ connection default; call mtr.add_suppression("Found 1 prepared XA transactions"); -# Kill and restart the server. --- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- shutdown_server 0 --- source include/wait_until_disconnected.inc - --- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- enable_reconnect --- source include/wait_until_connected_again.inc --- disable_reconnect +--source include/kill_mysqld.inc +--source include/start_mysqld.inc disconnect con1; connect (con1,localhost,root); diff --git a/mysql-test/suite/rpl/r/rpl_gtid_crash.result b/mysql-test/suite/rpl/r/rpl_gtid_crash.result index 0c2249f2dce..5f67901b7f5 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_crash.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_crash.result @@ -3,7 +3,6 @@ include/rpl_init.inc [topology=1->2] call mtr.add_suppression("Checking table:"); call mtr.add_suppression("client is using or hasn't closed the table properly"); call mtr.add_suppression("Table .* is marked as crashed and should be repaired"); -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); flush tables; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash.test b/mysql-test/suite/rpl/t/rpl_gtid_crash.test index df3ba9a3420..b81cbd38cd3 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_crash.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash.test @@ -12,11 +12,6 @@ call mtr.add_suppression("Checking table:"); call mtr.add_suppression("client is using or hasn't closed the table properly"); call mtr.add_suppression("Table .* is marked as crashed and should be repaired"); -# We have seen this warning a couple of times in Buildbot. Since we crash the -# server deliberately, it seems possible that we could in rare cases crash in -# the middle of a page write. The page is recovered from the doublewrite -# buffer ("[Note] InnoDB: Recovered the page from the doublewrite buffer."). -call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); flush tables; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 1cf856a731f..0b42e38a655 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -455,8 +455,11 @@ buf_dblwr_init_or_load_pages( os_file_write(path, file, page, source_page_no * UNIV_PAGE_SIZE, UNIV_PAGE_SIZE); - } else if (load_corrupt_pages) { - + } else if (load_corrupt_pages + && !buf_page_is_zeroes(page, FIL_PAGE_DATA)) { + /* Each valid page header must contain some + nonzero bytes, such as FIL_PAGE_OFFSET + or FIL_PAGE_LSN. */ recv_dblwr.add(page); } @@ -492,8 +495,6 @@ buf_dblwr_process() for (std::list::iterator i = recv_dblwr.pages.begin(); i != recv_dblwr.pages.end(); ++i, ++page_no_dblwr ) { - bool is_compressed = false; - page = *i; page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); space_id = mach_read_from_4(page + FIL_PAGE_SPACE_ID); @@ -501,139 +502,104 @@ buf_dblwr_process() if (!fil_tablespace_exists_in_mem(space_id)) { /* Maybe we have dropped the single-table tablespace and this page once belonged to it: do nothing */ - - } else if (!fil_check_adress_in_tablespace(space_id, - page_no)) { - ib_logf(IB_LOG_LEVEL_WARN, - "A page in the doublewrite buffer is not " - "within space bounds; space id %lu " - "page number %lu, page %lu in " - "doublewrite buf.", - (ulong) space_id, (ulong) page_no, - page_no_dblwr); - } else { - ulint zip_size = fil_space_get_zip_size(space_id); - - /* Read in the actual page from the file */ - fil_io(OS_FILE_READ, - true, - space_id, - zip_size, - page_no, - 0, - zip_size ? zip_size : UNIV_PAGE_SIZE, - read_buf, - NULL, - 0); - - /* Is page compressed ? */ - is_compressed = fil_page_is_compressed_encrypted(read_buf) | - fil_page_is_compressed(read_buf); - - /* If page was compressed, decompress it before we - check checksum. */ - if (is_compressed) { - fil_decompress_page(NULL, read_buf, UNIV_PAGE_SIZE, NULL, true); - } - - if (fil_space_verify_crypt_checksum(read_buf, zip_size)) { - /* page is encrypted and checksum is OK */ - } else if (buf_page_is_corrupted(true, read_buf, zip_size)) { - - fprintf(stderr, - "InnoDB: Warning: database page" - " corruption or a failed\n" - "InnoDB: file read of" - " space %lu page %lu.\n" - "InnoDB: Trying to recover it from" - " the doublewrite buffer.\n", - (ulong) space_id, (ulong) page_no); - - /* Is page compressed ? */ - is_compressed = fil_page_is_compressed_encrypted(page) | - fil_page_is_compressed(page); - - /* If page was compressed, decompress it before we - check checksum. */ - if (is_compressed) { - fil_decompress_page(NULL, page, UNIV_PAGE_SIZE, NULL, true); - } - - if (fil_space_verify_crypt_checksum(page, zip_size)) { - /* the doublewrite buffer page is encrypted and OK */ - } else if (buf_page_is_corrupted(true, - page, - zip_size)) { - fprintf(stderr, - "InnoDB: Dump of the page:\n"); - buf_page_print( - read_buf, zip_size, - BUF_PAGE_PRINT_NO_CRASH); - fprintf(stderr, - "InnoDB: Dump of" - " corresponding page" - " in doublewrite buffer:\n"); - buf_page_print( - page, zip_size, - BUF_PAGE_PRINT_NO_CRASH); - - fprintf(stderr, - "InnoDB: Also the page in the" - " doublewrite buffer" - " is corrupt.\n" - "InnoDB: Cannot continue" - " operation.\n" - "InnoDB: You can try to" - " recover the database" - " with the my.cnf\n" - "InnoDB: option:\n" - "InnoDB:" - " innodb_force_recovery=6\n"); - ut_error; - } - - /* Write the good page from the - doublewrite buffer to the intended - position */ - - fil_io(OS_FILE_WRITE, - true, - space_id, - zip_size, - page_no, - 0, - zip_size ? zip_size : UNIV_PAGE_SIZE, - page, - NULL, - 0); - - ib_logf(IB_LOG_LEVEL_INFO, - "Recovered the page from" - " the doublewrite buffer."); - - } else if (buf_page_is_zeroes(read_buf, zip_size)) { - - if (!buf_page_is_zeroes(page, zip_size) - && !buf_page_is_corrupted(true, page, - zip_size)) { - - /* Database page contained only - zeroes, while a valid copy is - available in dblwr buffer. */ - - fil_io(OS_FILE_WRITE, - true, - space_id, - zip_size, - page_no, - 0, - zip_size ? zip_size : UNIV_PAGE_SIZE, - page, - NULL, - 0); - } - } + continue; } + + if (!fil_check_adress_in_tablespace(space_id, page_no)) { + ib_logf(IB_LOG_LEVEL_WARN, + "A copy of page " ULINTPF ":" ULINTPF + " in the doublewrite buffer slot " ULINTPF + " is not within space bounds", + space_id, page_no, page_no_dblwr); + continue; + } + + ulint zip_size = fil_space_get_zip_size(space_id); + ut_ad(!buf_page_is_zeroes(page, zip_size)); + + /* Read in the actual page from the file */ + fil_io(OS_FILE_READ, + true, + space_id, + zip_size, + page_no, + 0, + zip_size ? zip_size : UNIV_PAGE_SIZE, + read_buf, + NULL, + 0); + + const bool is_all_zero = buf_page_is_zeroes( + read_buf, zip_size); + + if (is_all_zero) { + /* We will check if the copy in the + doublewrite buffer is valid. If not, we will + ignore this page (there should be redo log + records to initialize it). */ + } else { + if (fil_page_is_compressed_encrypted(read_buf) || + fil_page_is_compressed(read_buf)) { + /* Decompress the page before + validating the checksum. */ + fil_decompress_page( + NULL, read_buf, UNIV_PAGE_SIZE, + NULL, true); + } + + if (fil_space_verify_crypt_checksum( + read_buf, zip_size) + || !buf_page_is_corrupted( + true, read_buf, zip_size)) { + /* The page is good; there is no need + to consult the doublewrite buffer. */ + continue; + } + + /* We intentionally skip this message for + is_all_zero pages. */ + ib_logf(IB_LOG_LEVEL_INFO, + "Trying to recover page " ULINTPF ":" ULINTPF + " from the doublewrite buffer.", + space_id, page_no); + } + + /* Next, validate the doublewrite page. */ + if (fil_page_is_compressed_encrypted(page) || + fil_page_is_compressed(page)) { + /* Decompress the page before + validating the checksum. */ + fil_decompress_page( + NULL, page, UNIV_PAGE_SIZE, NULL, true); + } + + if (!fil_space_verify_crypt_checksum(page, zip_size) + && buf_page_is_corrupted(true, page, zip_size)) { + if (!is_all_zero) { + ib_logf(IB_LOG_LEVEL_WARN, + "A doublewrite copy of page " + ULINTPF ":" ULINTPF " is corrupted.", + space_id, page_no); + } + /* Theoretically we could have another good + copy for this page in the doublewrite + buffer. If not, we will report a fatal error + for a corrupted page somewhere else if that + page was truly needed. */ + continue; + } + + /* Write the good page from the doublewrite buffer to + the intended position. */ + + fil_io(OS_FILE_WRITE, true, space_id, zip_size, page_no, 0, + zip_size ? zip_size : UNIV_PAGE_SIZE, + page, NULL, 0); + + ib_logf(IB_LOG_LEVEL_INFO, + "Recovered page " ULINTPF ":" ULINTPF " from" + " the doublewrite buffer.", + space_id, page_no); } ut_free(unaligned_read_buf); diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc index 7f6b6caee9d..9c7eea6410a 100644 --- a/storage/xtradb/buf/buf0dblwr.cc +++ b/storage/xtradb/buf/buf0dblwr.cc @@ -455,8 +455,11 @@ buf_dblwr_init_or_load_pages( os_file_write(path, file, page, source_page_no * UNIV_PAGE_SIZE, UNIV_PAGE_SIZE); - } else if (load_corrupt_pages) { - + } else if (load_corrupt_pages + && !buf_page_is_zeroes(page, FIL_PAGE_DATA)) { + /* Each valid page header must contain some + nonzero bytes, such as FIL_PAGE_OFFSET + or FIL_PAGE_LSN. */ recv_dblwr.add(page); } @@ -492,8 +495,6 @@ buf_dblwr_process() for (std::list::iterator i = recv_dblwr.pages.begin(); i != recv_dblwr.pages.end(); ++i, ++page_no_dblwr ) { - bool is_compressed = false; - page = *i; page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); space_id = mach_read_from_4(page + FIL_PAGE_SPACE_ID); @@ -501,138 +502,104 @@ buf_dblwr_process() if (!fil_tablespace_exists_in_mem(space_id)) { /* Maybe we have dropped the single-table tablespace and this page once belonged to it: do nothing */ - - } else if (!fil_check_adress_in_tablespace(space_id, - page_no)) { - ib_logf(IB_LOG_LEVEL_WARN, - "A page in the doublewrite buffer is not " - "within space bounds; space id %lu " - "page number %lu, page %lu in " - "doublewrite buf.", - (ulong) space_id, (ulong) page_no, - page_no_dblwr); - } else { - ulint zip_size = fil_space_get_zip_size(space_id); - - /* Read in the actual page from the file */ - fil_io(OS_FILE_READ, - true, - space_id, - zip_size, - page_no, - 0, - zip_size ? zip_size : UNIV_PAGE_SIZE, - read_buf, - NULL, - 0); - - /* Is page compressed ? */ - is_compressed = fil_page_is_compressed_encrypted(read_buf) | - fil_page_is_compressed(read_buf); - - /* If page was compressed, decompress it before we - check checksum. */ - if (is_compressed) { - fil_decompress_page(NULL, read_buf, UNIV_PAGE_SIZE, NULL, true); - } - - if (fil_space_verify_crypt_checksum(read_buf, zip_size)) { - /* page is encrypted and checksum is OK */ - } else if (buf_page_is_corrupted(true, read_buf, zip_size)) { - - fprintf(stderr, - "InnoDB: Database page" - " corruption or a failed\n" - "InnoDB: file read of" - " space %lu page %lu.\n" - "InnoDB: Trying to recover it from" - " the doublewrite buffer.\n", - (ulong) space_id, (ulong) page_no); - - /* Is page compressed ? */ - is_compressed = fil_page_is_compressed_encrypted(page) | - fil_page_is_compressed(page); - - /* If page was compressed, decompress it before we - check checksum. */ - if (is_compressed) { - fil_decompress_page(NULL, page, UNIV_PAGE_SIZE, NULL, true); - } - - if (fil_space_verify_crypt_checksum(page, zip_size)) { - /* the doublewrite buffer page is encrypted and OK */ - } else if (buf_page_is_corrupted(true, - page, - zip_size)) { - fprintf(stderr, - "InnoDB: Dump of the page:\n"); - buf_page_print( - read_buf, zip_size, - BUF_PAGE_PRINT_NO_CRASH); - fprintf(stderr, - "InnoDB: Dump of" - " corresponding page" - " in doublewrite buffer:\n"); - buf_page_print( - page, zip_size, - BUF_PAGE_PRINT_NO_CRASH); - - fprintf(stderr, - "InnoDB: Also the page in the" - " doublewrite buffer" - " is corrupt.\n" - "InnoDB: Cannot continue" - " operation.\n" - "InnoDB: You can try to" - " recover the database" - " with the my.cnf\n" - "InnoDB: option:\n" - "InnoDB:" - " innodb_force_recovery=6\n"); - ut_error; - } - - /* Write the good page from the - doublewrite buffer to the intended - position */ - - fil_io(OS_FILE_WRITE, - true, - space_id, - zip_size, - page_no, - 0, - zip_size ? zip_size : UNIV_PAGE_SIZE, - page, - NULL, - 0); - - ib_logf(IB_LOG_LEVEL_INFO, - "Recovered the page from" - " the doublewrite buffer."); - - } else if (buf_page_is_zeroes(read_buf, zip_size)) { - - if (!buf_page_is_zeroes(page, zip_size) - && !buf_page_is_corrupted(true, page, - zip_size)) { - - /* Database page contained only - zeroes, while a valid copy is - available in dblwr buffer. */ - - fil_io(OS_FILE_WRITE, - true, - space_id, - zip_size, - page_no, 0, - zip_size ? zip_size : UNIV_PAGE_SIZE, - page, - NULL, - 0); - } - } + continue; } + + if (!fil_check_adress_in_tablespace(space_id, page_no)) { + ib_logf(IB_LOG_LEVEL_WARN, + "A copy of page " ULINTPF ":" ULINTPF + " in the doublewrite buffer slot " ULINTPF + " is not within space bounds", + space_id, page_no, page_no_dblwr); + continue; + } + + ulint zip_size = fil_space_get_zip_size(space_id); + ut_ad(!buf_page_is_zeroes(page, zip_size)); + + /* Read in the actual page from the file */ + fil_io(OS_FILE_READ, + true, + space_id, + zip_size, + page_no, + 0, + zip_size ? zip_size : UNIV_PAGE_SIZE, + read_buf, + NULL, + 0); + + const bool is_all_zero = buf_page_is_zeroes( + read_buf, zip_size); + + if (is_all_zero) { + /* We will check if the copy in the + doublewrite buffer is valid. If not, we will + ignore this page (there should be redo log + records to initialize it). */ + } else { + if (fil_page_is_compressed_encrypted(read_buf) || + fil_page_is_compressed(read_buf)) { + /* Decompress the page before + validating the checksum. */ + fil_decompress_page( + NULL, read_buf, UNIV_PAGE_SIZE, + NULL, true); + } + + if (fil_space_verify_crypt_checksum( + read_buf, zip_size) + || !buf_page_is_corrupted( + true, read_buf, zip_size)) { + /* The page is good; there is no need + to consult the doublewrite buffer. */ + continue; + } + + /* We intentionally skip this message for + is_all_zero pages. */ + ib_logf(IB_LOG_LEVEL_INFO, + "Trying to recover page " ULINTPF ":" ULINTPF + " from the doublewrite buffer.", + space_id, page_no); + } + + /* Next, validate the doublewrite page. */ + if (fil_page_is_compressed_encrypted(page) || + fil_page_is_compressed(page)) { + /* Decompress the page before + validating the checksum. */ + fil_decompress_page( + NULL, page, UNIV_PAGE_SIZE, NULL, true); + } + + if (!fil_space_verify_crypt_checksum(page, zip_size) + && buf_page_is_corrupted(true, page, zip_size)) { + if (!is_all_zero) { + ib_logf(IB_LOG_LEVEL_WARN, + "A doublewrite copy of page " + ULINTPF ":" ULINTPF " is corrupted.", + space_id, page_no); + } + /* Theoretically we could have another good + copy for this page in the doublewrite + buffer. If not, we will report a fatal error + for a corrupted page somewhere else if that + page was truly needed. */ + continue; + } + + /* Write the good page from the doublewrite buffer to + the intended position. */ + + fil_io(OS_FILE_WRITE, true, space_id, zip_size, page_no, 0, + zip_size ? zip_size : UNIV_PAGE_SIZE, + page, NULL, 0); + + ib_logf(IB_LOG_LEVEL_INFO, + "Recovered page " ULINTPF ":" ULINTPF " from" + " the doublewrite buffer.", + space_id, page_no); } ut_free(unaligned_read_buf); From ab1e6fefd869242d962cb91a006f37bb9ad534a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 14 Jan 2017 00:13:16 +0200 Subject: [PATCH 075/167] MDEV-11623 MariaDB 10.1 fails to start datadir created with MariaDB 10.0/MySQL 5.6 using innodb-page-size!=16K The storage format of FSP_SPACE_FLAGS was accidentally broken already in MariaDB 10.1.0. This fix is bringing the format in line with other MySQL and MariaDB release series. Please refer to the comments that were added to fsp0fsp.h for details. This is an INCOMPATIBLE CHANGE that affects users of page_compression and non-default innodb_page_size. Upgrading to this release will correct the flags in the data files. If you want to downgrade to earlier MariaDB 10.1.x, please refer to the test innodb.101_compatibility how to reset the FSP_SPACE_FLAGS in the files. NOTE: MariaDB 10.1.0 to 10.1.20 can misinterpret uncompressed data files with innodb_page_size=4k or 64k as compressed innodb_page_size=16k files, and then probably fail when trying to access the pages. See the comments in the function fsp_flags_convert_from_101() for detailed analysis. Move PAGE_COMPRESSION to FSP_SPACE_FLAGS bit position 16. In this way, compressed innodb_page_size=16k tablespaces will not be mistaken for uncompressed ones by MariaDB 10.1.0 to 10.1.20. Derive PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES and DATA_DIR from the dict_table_t::flags when the table is available, in fil_space_for_table_exists_in_mem() or fil_open_single_table_tablespace(). During crash recovery, fil_load_single_table_tablespace() will use innodb_compression_level for the PAGE_COMPRESSION_LEVEL. FSP_FLAGS_MEM_MASK: A bitmap of the memory-only fil_space_t::flags that are not to be written to FSP_SPACE_FLAGS. Currently, these will include PAGE_COMPRESSION_LEVEL, ATOMIC_WRITES and DATA_DIR. Introduce the macro FSP_FLAGS_PAGE_SSIZE(). We only support one innodb_page_size for the whole instance. When creating a dummy tablespace for the redo log, use fil_space_t::flags=0. The flags are never written to the redo log files. Remove many FSP_FLAGS_SET_ macros. dict_tf_verify_flags(): Remove. This is basically only duplicating the logic of dict_tf_to_fsp_flags(), used in a debug assertion. fil_space_t::mark: Remove. This flag was not used for anything. fil_space_for_table_exists_in_mem(): Remove the unnecessary parameter mark_space, and add a parameter for table flags. Check that fil_space_t::flags match the table flags, and adjust the (memory-only) flags based on the table flags. fil_node_open_file(): Remove some redundant or unreachable conditions, do not use stderr for output, and avoid unnecessary server aborts. fil_user_tablespace_restore_page(): Convert the flags, so that the correct page_size will be used when restoring a page from the doublewrite buffer. fil_space_get_page_compressed(), fsp_flags_is_page_compressed(): Remove. It suffices to have fil_space_is_page_compressed(). FSP_FLAGS_WIDTH_DATA_DIR, FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL, FSP_FLAGS_WIDTH_ATOMIC_WRITES: Remove, because these flags do not exist in the FSP_SPACE_FLAGS but only in memory. fsp_flags_try_adjust(): New function, to adjust the FSP_SPACE_FLAGS in page 0. Called by fil_open_single_table_tablespace(), fil_space_for_table_exists_in_mem(), innobase_start_or_create_for_mysql() except if --innodb-read-only is active. fsp_flags_is_valid(ulint): Reimplement from the scratch, with accurate comments. Do not display any details of detected inconsistencies, because the output could be confusing when dealing with MariaDB 10.1.x data files. fsp_flags_convert_from_101(ulint): Convert flags from buggy MariaDB 10.1.x format, or return ULINT_UNDEFINED if the flags cannot be in MariaDB 10.1.x format. fsp_flags_match(): Check the flags when probing files. Implemented based on fsp_flags_is_valid() and fsp_flags_convert_from_101(). dict_check_tablespaces_and_store_max_id(): Do not access the page after committing the mini-transaction. IMPORT TABLESPACE fixes: AbstractCallback::init(): Convert the flags. FetchIndexRootPages::operator(): Check that the tablespace flags match the table flags. Do not attempt to convert tablespace flags to table flags, because the conversion would necessarily be lossy. PageConverter::update_header(): Write back the correct flags. This takes care of the flags in IMPORT TABLESPACE. --- .../suite/innodb/include/ibd_convert.pl | 25 + .../suite/innodb/r/101_compatibility.result | 48 ++ mysql-test/suite/innodb/r/doublewrite.result | 2 + .../innodb/r/innodb-wl5522-debug-zip.result | 5 +- .../suite/innodb/t/101_compatibility.test | 101 ++++ mysql-test/suite/innodb/t/doublewrite.test | 42 +- .../innodb/t/innodb-wl5522-debug-zip.test | 3 +- storage/innobase/buf/buf0dblwr.cc | 15 + storage/innobase/dict/dict0load.cc | 20 +- storage/innobase/fil/fil0fil.cc | 400 +++++++--------- storage/innobase/fsp/fsp0fsp.cc | 3 +- storage/innobase/include/dict0dict.ic | 42 +- storage/innobase/include/dict0pagecompress.h | 13 +- storage/innobase/include/dict0pagecompress.ic | 88 +--- storage/innobase/include/fil0fil.h | 41 +- storage/innobase/include/fil0pagecompress.h | 13 +- storage/innobase/include/fsp0fsp.h | 428 +++++++++++++---- storage/innobase/include/fsp0fsp.ic | 153 +------ storage/innobase/include/fsp0pagecompress.h | 11 +- storage/innobase/include/fsp0pagecompress.ic | 28 +- storage/innobase/row/row0import.cc | 94 ++-- storage/innobase/row/row0mysql.cc | 11 +- storage/innobase/srv/srv0start.cc | 18 +- storage/xtradb/buf/buf0dblwr.cc | 15 + storage/xtradb/dict/dict0load.cc | 20 +- storage/xtradb/fil/fil0fil.cc | 399 +++++++--------- storage/xtradb/fsp/fsp0fsp.cc | 3 +- storage/xtradb/include/dict0dict.ic | 42 +- storage/xtradb/include/dict0pagecompress.h | 13 +- storage/xtradb/include/dict0pagecompress.ic | 88 +--- storage/xtradb/include/fil0fil.h | 41 +- storage/xtradb/include/fil0pagecompress.h | 13 +- storage/xtradb/include/fsp0fsp.h | 431 +++++++++++++----- storage/xtradb/include/fsp0fsp.ic | 153 +------ storage/xtradb/include/fsp0pagecompress.h | 11 +- storage/xtradb/include/fsp0pagecompress.ic | 28 +- storage/xtradb/row/row0import.cc | 94 ++-- storage/xtradb/row/row0mysql.cc | 11 +- storage/xtradb/srv/srv0start.cc | 18 +- 39 files changed, 1485 insertions(+), 1499 deletions(-) create mode 100644 mysql-test/suite/innodb/include/ibd_convert.pl create mode 100644 mysql-test/suite/innodb/r/101_compatibility.result create mode 100644 mysql-test/suite/innodb/t/101_compatibility.test diff --git a/mysql-test/suite/innodb/include/ibd_convert.pl b/mysql-test/suite/innodb/include/ibd_convert.pl new file mode 100644 index 00000000000..aba742ac649 --- /dev/null +++ b/mysql-test/suite/innodb/include/ibd_convert.pl @@ -0,0 +1,25 @@ +#!/usr/bin/perl +# Convert tablespace flags to the format understood by MariaDB 10.1.0..10.1.20, +# with the assumption that the flags were correct. + +sub convert_to_mariadb_101 +{ + my ($file, $page_size) = @_; + open(FILE, "+<", $file) or die "Unable to open $file\n"; + sysread(FILE, $_, $page_size)==$page_size||die "Unable to read $file\n"; + sysseek(FILE, 0, 0)||die "Unable to seek $file\n"; + + # FIL_PAGE_DATA + FSP_SPACE_FLAGS = 38 + 16 = 54 bytes from the start + my($flags) = unpack "x[54]N"; + my $badflags = ($flags & 0x3f); + my $compression_level=6; + $badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16); + $badflags |= ($flags & 15 << 6) << 7; # PAGE_SSIZE + + substr ($_, 54, 4) = pack("N", $badflags); + # Replace the innodb_checksum_algorithm=none checksum + substr ($_, 0, 4) = pack("N", 0xdeadbeef); + substr ($_, $page_size - 8, 4) = pack("N", 0xdeadbeef); + syswrite(FILE, $_, $page_size)==$page_size||die "Unable to write $file\n"; + close(FILE); +} diff --git a/mysql-test/suite/innodb/r/101_compatibility.result b/mysql-test/suite/innodb/r/101_compatibility.result new file mode 100644 index 00000000000..f9cc8c288ca --- /dev/null +++ b/mysql-test/suite/innodb/r/101_compatibility.result @@ -0,0 +1,48 @@ +# +# MDEV-11623 MariaDB 10.1 fails to start datadir created with +# MariaDB 10.0/MySQL 5.6 using innodb-page-size!=16K +# +call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of tablespace"); +SET GLOBAL innodb_file_per_table=1; +SET GLOBAL innodb_file_format=Barracuda; +CREATE TABLE tr(a INT)ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT; +CREATE TABLE td(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +CREATE TABLE tz(a INT)ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +CREATE TABLE tdd(a INT) ENGINE=InnoDB, DATA DIRECTORY='MYSQL_TMP_DIR'; +CREATE TABLE tp(a INT) ENGINE=InnoDB page_compressed=1; +CREATE TABLE ti(a INT) ENGINE=InnoDB; +FLUSH TABLES ti FOR EXPORT; +backup: ti +UNLOCK TABLES; +ALTER TABLE ti DISCARD TABLESPACE; +restore: ti .ibd and .cfg files +ALTER TABLE ti IMPORT TABLESPACE; +BEGIN; +INSERT INTO tr VALUES(1); +INSERT INTO tc VALUES(1); +INSERT INTO td VALUES(1); +INSERT INTO tz VALUES(1); +INSERT INTO tdd VALUES(1); +INSERT INTO tp VALUES(1); +INSERT INTO ti VALUES(1); +# Kill the server +CHECK TABLE tr,tc,td,tz,tdd,tp,ti; +Table Op Msg_type Msg_text +test.tr check status OK +test.tc check status OK +test.td check status OK +test.tz check status OK +test.tdd check status OK +test.tp check status OK +test.ti check status OK +CHECK TABLE tr,tc,td,tz,tdd,tp,ti; +Table Op Msg_type Msg_text +test.tr check status OK +test.tc check status OK +test.td check status OK +test.tz check status OK +test.tdd check status OK +test.tp check status OK +test.ti check status OK +DROP TABLE tr,tc,td,tz,tdd,tp,ti; diff --git a/mysql-test/suite/innodb/r/doublewrite.result b/mysql-test/suite/innodb/r/doublewrite.result index aa96a5f2d93..6b913f49972 100644 --- a/mysql-test/suite/innodb/r/doublewrite.result +++ b/mysql-test/suite/innodb/r/doublewrite.result @@ -39,6 +39,8 @@ set global innodb_buf_flush_list_now = 1; # Kill the server # Make the first page (page_no=0) of the user tablespace # full of zeroes. +# +# MDEV-11623: Use old FSP_SPACE_FLAGS in the doublewrite buffer. check table t1; Table Op Msg_type Msg_text test.t1 check status OK diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result index 6231a875804..58721a8732a 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result @@ -1,4 +1,5 @@ -call mtr.add_suppression("InnoDB: Page for tablespace .* "); +call mtr.add_suppression("InnoDB: Page for tablespace "); +call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS=0x"); FLUSH TABLES; SET GLOBAL innodb_file_per_table = 1; SELECT @@innodb_file_per_table; @@ -565,7 +566,7 @@ ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure"; ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; -ERROR HY000: Internal error: Cannot reset LSNs in table '"test_wl5522"."t1"' : Unsupported +ERROR HY000: Internal error: Cannot reset LSNs in table '"test_wl5522"."t1"' : Data structure corruption SET SESSION debug_dbug="-d,fsp_flags_is_valid_failure"; DROP TABLE test_wl5522.t1; unlink: t1.ibd diff --git a/mysql-test/suite/innodb/t/101_compatibility.test b/mysql-test/suite/innodb/t/101_compatibility.test new file mode 100644 index 00000000000..125a559c1cb --- /dev/null +++ b/mysql-test/suite/innodb/t/101_compatibility.test @@ -0,0 +1,101 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc + +-- echo # +-- echo # MDEV-11623 MariaDB 10.1 fails to start datadir created with +-- echo # MariaDB 10.0/MySQL 5.6 using innodb-page-size!=16K +-- echo # + +# This is actually testing the opposite: starting the fixed 10.1 with +# buggy 10.1 files (by manually converting the flags in the files). + +call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of tablespace"); +SET GLOBAL innodb_file_per_table=1; +SET GLOBAL innodb_file_format=Barracuda; +let INNODB_PAGE_SIZE=`select @@innodb_page_size`; +let MYSQLD_DATADIR=`select @@datadir`; + +CREATE TABLE tr(a INT)ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT; +CREATE TABLE td(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +--disable_warnings +CREATE TABLE tz(a INT)ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +--enable_warnings + +--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR +EVAL CREATE TABLE tdd(a INT) ENGINE=InnoDB, DATA DIRECTORY='$MYSQL_TMP_DIR'; + +CREATE TABLE tp(a INT) ENGINE=InnoDB page_compressed=1; +CREATE TABLE ti(a INT) ENGINE=InnoDB; +FLUSH TABLES ti FOR EXPORT; +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_backup_tablespaces("test", "ti"); +EOF +UNLOCK TABLES; +ALTER TABLE ti DISCARD TABLESPACE; +perl; +do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl"; +ib_discard_tablespaces("test", "ti"); +ib_restore_tablespaces("test", "ti"); +do "$ENV{MTR_SUITE_DIR}/include/ibd_convert.pl"; +my $ps = $ENV{INNODB_PAGE_SIZE}; +my $dd = $ENV{MYSQLD_DATADIR}; +convert_to_mariadb_101("$dd/test/ti.ibd", $ps); +EOF + +ALTER TABLE ti IMPORT TABLESPACE; + +BEGIN; +INSERT INTO tr VALUES(1); +INSERT INTO tc VALUES(1); +INSERT INTO td VALUES(1); +INSERT INTO tz VALUES(1); +INSERT INTO tdd VALUES(1); +INSERT INTO tp VALUES(1); +INSERT INTO ti VALUES(1); + +--source include/kill_mysqld.inc + +perl; +do "$ENV{MTR_SUITE_DIR}/include/ibd_convert.pl"; +my $ps = $ENV{INNODB_PAGE_SIZE}; +my $dd = $ENV{MYSQLD_DATADIR}; + +convert_to_mariadb_101("$dd/ibdata1", $ps); +convert_to_mariadb_101("$dd/test/tr.ibd", $ps); +convert_to_mariadb_101("$dd/test/tc.ibd", $ps); +convert_to_mariadb_101("$dd/test/td.ibd", $ps); +convert_to_mariadb_101("$dd/test/tz.ibd", 1024) if $ps<32768; +convert_to_mariadb_101("$dd/test/tp.ibd", $ps); +convert_to_mariadb_101("$dd/test/ti.ibd", $ps); +convert_to_mariadb_101("$ENV{MYSQL_TMP_DIR}/test/tdd.ibd", $ps); +EOF + +--source include/start_mysqld.inc +CHECK TABLE tr,tc,td,tz,tdd,tp,ti; +--source include/shutdown_mysqld.inc + +perl; +do "$ENV{MTR_SUITE_DIR}/include/ibd_convert.pl"; +my $ps = $ENV{INNODB_PAGE_SIZE}; +my $dd = $ENV{MYSQLD_DATADIR}; + +convert_to_mariadb_101("$dd/ibdata1", $ps); +convert_to_mariadb_101("$dd/test/tr.ibd", $ps); +convert_to_mariadb_101("$dd/test/tc.ibd", $ps); +convert_to_mariadb_101("$dd/test/td.ibd", $ps); +convert_to_mariadb_101("$dd/test/tz.ibd", 1024) if $ps<32768; +convert_to_mariadb_101("$dd/test/tp.ibd", $ps); +convert_to_mariadb_101("$dd/test/ti.ibd", $ps); +convert_to_mariadb_101("$ENV{MYSQL_TMP_DIR}/test/tdd.ibd", $ps); +EOF + +--let $restart_parameters=--innodb-read-only +--source include/start_mysqld.inc +CHECK TABLE tr,tc,td,tz,tdd,tp,ti; +--source include/shutdown_mysqld.inc + +--let $restart_parameters= +--source include/start_mysqld.inc +DROP TABLE tr,tc,td,tz,tdd,tp,ti; diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 56cc88f5590..245b4e1a676 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -17,7 +17,7 @@ call mtr.add_suppression("space header page consists of zero bytes.*test.t1"); call mtr.add_suppression("checksum mismatch in tablespace.*test.t1"); call mtr.add_suppression("Current page size .* != page size on page"); call mtr.add_suppression("innodb-page-size mismatch in tablespace.*test.t1"); -call mtr.add_suppression("Database page corruption"); +call mtr.add_suppression("Trying to recover page.*from the doublewrite buffer"); --enable_query_log let INNODB_PAGE_SIZE=`select @@innodb_page_size`; @@ -65,14 +65,48 @@ set global innodb_buf_flush_list_now = 1; --echo # Make the first page (page_no=0) of the user tablespace --echo # full of zeroes. +--echo # +--echo # MDEV-11623: Use old FSP_SPACE_FLAGS in the doublewrite buffer. + perl; use IO::Handle; my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd"; +my $page_size = $ENV{INNODB_PAGE_SIZE}; +my $page; open(FILE, "+<", $fname) or die; -FILE->autoflush(1); -binmode FILE; -print FILE chr(0) x ($ENV{'INNODB_PAGE_SIZE'}); +sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $file\n"; +sysseek(FILE, 0, 0)||die "Unable to seek $file\n"; +die unless syswrite(FILE, chr(0) x $page_size, $page_size) == $page_size; close FILE; + +open(FILE, "+<", "$ENV{MYSQLD_DATADIR}ibdata1")||die "cannot open ibdata1\n"; +sysseek(FILE, 6 * $page_size - 190, 0)||die "Unable to seek ibdata1\n"; +sysread(FILE, $_, 12) == 12||die "Unable to read TRX_SYS\n"; +my($magic,$d1,$d2)=unpack "NNN"; +die "magic=$magic, $d1, $d2\n" unless $magic == 536853855 && $d2 >= $d1 + 64; +sysseek(FILE, $d1 * $page_size, 0)||die "Unable to seek ibdata1\n"; +# Find the page in the doublewrite buffer +for (my $d = $d1; $d < $d2 + 64; $d++) +{ + sysread(FILE, $_, $page_size)==$page_size||die "Cannot read doublewrite\n"; + next unless $_ eq $page; + sysseek(FILE, $d * $page_size, 0)||die "Unable to seek ibdata1\n"; + # Write buggy MariaDB 10.1.x FSP_SPACE_FLAGS to the doublewrite buffer + my($flags) = unpack "x[54]N"; + my $badflags = ($flags & 0x3f); + my $compression_level=6; + $badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16); + $badflags |= ($flags & 15 << 6) << 7; # PAGE_SSIZE + + substr ($_, 54, 4) = pack("N", $badflags); + # Replace the innodb_checksum_algorithm=none checksum + substr ($_, 0, 4) = pack("N", 0xdeadbeef); + substr ($_, $page_size - 8, 4) = pack("N", 0xdeadbeef); + syswrite(FILE, $_, $page_size)==$page_size||die "Unable to write $file\n"; + close(FILE); + exit 0; +} +die "Did not find the page in the doublewrite buffer ($d1,$d2)\n"; EOF --source include/start_mysqld.inc diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test index bc3edbb2643..0bfe67c06bc 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test @@ -17,7 +17,8 @@ # allow test to run only when innodb-page-size=16 --source include/have_innodb_16k.inc -call mtr.add_suppression("InnoDB: Page for tablespace .* "); +call mtr.add_suppression("InnoDB: Page for tablespace "); +call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS=0x"); FLUSH TABLES; let MYSQLD_DATADIR =`SELECT @@datadir`; diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 0b42e38a655..e49185f6a1f 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -589,6 +589,21 @@ buf_dblwr_process() continue; } + if (page_no == 0) { + /* Check the FSP_SPACE_FLAGS. */ + ulint flags = fsp_header_get_flags(page); + if (!fsp_flags_is_valid(flags) + && fsp_flags_convert_from_101(flags) + == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_WARN, + "Ignoring a doublewrite copy of page " + ULINTPF ":0 due to invalid flags 0x%x", + space_id, int(flags)); + continue; + } + /* The flags on the page should be converted later. */ + } + /* Write the good page from the doublewrite buffer to the intended position. */ diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 0ab25ee1eac..0f9f4f153f5 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1052,8 +1052,6 @@ loop: btr_pcur_store_position(&pcur, &mtr); - mtr_commit(&mtr); - /* For tables created with old versions of InnoDB, SYS_TABLES.MIX_LEN may contain garbage. Such tables would always be in ROW_FORMAT=REDUNDANT. Pretend that @@ -1087,16 +1085,19 @@ loop: if (space_id == 0) { /* The system tablespace always exists. */ ut_ad(!discarded); - goto next_tablespace; + mem_free(name); + goto loop; } + mtr_commit(&mtr); + switch (dict_check) { case DICT_CHECK_ALL_LOADED: /* All tablespaces should have been found in fil_load_single_table_tablespaces(). */ if (fil_space_for_table_exists_in_mem( - space_id, name, TRUE, !(is_temp || discarded), - false, NULL, 0) + space_id, name, !(is_temp || discarded), + false, NULL, 0, flags) && !(is_temp || discarded)) { /* If user changes the path of .ibd files in *.isl files before doing crash recovery , @@ -1128,8 +1129,8 @@ loop: /* Some tablespaces may have been opened in trx_resurrect_table_locks(). */ if (fil_space_for_table_exists_in_mem( - space_id, name, FALSE, FALSE, - false, NULL, 0)) { + space_id, name, false, + false, NULL, 0, flags)) { break; } /* fall through */ @@ -1191,7 +1192,6 @@ loop: max_space_id = space_id; } -next_tablespace: mem_free(name); mtr_start(&mtr); @@ -2382,8 +2382,8 @@ err_exit: table->ibd_file_missing = TRUE; } else if (!fil_space_for_table_exists_in_mem( - table->space, name, FALSE, FALSE, true, heap, - table->id)) { + table->space, name, false, true, heap, + table->id, table->flags)) { if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) { /* Do not bother to retry opening temporary tables. */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 1e8b2be6f01..fe6a2922b35 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. -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 @@ -596,10 +596,7 @@ fil_node_open_file( ibool success; byte* buf2; byte* page; - ulint space_id; - ulint flags=0; ulint page_size; - ulint atomic_writes=0; ut_ad(mutex_own(&(system->mutex))); ut_a(node->n_pending == 0); @@ -621,8 +618,6 @@ fil_node_open_file( /* The following call prints an error message */ os_file_get_last_error(true); - ut_print_timestamp(stderr); - ib_logf(IB_LOG_LEVEL_WARN, "InnoDB: Error: cannot " "open %s\n. InnoDB: Have you deleted .ibd " "files under a running mysqld server?\n", @@ -648,17 +643,13 @@ fil_node_open_file( ut_a(fil_is_user_tablespace_id(space->id)); if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { - fprintf(stderr, - "InnoDB: Error: the size of single-table" - " tablespace file %s\n" - "InnoDB: is only " UINT64PF "," - " should be at least %lu!\n", - node->name, - size_bytes, - (ulong) (FIL_IBD_FILE_INITIAL_SIZE - * UNIV_PAGE_SIZE)); - - ut_a(0); + ib_logf(IB_LOG_LEVEL_ERROR, + "The size of the file %s is only " UINT64PF + " bytes, should be at least " ULINTPF, + node->name, size_bytes, + FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE); + os_file_close(node->handle); + return(false); } /* Read the first page of the tablespace */ @@ -671,78 +662,34 @@ fil_node_open_file( success = os_file_read(node->handle, page, 0, UNIV_PAGE_SIZE); srv_stats.page0_read.add(1); - space_id = fsp_header_get_space_id(page); - flags = fsp_header_get_flags(page); - - page_size = fsp_flags_get_page_size(flags); - atomic_writes = fsp_flags_get_atomic_writes(flags); - + const ulint space_id = fsp_header_get_space_id(page); + ulint flags = fsp_header_get_flags(page); ut_free(buf2); - - /* Close the file now that we have read the space id from it */ - os_file_close(node->handle); + if (!fsp_flags_is_valid(flags)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Expected tablespace flags 0x%x" + " but found 0x%x in the file %s", + int(space->flags), int(flags), + node->name); + return(false); + } + + flags = cflags; + } + + page_size = fsp_flags_get_page_size(flags); + if (UNIV_UNLIKELY(space_id != space->id)) { - fprintf(stderr, - "InnoDB: Error: tablespace id is %lu" - " in the data dictionary\n" - "InnoDB: but in file %s it is %lu!\n", + ib_logf(IB_LOG_LEVEL_ERROR, + "tablespace id is " ULINTPF " in the data dictionary" + " but in file %s it is " ULINTPF "!\n", space->id, node->name, space_id); - - ut_error; - } - - if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED - || space_id == 0)) { - fprintf(stderr, - "InnoDB: Error: tablespace id %lu" - " in file %s is not sensible\n", - (ulong) space_id, node->name); - - ut_error; - } - - if (UNIV_UNLIKELY(fsp_flags_get_page_size(space->flags) - != page_size)) { - fprintf(stderr, - "InnoDB: Error: tablespace file %s" - " has page size 0x%lx\n" - "InnoDB: but the data dictionary" - " expects page size 0x%lx!\n", - node->name, flags, - fsp_flags_get_page_size(space->flags)); - - ut_error; - } - - if (UNIV_UNLIKELY(space->flags != flags)) { - ulint sflags = (space->flags & ~FSP_FLAGS_MASK_DATA_DIR); - ulint fflags = (flags & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - - /* DATA_DIR option is on different place on MariaDB - compared to MySQL. If this is the difference. Fix - it. */ - - if (sflags == fflags) { - fprintf(stderr, - "InnoDB: Warning: Table flags 0x%lx" - " in the data dictionary but in file %s are 0x%lx!\n" - " Temporally corrected because DATA_DIR option to 0x%lx.\n", - space->flags, node->name, flags, space->flags); - - flags = space->flags; - } - - if (!dict_tf_verify_flags(space->flags, flags)) { - fprintf(stderr, - "InnoDB: Error: table flags are 0x%lx" - " in the data dictionary\n" - "InnoDB: but the flags in file %s are 0x%lx!\n", - space->flags, node->name, flags); - ut_error; - } + return(false); } if (size_bytes >= (1024*1024)) { @@ -764,7 +711,7 @@ add_size: space->size += node->size; } - atomic_writes = fsp_flags_get_atomic_writes(space->flags); + ulint atomic_writes = fsp_flags_get_atomic_writes(space->flags); /* printf("Opening file %s\n", node->name); */ @@ -1534,7 +1481,6 @@ fil_space_create( fil_system->tablespace_version++; space->tablespace_version = fil_system->tablespace_version; - space->mark = FALSE; if (purpose == FIL_TABLESPACE && !recv_recovery_on && id > fil_system->max_assigned_id) { @@ -2273,27 +2219,21 @@ fil_write_flushed_lsn_to_data_files( return(DB_SUCCESS); } -/*******************************************************************//** -Checks the consistency of the first data page of a tablespace +/** Check the consistency of the first data page of a tablespace at database startup. +@param[in] page page frame +@param[in] space_id tablespace identifier +@param[in] flags tablespace flags @retval NULL on success, or if innodb_force_recovery is set @return pointer to an error message string */ static MY_ATTRIBUTE((warn_unused_result)) const char* -fil_check_first_page( -/*=================*/ - const page_t* page) /*!< in: data page */ +fil_check_first_page(const page_t* page, ulint space_id, ulint flags) { - ulint space_id; - ulint flags; - if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) { return(NULL); } - space_id = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page); - flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (UNIV_PAGE_SIZE != fsp_flags_get_page_size(flags)) { fprintf(stderr, "InnoDB: Error: Current page size %lu != " @@ -2342,7 +2282,7 @@ fil_read_first_page( ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ - ulint* flags, /*!< out: tablespace flags */ + ulint* flags, /*!< out: FSP_SPACE_FLAGS */ ulint* space_id, /*!< out: tablespace ID */ #ifdef UNIV_LOG_ARCHIVE ulint* min_arch_log_no, /*!< out: min of archived @@ -2378,12 +2318,22 @@ fil_read_first_page( *flags and *space_id as they were read from the first file and do not validate the first page. */ if (!one_read_already) { - *flags = fsp_header_get_flags(page); *space_id = fsp_header_get_space_id(page); - } + *flags = fsp_header_get_flags(page); - if (!one_read_already) { - check_msg = fil_check_first_page(page); + if (!fsp_flags_is_valid(*flags)) { + ulint cflags = fsp_flags_convert_from_101(*flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Invalid flags 0x%x in tablespace %u", + unsigned(*flags), unsigned(*space_id)); + return "invalid tablespace flags"; + } else { + *flags = cflags; + } + } + + check_msg = fil_check_first_page(page, *space_id, *flags); } flushed_lsn = mach_read_from_8(page + @@ -2577,6 +2527,7 @@ fil_op_write_log( ulint len; log_ptr = mlog_open(mtr, 11 + 2 + 1); + ut_ad(fsp_flags_is_valid(flags)); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: @@ -3783,7 +3734,7 @@ fil_create_new_single_table_tablespace( ibool success; /* TRUE if a table is created with CREATE TEMPORARY TABLE */ bool is_temp = !!(flags2 & DICT_TF2_TEMPORARY); - bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags); + bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0; ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags); fil_space_crypt_t *crypt_data = NULL; @@ -3791,7 +3742,7 @@ fil_create_new_single_table_tablespace( ut_ad(!srv_read_only_mode); ut_a(space_id < SRV_LOG_SPACE_FIRST_ID); ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE); - ut_a(fsp_flags_is_valid(flags)); + ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); if (is_temp) { /* Temporary table filepath */ @@ -3884,12 +3835,9 @@ fil_create_new_single_table_tablespace( memset(page, '\0', UNIV_PAGE_SIZE); - /* Add the UNIV_PAGE_SIZE to the table flags and write them to the - tablespace header. */ - flags = fsp_flags_set_page_size(flags, UNIV_PAGE_SIZE); + flags |= FSP_FLAGS_PAGE_SSIZE(); fsp_header_init_fields(page, space_id, flags); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); - ut_ad(fsp_flags_is_valid(flags)); if (!(fsp_flags_is_compressed(flags))) { buf_flush_init_for_writing(page, NULL, 0); @@ -3968,7 +3916,8 @@ fil_create_new_single_table_tablespace( fil_op_write_log(flags ? MLOG_FILE_CREATE2 : MLOG_FILE_CREATE, - space_id, mlog_file_flag, flags, + space_id, mlog_file_flag, + flags & ~FSP_FLAGS_MEM_MASK, tablename, NULL, &mtr); mtr_commit(&mtr); @@ -4032,6 +3981,39 @@ fil_report_bad_tablespace( (ulong) expected_id, (ulong) expected_flags); } +/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations. +(Typically when upgrading from MariaDB 10.1.0..10.1.20.) +@param[in] space_id tablespace ID +@param[in] flags desired tablespace flags */ +UNIV_INTERN +void +fsp_flags_try_adjust(ulint space_id, ulint flags) +{ + ut_ad(!srv_read_only_mode); + ut_ad(fsp_flags_is_valid(flags)); + + mtr_t mtr; + mtr_start(&mtr); + if (buf_block_t* b = buf_page_get( + space_id, fsp_flags_get_zip_size(flags), 0, RW_X_LATCH, + &mtr)) { + ulint f = fsp_header_get_flags(b->frame); + /* Suppress the message if only the DATA_DIR flag to differs. */ + if ((f ^ flags) & ~(1U << FSP_FLAGS_POS_RESERVED)) { + ib_logf(IB_LOG_LEVEL_WARN, + "adjusting FSP_SPACE_FLAGS of tablespace " + ULINTPF " from 0x%x to 0x%x", + space_id, int(f), int(flags)); + } + if (f != flags) { + mlog_write_ulint(FSP_HEADER_OFFSET + + FSP_SPACE_FLAGS + b->frame, + flags, MLOG_4BYTES, &mtr); + } + } + mtr_commit(&mtr); +} + /********************************************************************//** Tries to open a single-table tablespace and optionally checks that the space id in it is correct. If this does not succeed, print an error message @@ -4061,7 +4043,7 @@ fil_open_single_table_tablespace( bool validate, /*!< in: Do we validate tablespace? */ bool fix_dict, /*!< in: Can we fix the dictionary? */ ulint id, /*!< in: space id */ - ulint flags, /*!< in: tablespace flags */ + ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ const char* path_in, /*!< in: tablespace filepath */ @@ -4086,20 +4068,13 @@ fil_open_single_table_tablespace( /* Table flags can be ULINT_UNDEFINED if dict_tf_to_fsp_flags_failure is set. */ - if (flags != ULINT_UNDEFINED) { - if (!fsp_flags_is_valid(flags)) { - return(DB_CORRUPTION); - } - } else { + if (flags == ULINT_UNDEFINED) { return(DB_CORRUPTION); } + ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); atomic_writes = fsp_flags_get_atomic_writes(flags); - /* If the tablespace was relocated, we do not - compare the DATA_DIR flag */ - ulint mod_flags = flags & ~FSP_FLAGS_MASK_DATA_DIR; - memset(&def, 0, sizeof(def)); memset(&dict, 0, sizeof(dict)); memset(&remote, 0, sizeof(remote)); @@ -4180,31 +4155,17 @@ fil_open_single_table_tablespace( &space_arch_log_no, &space_arch_log_no, #endif /* UNIV_LOG_ARCHIVE */ &def.lsn, &def.lsn, &def.crypt_data); - def.valid = !def.check_msg; if (table) { table->crypt_data = def.crypt_data; table->page_0_read = true; } - /* Validate this single-table-tablespace with SYS_TABLES, - but do not compare the DATA_DIR flag, in case the - tablespace was relocated. */ - - ulint newf = def.flags; - if (newf != mod_flags) { - if (FSP_FLAGS_HAS_DATA_DIR(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR); - } else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - } - } - - if (def.valid && def.id == id - && newf == mod_flags) { + def.valid = !def.check_msg && def.id == id + && fsp_flags_match(flags, def.flags); + if (def.valid) { valid_tablespaces_found++; } else { - def.valid = false; /* Do not use this tablespace. */ fil_report_bad_tablespace( def.filepath, def.check_msg, def.id, @@ -4220,30 +4181,18 @@ fil_open_single_table_tablespace( &remote.arch_log_no, &remote.arch_log_no, #endif /* UNIV_LOG_ARCHIVE */ &remote.lsn, &remote.lsn, &remote.crypt_data); - remote.valid = !remote.check_msg; if (table) { table->crypt_data = remote.crypt_data; table->page_0_read = true; } - /* Validate this single-table-tablespace with SYS_TABLES, - but do not compare the DATA_DIR flag, in case the - tablespace was relocated. */ - ulint newf = remote.flags; - if (newf != mod_flags) { - if (FSP_FLAGS_HAS_DATA_DIR(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR); - } else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - } - } - - if (remote.valid && remote.id == id - && newf == mod_flags) { + /* Validate this single-table-tablespace with SYS_TABLES. */ + remote.valid = !remote.check_msg && remote.id == id + && fsp_flags_match(flags, remote.flags); + if (remote.valid) { valid_tablespaces_found++; } else { - remote.valid = false; /* Do not use this linked tablespace. */ fil_report_bad_tablespace( remote.filepath, remote.check_msg, remote.id, @@ -4260,30 +4209,19 @@ fil_open_single_table_tablespace( &dict.arch_log_no, &dict.arch_log_no, #endif /* UNIV_LOG_ARCHIVE */ &dict.lsn, &dict.lsn, &dict.crypt_data); - dict.valid = !dict.check_msg; if (table) { table->crypt_data = dict.crypt_data; table->page_0_read = true; } - /* Validate this single-table-tablespace with SYS_TABLES, - but do not compare the DATA_DIR flag, in case the - tablespace was relocated. */ - ulint newf = dict.flags; - if (newf != mod_flags) { - if (FSP_FLAGS_HAS_DATA_DIR(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR); - } else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - } - } + /* Validate this single-table-tablespace with SYS_TABLES. */ + dict.valid = !dict.check_msg && dict.id == id + && fsp_flags_match(flags, dict.flags); - if (dict.valid && dict.id == id - && newf == mod_flags) { + if (dict.valid) { valid_tablespaces_found++; } else { - dict.valid = false; /* Do not use this tablespace. */ fil_report_bad_tablespace( dict.filepath, dict.check_msg, dict.id, @@ -4481,6 +4419,10 @@ cleanup_and_exit: mem_free(def.filepath); + if (err == DB_SUCCESS && !srv_read_only_mode) { + fsp_flags_try_adjust(id, flags & ~FSP_FLAGS_MEM_MASK); + } + return(err); } #endif /* !UNIV_HOTBACKUP */ @@ -4662,7 +4604,23 @@ fil_user_tablespace_restore_page( goto out; } - flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + + if (!fsp_flags_is_valid(flags)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_WARN, + "Ignoring a doublewrite copy of page " + ULINTPF ":" ULINTPF + " due to invalid flags 0x%x", + fsp->id, page_no, int(flags)); + err = false; + goto out; + } + flags = cflags; + /* The flags on the page should be converted later. */ + } + zip_size = fsp_flags_get_zip_size(flags); page_size = fsp_flags_get_page_size(flags); @@ -5051,6 +5009,16 @@ will_not_choose: } mutex_exit(&fil_system->mutex); #endif /* UNIV_HOTBACKUP */ + /* Adjust the memory-based flags that would normally be set by + dict_tf_to_fsp_flags(). In recovery, we have no data dictionary. */ + if (FSP_FLAGS_HAS_PAGE_COMPRESSION(fsp->flags)) { + fsp->flags |= page_zip_level + << FSP_FLAGS_MEM_COMPRESSION_LEVEL; + } + remote.flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; + /* We will leave atomic_writes at ATOMIC_WRITES_DEFAULT. + That will be adjusted in fil_space_for_table_exists_in_mem(). */ + ibool file_space_create_success = fil_space_create( tablename, fsp->id, fsp->flags, FIL_TABLESPACE, fsp->crypt_data, false); @@ -5342,13 +5310,12 @@ fil_report_missing_tablespace( name, space_id); } -/*******************************************************************//** -Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory +/** Check if a matching tablespace exists in the InnoDB tablespace memory cache. Note that if we have not done a crash recovery at the database startup, there may be many tablespaces which are not yet in the memory cache. -@return TRUE if a matching tablespace exists in the memory cache */ +@return whether a matching tablespace exists in the memory cache */ UNIV_INTERN -ibool +bool fil_space_for_table_exists_in_mem( /*==============================*/ ulint id, /*!< in: space id */ @@ -5356,13 +5323,7 @@ fil_space_for_table_exists_in_mem( fil_space_create(). Either the standard 'dbname/tablename' format or table->dir_path_of_temp_table */ - ibool mark_space, /*!< in: in crash recovery, at database - startup we mark all spaces which have - an associated table in the InnoDB - data dictionary, so that - we can print a warning about orphaned - tablespaces */ - ibool print_error_if_does_not_exist, + bool print_error_if_does_not_exist, /*!< in: print detailed error information to the .err log if a matching tablespace is not found from @@ -5370,12 +5331,13 @@ fil_space_for_table_exists_in_mem( bool adjust_space, /*!< in: whether to adjust space id when find table space mismatch */ mem_heap_t* heap, /*!< in: heap memory */ - table_id_t table_id) /*!< in: table id */ + table_id_t table_id, /*!< in: table id */ + ulint table_flags) /*!< in: table flags */ { fil_space_t* fnamespace; fil_space_t* space; - ut_ad(fil_system); + const ulint expected_flags = dict_tf_to_fsp_flags(table_flags); mutex_enter(&fil_system->mutex); @@ -5387,42 +5349,31 @@ fil_space_for_table_exists_in_mem( directory path from the datadir to the file */ fnamespace = fil_space_get_by_name(name); - if (space && space == fnamespace) { - /* Found */ - - if (mark_space) { - space->mark = TRUE; - } - - mutex_exit(&fil_system->mutex); - - return(TRUE); - } - - /* Info from "fnamespace" comes from the ibd file itself, it can - be different from data obtained from System tables since it is - not transactional. If adjust_space is set, and the mismatching - space are between a user table and its temp table, we shall - adjust the ibd file name according to system table info */ - if (adjust_space - && space != NULL - && row_is_mysql_tmp_table_name(space->name) - && !row_is_mysql_tmp_table_name(name)) { + bool valid = space && !((space->flags ^ expected_flags) + & ~FSP_FLAGS_MEM_MASK); + if (!space) { + } else if (!valid || space == fnamespace) { + /* Found with the same file name, or got a flag mismatch. */ + goto func_exit; + } else if (adjust_space + && row_is_mysql_tmp_table_name(space->name) + && !row_is_mysql_tmp_table_name(name)) { + /* Info from fnamespace comes from the ibd file + itself, it can be different from data obtained from + System tables since renaming files is not + transactional. We shall adjust the ibd file name + according to system table info. */ mutex_exit(&fil_system->mutex); DBUG_EXECUTE_IF("ib_crash_before_adjust_fil_space", DBUG_SUICIDE();); - if (fnamespace) { - char* tmp_name; + char* tmp_name = dict_mem_create_temporary_tablename( + heap, name, table_id); - tmp_name = dict_mem_create_temporary_tablename( - heap, name, table_id); - - fil_rename_tablespace(fnamespace->name, fnamespace->id, - tmp_name, NULL); - } + fil_rename_tablespace(fnamespace->name, fnamespace->id, + tmp_name, NULL); DBUG_EXECUTE_IF("ib_crash_after_adjust_one_fil_space", DBUG_SUICIDE();); @@ -5435,16 +5386,12 @@ fil_space_for_table_exists_in_mem( mutex_enter(&fil_system->mutex); fnamespace = fil_space_get_by_name(name); ut_ad(space == fnamespace); - mutex_exit(&fil_system->mutex); - - return(TRUE); + goto func_exit; } if (!print_error_if_does_not_exist) { - - mutex_exit(&fil_system->mutex); - - return(FALSE); + valid = false; + goto func_exit; } if (space == NULL) { @@ -5471,10 +5418,8 @@ error_exit: fputs("InnoDB: Please refer to\n" "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n" "InnoDB: for how to resolve the issue.\n", stderr); - - mutex_exit(&fil_system->mutex); - - return(FALSE); + valid = false; + goto func_exit; } if (0 != strcmp(space->name, name)) { @@ -5501,9 +5446,19 @@ error_exit: goto error_exit; } +func_exit: + if (valid) { + /* Adjust the flags that are in FSP_FLAGS_MEM_MASK. + FSP_SPACE_FLAGS will not be written back here. */ + space->flags = expected_flags; + } mutex_exit(&fil_system->mutex); - return(FALSE); + if (valid && !srv_read_only_mode) { + fsp_flags_try_adjust(id, expected_flags & ~FSP_FLAGS_MEM_MASK); + } + + return(valid); } /*******************************************************************//** @@ -7331,9 +7286,8 @@ fil_space_get_crypt_data( byte *page = static_cast(ut_align(buf, UNIV_PAGE_SIZE)); fil_read(true, space_id, 0, 0, 0, UNIV_PAGE_SIZE, page, NULL, NULL); - ulint flags = fsp_header_get_flags(page); ulint offset = fsp_header_get_crypt_offset( - fsp_flags_get_zip_size(flags), NULL); + fsp_header_get_zip_size(page), NULL); space->crypt_data = fil_space_read_crypt_data(space_id, page, offset); ut_free(buf); diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 87aa5f7db5c..a71d9f95ac2 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -660,6 +660,7 @@ fsp_header_init_fields( ulint space_id, /*!< in: space id */ ulint flags) /*!< in: tablespace flags (FSP_SPACE_FLAGS) */ { + flags &= ~FSP_FLAGS_MEM_MASK; ut_a(fsp_flags_is_valid(flags)); mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page, @@ -710,7 +711,7 @@ fsp_header_init( mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr); - mlog_write_ulint(header + FSP_SPACE_FLAGS, flags, + mlog_write_ulint(header + FSP_SPACE_FLAGS, flags & ~FSP_FLAGS_MEM_MASK, MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr); diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 3d2f0dff0da..800065ddaa1 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates -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 @@ -914,10 +914,13 @@ dict_tf_to_fsp_flags( ulint table_flags) /*!< in: dict_table_t::flags */ { ulint fsp_flags; - ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags); - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags); + ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL( + table_flags); ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags); + ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0) + == (page_compression_level == 0)); + DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure", return(ULINT_UNDEFINED);); @@ -925,30 +928,23 @@ dict_tf_to_fsp_flags( fsp_flags = DICT_TF_HAS_ATOMIC_BLOBS(table_flags) ? 1 : 0; /* ZIP_SSIZE and ATOMIC_BLOBS are at the same position. */ - fsp_flags |= table_flags & DICT_TF_MASK_ZIP_SSIZE; - fsp_flags |= table_flags & DICT_TF_MASK_ATOMIC_BLOBS; + fsp_flags |= table_flags + & (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS); - /* In addition, tablespace flags also contain the page size. */ - fsp_flags |= fsp_flags_set_page_size(fsp_flags, UNIV_PAGE_SIZE); + fsp_flags |= FSP_FLAGS_PAGE_SSIZE(); - /* The DATA_DIR flag is in a different position in fsp_flag */ - fsp_flags |= DICT_TF_HAS_DATA_DIR(table_flags) - ? FSP_FLAGS_MASK_DATA_DIR : 0; - - /* In addition, tablespace flags also contain if the page - compression is used for this table. */ - fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION(fsp_flags, page_compression); - - /* In addition, tablespace flags also contain page compression level - if page compression is used for this table. */ - fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(fsp_flags, page_compression_level); - - /* In addition, tablespace flags also contain flag if atomic writes - is used for this table */ - fsp_flags |= FSP_FLAGS_SET_ATOMIC_WRITES(fsp_flags, atomic_writes); + if (page_compression_level) { + fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION; + } ut_a(fsp_flags_is_valid(fsp_flags)); - ut_a(dict_tf_verify_flags(table_flags, fsp_flags)); + + if (DICT_TF_HAS_DATA_DIR(table_flags)) { + fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; + } + + fsp_flags |= atomic_writes << FSP_FLAGS_MEM_ATOMIC_WRITES; + fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL; return(fsp_flags); } diff --git a/storage/innobase/include/dict0pagecompress.h b/storage/innobase/include/dict0pagecompress.h index 19a2a6c52f3..6503c86ffa2 100644 --- a/storage/innobase/include/dict0pagecompress.h +++ b/storage/innobase/include/dict0pagecompress.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013 SkySQL Ab. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -56,17 +56,6 @@ dict_table_page_compression_level( const dict_table_t* table) /*!< in: table */ __attribute__((const)); -/********************************************************************//** -Verify that dictionary flags match tablespace flags -@return true if flags match, false if not */ -UNIV_INLINE -ibool -dict_tf_verify_flags( -/*=================*/ - ulint table_flags, /*!< in: dict_table_t::flags */ - ulint fsp_flags) /*!< in: fil_space_t::flags */ - __attribute__((const)); - /********************************************************************//** Extract the atomic writes flag from table flags. @return true if atomic writes are used, false if not used */ diff --git a/storage/innobase/include/dict0pagecompress.ic b/storage/innobase/include/dict0pagecompress.ic index 811976434a8..13c2b46c51c 100644 --- a/storage/innobase/include/dict0pagecompress.ic +++ b/storage/innobase/include/dict0pagecompress.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013 SkySQL Ab. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,92 +24,6 @@ page compression and atomic writes information to dictionary. Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com ***********************************************************************/ -/********************************************************************//** -Verify that dictionary flags match tablespace flags -@return true if flags match, false if not */ -UNIV_INLINE -ibool -dict_tf_verify_flags( -/*=================*/ - ulint table_flags, /*!< in: dict_table_t::flags */ - ulint fsp_flags) /*!< in: fil_space_t::flags */ -{ - ulint table_unused = DICT_TF_GET_UNUSED(table_flags); - ulint compact = DICT_TF_GET_COMPACT(table_flags); - ulint ssize = DICT_TF_GET_ZIP_SSIZE(table_flags); - ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(table_flags); - ulint data_dir = DICT_TF_HAS_DATA_DIR(table_flags); - ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags); - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags); - ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags); - ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(fsp_flags); - ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags); - ulint fsp_atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(fsp_flags); - ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags); - ulint fsp_unused = FSP_FLAGS_GET_UNUSED(fsp_flags); - ulint fsp_page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(fsp_flags); - ulint fsp_page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(fsp_flags); - ulint fsp_atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(fsp_flags); - - DBUG_EXECUTE_IF("dict_tf_verify_flags_failure", - return(ULINT_UNDEFINED);); - - ut_a(!table_unused); - ut_a(!fsp_unused); - ut_a(page_ssize == 0 || page_ssize != 0); /* silence compiler */ - ut_a(compact == 0 || compact == 1); /* silence compiler */ - ut_a(data_dir == 0 || data_dir == 1); /* silence compiler */ - ut_a(post_antelope == 0 || post_antelope == 1); /* silence compiler */ - - if (ssize != zip_ssize) { - fprintf(stderr, - "InnoDB: Error: table flags has zip_ssize %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has zip_ssize %ld\n", - ssize, zip_ssize); - return (FALSE); - } - if (atomic_blobs != fsp_atomic_blobs) { - fprintf(stderr, - "InnoDB: Error: table flags has atomic_blobs %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has atomic_blobs %ld\n", - atomic_blobs, fsp_atomic_blobs); - - return (FALSE); - } - if (page_compression != fsp_page_compression) { - fprintf(stderr, - "InnoDB: Error: table flags has page_compression %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file ahas page_compression %ld\n", - page_compression, fsp_page_compression); - - return (FALSE); - } - if (page_compression_level != fsp_page_compression_level) { - fprintf(stderr, - "InnoDB: Error: table flags has page_compression_level %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has page_compression_level %ld\n", - page_compression_level, fsp_page_compression_level); - - return (FALSE); - } - - if (atomic_writes != fsp_atomic_writes) { - fprintf(stderr, - "InnoDB: Error: table flags has atomic writes %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has atomic_writes %ld\n", - atomic_writes, fsp_atomic_writes); - - return (FALSE); - } - - return(TRUE); -} - /********************************************************************//** Extract the page compression level from dict_table_t::flags. These flags are in memory, so assert that they are valid. diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index cc67d918d5f..525a68bf5e6 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. -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 @@ -44,7 +44,6 @@ Created 10/25/1995 Heikki Tuuri // Forward declaration struct trx_t; -struct fil_space_t; typedef std::list space_name_list_t; @@ -271,10 +270,6 @@ struct fil_space_t { an insert buffer merge request for a page because it actually was for the previous incarnation of the space */ - ibool mark; /*!< this is set to TRUE at database startup if - the space corresponds to a table in the InnoDB - data dictionary; so we can print a warning of - orphaned tablespaces */ ibool stop_ios;/*!< TRUE if we want to rename the .ibd file of tablespace and want to stop temporarily posting of new i/o @@ -303,7 +298,8 @@ struct fil_space_t { /*!< recovered tablespace size in pages; 0 if no size change was read from the redo log, or if the size change was implemented */ - ulint flags; /*!< tablespace flags; see + ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; + see fsp0fsp.h, fsp_flags_is_valid(), fsp_flags_get_zip_size() */ ulint n_reserved_extents; @@ -455,6 +451,7 @@ fil_node_create( ibool is_raw) /*!< in: TRUE if a raw device or a raw disk partition */ MY_ATTRIBUTE((nonnull, warn_unused_result)); + #ifdef UNIV_LOG_ARCHIVE /****************************************************************//** Drops files from the start of a file space, so that its size is cut by @@ -618,7 +615,7 @@ fil_read_first_page( ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ - ulint* flags, /*!< out: tablespace flags */ + ulint* flags, /*!< out: FSP_SPACE_FLAGS */ ulint* space_id, /*!< out: tablespace ID */ #ifdef UNIV_LOG_ARCHIVE ulint* min_arch_log_no, /*!< out: min of archived @@ -836,6 +833,14 @@ fil_create_new_single_table_tablespace( ulint key_id) /*!< in: encryption key_id */ __attribute__((nonnull, warn_unused_result)); #ifndef UNIV_HOTBACKUP +/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations. +(Typically when upgrading from MariaDB 10.1.0..10.1.20.) +@param[in] space_id tablespace ID +@param[in] flags desired tablespace flags */ +UNIV_INTERN +void +fsp_flags_try_adjust(ulint space_id, ulint flags); + /********************************************************************//** Tries to open a single-table tablespace and optionally checks the space id is right in it. If does not succeed, prints an error message to the .err log. This @@ -864,7 +869,7 @@ fil_open_single_table_tablespace( bool validate, /*!< in: Do we validate tablespace? */ bool fix_dict, /*!< in: Can we fix the dictionary? */ ulint id, /*!< in: space id */ - ulint flags, /*!< in: tablespace flags */ + ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ const char* filepath, /*!< in: tablespace filepath */ @@ -905,25 +910,18 @@ fil_tablespace_exists_in_mem( /*=========================*/ ulint id); /*!< in: space id */ #ifndef UNIV_HOTBACKUP -/*******************************************************************//** -Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory +/** Check if a matching tablespace exists in the InnoDB tablespace memory cache. Note that if we have not done a crash recovery at the database startup, there may be many tablespaces which are not yet in the memory cache. -@return TRUE if a matching tablespace exists in the memory cache */ +@return whether a matching tablespace exists in the memory cache */ UNIV_INTERN -ibool +bool fil_space_for_table_exists_in_mem( /*==============================*/ ulint id, /*!< in: space id */ const char* name, /*!< in: table name in the standard 'databasename/tablename' format */ - ibool mark_space, /*!< in: in crash recovery, at database - startup we mark all spaces which have - an associated table in the InnoDB - data dictionary, so that - we can print a warning about orphaned - tablespaces */ - ibool print_error_if_does_not_exist, + bool print_error_if_does_not_exist, /*!< in: print detailed error information to the .err log if a matching tablespace is not found from @@ -931,7 +929,8 @@ fil_space_for_table_exists_in_mem( bool adjust_space, /*!< in: whether to adjust space id when find table space mismatch */ mem_heap_t* heap, /*!< in: heap memory */ - table_id_t table_id); /*!< in: table id */ + table_id_t table_id, /*!< in: table id */ + ulint table_flags); /*!< in: table flags */ #else /* !UNIV_HOTBACKUP */ /********************************************************************//** Extends all tablespaces to the size stored in the space header. During the diff --git a/storage/innobase/include/fil0pagecompress.h b/storage/innobase/include/fil0pagecompress.h index 10db59fb218..1fe5cb66bf6 100644 --- a/storage/innobase/include/fil0pagecompress.h +++ b/storage/innobase/include/fil0pagecompress.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2016 MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017 MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -44,20 +44,11 @@ Returns the page compression flag of the space, or false if the space is not compressed. The tablespace must be cached in the memory cache. @return true if page compressed, false if not or space not found */ UNIV_INLINE -ibool +bool fil_space_is_page_compressed( /*=========================*/ ulint id); /*!< in: space id */ /*******************************************************************//** -Returns the page compression flag of the space, or false if the space -is not compressed. The tablespace must be cached in the memory cache. -@return true if page compressed, false if not or space not found */ -UNIV_INTERN -ibool -fil_space_get_page_compressed( -/*=========================*/ - fil_space_t* space); /*!< in: space id */ -/*******************************************************************//** Returns the atomic writes flag of the space, or false if the space is not using atomic writes. The tablespace must be cached in the memory cache. @return atomic write table option value */ diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index abcd5721a47..24fe382b344 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -52,28 +52,67 @@ to the two Barracuda row formats COMPRESSED and DYNAMIC. */ #define FSP_FLAGS_WIDTH_ATOMIC_BLOBS 1 /** Number of flag bits used to indicate the tablespace page size */ #define FSP_FLAGS_WIDTH_PAGE_SSIZE 4 -/** Width of the DATA_DIR flag. This flag indicates that the tablespace -is found in a remote location, not the default data directory. */ -#define FSP_FLAGS_WIDTH_DATA_DIR 1 -/** Number of flag bits used to indicate the page compression and compression level */ -#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1 -#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL 4 +/** Number of reserved bits */ +#define FSP_FLAGS_WIDTH_RESERVED 6 +/** Number of flag bits used to indicate the page compression */ +#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1 -/** Number of flag bits used to indicate atomic writes for this tablespace */ -#define FSP_FLAGS_WIDTH_ATOMIC_WRITES 2 - -/** Width of all the currently known tablespace flags */ +/** Width of all the currently known persistent tablespace flags */ #define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \ + FSP_FLAGS_WIDTH_ZIP_SSIZE \ + FSP_FLAGS_WIDTH_ATOMIC_BLOBS \ + FSP_FLAGS_WIDTH_PAGE_SSIZE \ - + FSP_FLAGS_WIDTH_DATA_DIR \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL \ - + FSP_FLAGS_WIDTH_ATOMIC_WRITES ) + + FSP_FLAGS_WIDTH_RESERVED \ + + FSP_FLAGS_WIDTH_PAGE_COMPRESSION) -/** A mask of all the known/used bits in tablespace flags */ -#define FSP_FLAGS_MASK (~(~0 << FSP_FLAGS_WIDTH)) +/** A mask of all the known/used bits in FSP_SPACE_FLAGS */ +#define FSP_FLAGS_MASK (~(~0U << FSP_FLAGS_WIDTH)) + +/* FSP_SPACE_FLAGS position and name in MySQL 5.6/MariaDB 10.0 or older +and MariaDB 10.1.20 or older MariaDB 10.1 and in MariaDB 10.1.21 +or newer. +MySQL 5.6 MariaDB 10.1.x MariaDB 10.1.21 +==================================================================== +Below flags in same offset +==================================================================== +0: POST_ANTELOPE 0:POST_ANTELOPE 0: POST_ANTELOPE +1..4: ZIP_SSIZE(0..5) 1..4:ZIP_SSIZE(0..5) 1..4: ZIP_SSIZE(0..5) +(NOTE: bit 4 is always 0) +5: ATOMIC_BLOBS 5:ATOMIC_BLOBS 5: ATOMIC_BLOBS +===================================================================== +Below note the order difference: +===================================================================== +6..9: PAGE_SSIZE(3..7) 6: COMPRESSION 6..9: PAGE_SSIZE(3..7) +10: DATA_DIR 7..10: COMP_LEVEL(0..9) 10: RESERVED (5.6 DATA_DIR) +===================================================================== +The flags below were in incorrect position in MariaDB 10.1, +or have been introduced in MySQL 5.7 or 8.0: +===================================================================== +11: UNUSED 11..12:ATOMIC_WRITES 11: RESERVED (5.7 SHARED) + 12: RESERVED (5.7 TEMPORARY) + 13..15:PAGE_SSIZE(3..7) 13: RESERVED (5.7 ENCRYPTION) + 14: RESERVED (8.0 SDI) + 15: RESERVED + 16: PAGE_SSIZE_msb(0) 16: COMPRESSION + 17: DATA_DIR 17: UNUSED + 18: UNUSED +===================================================================== +The flags below only exist in fil_space_t::flags, not in FSP_SPACE_FLAGS: +===================================================================== + 25: DATA_DIR + 26..27: ATOMIC_WRITES + 28..31: COMPRESSION_LEVEL +*/ + +/** A mask of the memory-only flags in fil_space_t::flags */ +#define FSP_FLAGS_MEM_MASK (~0U << FSP_FLAGS_MEM_DATA_DIR) + +/** Zero relative shift position of the DATA_DIR flag */ +#define FSP_FLAGS_MEM_DATA_DIR 25 +/** Zero relative shift position of the ATOMIC_WRITES field */ +#define FSP_FLAGS_MEM_ATOMIC_WRITES 26 +/** Zero relative shift position of the COMPRESSION_LEVEL field */ +#define FSP_FLAGS_MEM_COMPRESSION_LEVEL 28 /** Zero relative shift position of the POST_ANTELOPE field */ #define FSP_FLAGS_POS_POST_ANTELOPE 0 @@ -83,29 +122,16 @@ is found in a remote location, not the default data directory. */ /** Zero relative shift position of the ATOMIC_BLOBS field */ #define FSP_FLAGS_POS_ATOMIC_BLOBS (FSP_FLAGS_POS_ZIP_SSIZE \ + FSP_FLAGS_WIDTH_ZIP_SSIZE) -/** Note that these need to be before the page size to be compatible with -dictionary */ +/** Zero relative shift position of the start of the PAGE_SSIZE bits */ +#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_BLOBS \ + + FSP_FLAGS_WIDTH_ATOMIC_BLOBS) +/** Zero relative shift position of the start of the RESERVED bits +these are only used in MySQL 5.7 and used for compatibility. */ +#define FSP_FLAGS_POS_RESERVED (FSP_FLAGS_POS_PAGE_SSIZE \ + + FSP_FLAGS_WIDTH_PAGE_SSIZE) /** Zero relative shift position of the PAGE_COMPRESSION field */ -#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_ATOMIC_BLOBS \ - + FSP_FLAGS_WIDTH_ATOMIC_BLOBS) -/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */ -#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL (FSP_FLAGS_POS_PAGE_COMPRESSION \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION) -/** Zero relative shift position of the ATOMIC_WRITES field */ -#define FSP_FLAGS_POS_ATOMIC_WRITES (FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL) -/** Zero relative shift position of the PAGE_SSIZE field */ -#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_WRITES \ - + FSP_FLAGS_WIDTH_ATOMIC_WRITES) -/** Zero relative shift position of the start of the UNUSED bits */ -#define FSP_FLAGS_POS_DATA_DIR (FSP_FLAGS_POS_PAGE_SSIZE \ - + FSP_FLAGS_WIDTH_PAGE_SSIZE) -#define FSP_FLAGS_POS_DATA_DIR_ORACLE (FSP_FLAGS_POS_ATOMIC_BLOBS \ - + FSP_FLAGS_WIDTH_ATOMIC_BLOBS \ - + FSP_FLAGS_WIDTH_PAGE_SSIZE) -/** Zero relative shift position of the start of the UNUSED bits */ -#define FSP_FLAGS_POS_UNUSED (FSP_FLAGS_POS_DATA_DIR \ - + FSP_FLAGS_WIDTH_DATA_DIR) +#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_RESERVED \ + + FSP_FLAGS_WIDTH_RESERVED) /** Bit mask of the POST_ANTELOPE field */ #define FSP_FLAGS_MASK_POST_ANTELOPE \ @@ -123,26 +149,23 @@ dictionary */ #define FSP_FLAGS_MASK_PAGE_SSIZE \ ((~(~0U << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \ << FSP_FLAGS_POS_PAGE_SSIZE) -/** Bit mask of the DATA_DIR field */ -#define FSP_FLAGS_MASK_DATA_DIR \ - ((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \ - << FSP_FLAGS_POS_DATA_DIR) -/** Bit mask of the DATA_DIR field */ -#define FSP_FLAGS_MASK_DATA_DIR_ORACLE \ - ((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \ - << FSP_FLAGS_POS_DATA_DIR_ORACLE) +/** Bit mask of the RESERVED1 field */ +#define FSP_FLAGS_MASK_RESERVED \ + ((~(~0U << FSP_FLAGS_WIDTH_RESERVED)) \ + << FSP_FLAGS_POS_RESERVED) /** Bit mask of the PAGE_COMPRESSION field */ -#define FSP_FLAGS_MASK_PAGE_COMPRESSION \ +#define FSP_FLAGS_MASK_PAGE_COMPRESSION \ ((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \ << FSP_FLAGS_POS_PAGE_COMPRESSION) -/** Bit mask of the PAGE_COMPRESSION_LEVEL field */ -#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL \ - ((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)) \ - << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL) -/** Bit mask of the ATOMIC_WRITES field */ -#define FSP_FLAGS_MASK_ATOMIC_WRITES \ - ((~(~0U << FSP_FLAGS_WIDTH_ATOMIC_WRITES)) \ - << FSP_FLAGS_POS_ATOMIC_WRITES) + +/** Bit mask of the in-memory ATOMIC_WRITES field */ +#define FSP_FLAGS_MASK_MEM_ATOMIC_WRITES \ + (3U << FSP_FLAGS_MEM_ATOMIC_WRITES) + +/** Bit mask of the in-memory COMPRESSION_LEVEL field */ +#define FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL \ + (15U << FSP_FLAGS_MEM_COMPRESSION_LEVEL) + /** Return the value of the POST_ANTELOPE field */ #define FSP_FLAGS_GET_POST_ANTELOPE(flags) \ ((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \ @@ -159,49 +182,78 @@ dictionary */ #define FSP_FLAGS_GET_PAGE_SSIZE(flags) \ ((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \ >> FSP_FLAGS_POS_PAGE_SSIZE) -/** Return the value of the DATA_DIR field */ -#define FSP_FLAGS_HAS_DATA_DIR(flags) \ - ((flags & FSP_FLAGS_MASK_DATA_DIR) \ - >> FSP_FLAGS_POS_DATA_DIR) -#define FSP_FLAGS_HAS_DATA_DIR_ORACLE(flags) \ - ((flags & FSP_FLAGS_MASK_DATA_DIR_ORACLE) \ - >> FSP_FLAGS_POS_DATA_DIR_ORACLE) +/** @return the RESERVED flags */ +#define FSP_FLAGS_GET_RESERVED(flags) \ + ((flags & FSP_FLAGS_MASK_RESERVED) \ + >> FSP_FLAGS_POS_RESERVED) +/** @return the PAGE_COMPRESSION flag */ +#define FSP_FLAGS_HAS_PAGE_COMPRESSION(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \ + >> FSP_FLAGS_POS_PAGE_COMPRESSION) + /** Return the contents of the UNUSED bits */ #define FSP_FLAGS_GET_UNUSED(flags) \ (flags >> FSP_FLAGS_POS_UNUSED) -/** Return the value of the PAGE_COMPRESSION field */ -#define FSP_FLAGS_GET_PAGE_COMPRESSION(flags) \ - ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \ - >> FSP_FLAGS_POS_PAGE_COMPRESSION) -/** Return the value of the PAGE_COMPRESSION_LEVEL field */ +/** @return the PAGE_SSIZE flags for the current innodb_page_size */ +#define FSP_FLAGS_PAGE_SSIZE() \ + ((UNIV_PAGE_SIZE == UNIV_PAGE_SIZE_ORIG) ? \ + 0 : (UNIV_PAGE_SIZE_SHIFT - UNIV_ZIP_SIZE_SHIFT_MIN + 1) \ + << FSP_FLAGS_POS_PAGE_SSIZE) + +/** @return the value of the DATA_DIR field */ +#define FSP_FLAGS_HAS_DATA_DIR(flags) \ + (flags & 1U << FSP_FLAGS_MEM_DATA_DIR) +/** @return the COMPRESSION_LEVEL field */ #define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \ - ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL) \ - >> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL) -/** Return the value of the ATOMIC_WRITES field */ + ((flags & FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL) \ + >> FSP_FLAGS_MEM_COMPRESSION_LEVEL) +/** @return the ATOMIC_WRITES field */ #define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \ - ((flags & FSP_FLAGS_MASK_ATOMIC_WRITES) \ - >> FSP_FLAGS_POS_ATOMIC_WRITES) + ((flags & FSP_FLAGS_MASK_MEM_ATOMIC_WRITES) \ + >> FSP_FLAGS_MEM_ATOMIC_WRITES) -/** Set a PAGE_SSIZE into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize) \ - (flags | (ssize << FSP_FLAGS_POS_PAGE_SSIZE)) +/* Compatibility macros for MariaDB 10.1.20 or older 10.1 see +table above. */ +/** Zero relative shift position of the PAGE_COMPRESSION field */ +#define FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 \ + (FSP_FLAGS_POS_ATOMIC_BLOBS \ + + FSP_FLAGS_WIDTH_ATOMIC_BLOBS) +/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */ +#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 \ + (FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 + 1) +/** Zero relative shift position of the ATOMIC_WRITES field */ +#define FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 \ + (FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 + 4) +/** Zero relative shift position of the PAGE_SSIZE field */ +#define FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101 \ + (FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 + 2) -/** Set a PAGE_COMPRESSION into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_PAGE_COMPRESSION(flags, compression) \ - (flags | (compression << FSP_FLAGS_POS_PAGE_COMPRESSION)) +/** Bit mask of the PAGE_COMPRESSION field */ +#define FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101 \ + (1U << FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101) +/** Bit mask of the PAGE_COMPRESSION_LEVEL field */ +#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101 \ + (15U << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101) +/** Bit mask of the ATOMIC_WRITES field */ +#define FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101 \ + (3U << FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101) +/** Bit mask of the PAGE_SSIZE field */ +#define FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101 \ + (15U << FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101) -/** Set a PAGE_COMPRESSION_LEVEL into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(flags, level) \ - (flags | (level << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)) - -/** Set a ATOMIC_WRITES into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_ATOMIC_WRITES(flags, atomics) \ - (flags | (atomics << FSP_FLAGS_POS_ATOMIC_WRITES)) +/** Return the value of the PAGE_COMPRESSION field */ +#define FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101) \ + >> FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101) +/** Return the value of the PAGE_COMPRESSION_LEVEL field */ +#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101) \ + >> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101) +/** Return the value of the PAGE_SSIZE field */ +#define FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101) \ + >> FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101) /* @} */ @@ -735,19 +787,193 @@ fseg_print( mtr_t* mtr); /*!< in/out: mini-transaction */ #endif /* UNIV_BTR_PRINT */ -/********************************************************************//** -Validate and return the tablespace flags, which are stored in the -tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for -ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats, -COMPRESSED and DYNAMIC, use a file format > Antelope so they should -have a file format number plus the DICT_TF_COMPACT bit set. -@return true if check ok */ +/** Validate the tablespace flags, which are stored in the +tablespace header at offset FSP_SPACE_FLAGS. +@param[in] flags the contents of FSP_SPACE_FLAGS +@return whether the flags are correct (not in the buggy 10.1) format */ +MY_ATTRIBUTE((warn_unused_result, const)) UNIV_INLINE bool -fsp_flags_is_valid( -/*===============*/ - ulint flags) /*!< in: tablespace flags */ - MY_ATTRIBUTE((warn_unused_result, const)); +fsp_flags_is_valid(ulint flags) +{ + DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", + return(false);); + if (flags == 0) { + return(true); + } + if (flags & ~FSP_FLAGS_MASK) { + return(false); + } + if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS)) + == FSP_FLAGS_MASK_ATOMIC_BLOBS) { + /* If the "atomic blobs" flag (indicating + ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag + is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag + must also be set. */ + return(false); + } + /* Bits 10..14 should be 0b0000d where d is the DATA_DIR flag + of MySQL 5.6 and MariaDB 10.0, which we ignore. + In the buggy FSP_SPACE_FLAGS written by MariaDB 10.1.0 to 10.1.20, + bits 10..14 would be nonzero 0bsssaa where sss is + nonzero PAGE_SSIZE (3, 4, 6, or 7) + and aa is ATOMIC_WRITES (not 0b11). */ + if (FSP_FLAGS_GET_RESERVED(flags) & ~1) { + return(false); + } + + const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); + if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) { + /* the page_size is not between 4k and 64k; + 16k should be encoded as 0, not 5 */ + return(false); + } + const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); + if (zssize == 0) { + /* not ROW_FORMAT=COMPRESSED */ + } else if (zssize > (ssize ? ssize : 5)) { + /* invalid KEY_BLOCK_SIZE */ + return(false); + } else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE + | FSP_FLAGS_MASK_ATOMIC_BLOBS)) { + /* both these flags should be set for + ROW_FORMAT=COMPRESSED */ + return(false); + } + + return(true); +} + +/** Convert FSP_SPACE_FLAGS from the buggy MariaDB 10.1.0..10.1.20 format. +@param[in] flags the contents of FSP_SPACE_FLAGS +@return the flags corrected from the buggy MariaDB 10.1 format +@retval ULINT_UNDEFINED if the flags are not in the buggy 10.1 format */ +MY_ATTRIBUTE((warn_unused_result, const)) +UNIV_INLINE +ulint +fsp_flags_convert_from_101(ulint flags) +{ + DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", + return(ULINT_UNDEFINED);); + if (flags == 0) { + return(flags); + } + + if (flags >> 18) { + /* The most significant FSP_SPACE_FLAGS bit that was ever set + by MariaDB 10.1.0 to 10.1.20 was bit 17 (misplaced DATA_DIR flag). + The flags must be less than 1<<18 in order to be valid. */ + return(ULINT_UNDEFINED); + } + + if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS)) + == FSP_FLAGS_MASK_ATOMIC_BLOBS) { + /* If the "atomic blobs" flag (indicating + ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag + is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag + must also be set. */ + return(ULINT_UNDEFINED); + } + + /* Bits 6..10 denote compression in MariaDB 10.1.0 to 10.1.20. + They must be either 0b00000 or 0b00011 through 0b10011. + In correct versions, these bits would be + 0bd0sss where d is the DATA_DIR flag (garbage bit) and + sss is the PAGE_SSIZE (3, 4, 6, or 7). + + NOTE: MariaDB 10.1.0 to 10.1.20 can misinterpret + uncompressed data files with innodb_page_size=4k or 64k as + compressed innodb_page_size=16k files. Below is an exhaustive + state space analysis. + + -0by1zzz: impossible (the bit 4 must be clean; see above) + -0b101xx: DATA_DIR, innodb_page_size>4k: invalid (COMPRESSION_LEVEL>9) + +0bx0011: innodb_page_size=4k: + !!! Misinterpreted as COMPRESSION_LEVEL=9 or 1, COMPRESSION=1. + -0bx0010: impossible, because sss must be 0b011 or 0b1xx + -0bx0001: impossible, because sss must be 0b011 or 0b1xx + -0b10000: DATA_DIR, innodb_page_size=16: + invalid (COMPRESSION_LEVEL=8 but COMPRESSION=0) + +0b00111: no DATA_DIR, innodb_page_size=64k: + !!! Misinterpreted as COMPRESSION_LEVEL=3, COMPRESSION=1. + -0b00101: impossible, because sss must be 0 for 16k, not 0b101 + -0b001x0: no DATA_DIR, innodb_page_size=32k or 8k: + invalid (COMPRESSION_LEVEL=3 but COMPRESSION=0) + +0b00000: innodb_page_size=16k (looks like COMPRESSION=0) + ??? Could actually be compressed; see PAGE_SSIZE below */ + const ulint level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101( + flags); + if (FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) != (level != 0) + || level > 9) { + /* The compression flags are not in the buggy MariaDB + 10.1 format. */ + return(ULINT_UNDEFINED); + } + if (!(~flags & FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101)) { + /* The ATOMIC_WRITES flags cannot be 0b11. + (The bits 11..12 should actually never be 0b11, + because in MySQL they would be SHARED|TEMPORARY.) */ + return(ULINT_UNDEFINED); + } + + /* Bits 13..16 are the wrong position for PAGE_SSIZE, and they + should contain one of the values 3,4,6,7, that is, be of the form + 0b0011 or 0b01xx (except 0b0110). + In correct versions, these bits should be 0bc0se + where c is the MariaDB COMPRESSED flag + and e is the MySQL 5.7 ENCRYPTION flag + and s is the MySQL 8.0 SDI flag. MariaDB can only support s=0, e=0. + + Compressed innodb_page_size=16k tables with correct FSP_SPACE_FLAGS + will be properly rejected by older MariaDB 10.1.x because they + would read as PAGE_SSIZE>=8 which is not valid. */ + + const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags); + if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) { + /* the page_size is not between 4k and 64k; + 16k should be encoded as 0, not 5 */ + return(ULINT_UNDEFINED); + } + const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); + if (zssize == 0) { + /* not ROW_FORMAT=COMPRESSED */ + } else if (zssize > (ssize ? ssize : 5)) { + /* invalid KEY_BLOCK_SIZE */ + return(ULINT_UNDEFINED); + } else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE + | FSP_FLAGS_MASK_ATOMIC_BLOBS)) { + /* both these flags should be set for + ROW_FORMAT=COMPRESSED */ + return(ULINT_UNDEFINED); + } + + flags = ((flags & 0x3f) | ssize << FSP_FLAGS_POS_PAGE_SSIZE + | FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) + << FSP_FLAGS_POS_PAGE_COMPRESSION); + ut_ad(fsp_flags_is_valid(flags)); + return(flags); +} + +/** Compare tablespace flags. +@param[in] expected expected flags from dict_tf_to_fsp_flags() +@param[in] actual flags read from FSP_SPACE_FLAGS +@return whether the flags match */ +MY_ATTRIBUTE((warn_unused_result)) +UNIV_INLINE +bool +fsp_flags_match(ulint expected, ulint actual) +{ + expected &= ~FSP_FLAGS_MEM_MASK; + ut_ad(fsp_flags_is_valid(expected)); + + if (actual == expected) { + return(true); + } + + actual = fsp_flags_convert_from_101(actual); + return(actual == expected); +} + /********************************************************************//** Determine if the tablespace is compressed from dict_table_t::flags. @return TRUE if compressed, FALSE if not compressed */ diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index 9f09a9d53e1..59c732b7a29 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, SkySQL Ab. All Rights Reserved. +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 @@ -46,107 +46,6 @@ fsp_descr_page( return((page_no & (zip_size - 1)) == FSP_XDES_OFFSET); } -/********************************************************************//** -Validate and return the tablespace flags, which are stored in the -tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for -ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats, -COMPRESSED and DYNAMIC, use a file format > Antelope so they should -have a file format number plus the DICT_TF_COMPACT bit set. -@return true if check ok */ -UNIV_INLINE -bool -fsp_flags_is_valid( -/*===============*/ - ulint flags) /*!< in: tablespace flags */ -{ - ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(flags); - ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); - ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags); - ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); - ulint unused = FSP_FLAGS_GET_UNUSED(flags); - ulint page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags); - ulint page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags); - ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags); - - DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false);); - - /* fsp_flags is zero unless atomic_blobs is set. */ - /* Make sure there are no bits that we do not know about. */ - if (unused != 0 || flags == 1) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted unused %lu\n", - flags, unused); - return(false); - } else if (post_antelope) { - /* The Antelope row formats REDUNDANT and COMPACT did - not use tablespace flags, so this flag and the entire - 4-byte field is zero for Antelope row formats. */ - - if (!atomic_blobs) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_blobs %lu\n", - flags, atomic_blobs); - return(false); - } - } - - if (!atomic_blobs) { - /* Barracuda row formats COMPRESSED and DYNAMIC build on - the page structure introduced for the COMPACT row format - by allowing long fields to be broken into prefix and - externally stored parts. */ - - if (post_antelope || zip_ssize != 0) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu atomic_blobs %lu\n", - flags, zip_ssize, atomic_blobs); - return(false); - } - - } else if (!post_antelope || zip_ssize > PAGE_ZIP_SSIZE_MAX) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu max %d\n", - flags, zip_ssize, PAGE_ZIP_SSIZE_MAX); - return(false); - } else if (page_ssize > UNIV_PAGE_SSIZE_MAX) { - - /* The page size field can be used for any row type, or it may - be zero for an original 16k page size. - Validate the page shift size is within allowed range. */ - - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu\n", - flags, page_ssize, UNIV_PAGE_SSIZE_MAX); - return(false); - - } else if (UNIV_PAGE_SIZE != UNIV_PAGE_SIZE_ORIG && !page_ssize) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu:%d\n", - flags, page_ssize, UNIV_PAGE_SIZE, UNIV_PAGE_SIZE_ORIG); - return(false); - } - - /* Page compression level requires page compression and atomic blobs - to be set */ - if (page_compression_level || page_compression) { - if (!page_compression || !atomic_blobs) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_compression %lu\n" - "InnoDB: Error: page_compression_level %lu atomic_blobs %lu\n", - flags, page_compression, page_compression_level, atomic_blobs); - return(false); - } - } - - if (atomic_writes > ATOMIC_WRITES_OFF) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_writes %lu\n", - flags, atomic_writes); - return (false); - } - -#if UNIV_FORMAT_MAX != UNIV_FORMAT_B -# error "UNIV_FORMAT_MAX != UNIV_FORMAT_B, Add more validations." -#endif - - /* The DATA_DIR field can be used for any row type so there is - nothing here to validate. */ - - return(true); -} - /********************************************************************//** Determine if the tablespace is compressed from dict_table_t::flags. @return TRUE if compressed, FALSE if not compressed */ @@ -191,10 +90,10 @@ UNIV_INLINE ulint fsp_flags_get_page_size( /*====================*/ - ulint flags) /*!< in: tablespace flags */ + ulint flags) /*!< in: tablespace flags */ { - ulint page_size = 0; - ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); + ulint page_size = 0; + ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); /* Convert from a 'log2 minus 9' to a page size in bytes. */ if (UNIV_UNLIKELY(ssize)) { @@ -211,50 +110,6 @@ fsp_flags_get_page_size( } #ifndef UNIV_INNOCHECKSUM - -/********************************************************************//** -Add the page size to the tablespace flags. -@return tablespace flags after page size is added */ -UNIV_INLINE -ulint -fsp_flags_set_page_size( -/*====================*/ - ulint flags, /*!< in: tablespace flags */ - ulint page_size) /*!< in: page size in bytes */ -{ - ulint ssize = 0; - ulint shift; - - /* Page size should be > UNIV_PAGE_SIZE_MIN */ - ut_ad(page_size >= UNIV_PAGE_SIZE_MIN); - ut_ad(page_size <= UNIV_PAGE_SIZE_MAX); - - if (page_size == UNIV_PAGE_SIZE_ORIG) { - ut_ad(0 == FSP_FLAGS_GET_PAGE_SSIZE(flags)); - return(flags); - } - - for (shift = UNIV_PAGE_SIZE_SHIFT_MAX; - shift >= UNIV_PAGE_SIZE_SHIFT_MIN; - shift--) { - ulint mask = (1 << shift); - if (page_size & mask) { - ut_ad(!(page_size & ~mask)); - ssize = shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1; - break; - } - } - - ut_ad(ssize); - ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX); - - flags = FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize); - - ut_ad(fsp_flags_is_valid(flags)); - - return(flags); -} - /********************************************************************//** Calculates the descriptor index within a descriptor page. @return descriptor index */ diff --git a/storage/innobase/include/fsp0pagecompress.h b/storage/innobase/include/fsp0pagecompress.h index 5f943ee2b83..c623d11c326 100644 --- a/storage/innobase/include/fsp0pagecompress.h +++ b/storage/innobase/include/fsp0pagecompress.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -47,15 +47,6 @@ fsp_header_get_compression_level( /*=============================*/ const page_t* page); /*!< in: first page of a tablespace */ -/********************************************************************//** -Determine if the tablespace is page compressed from dict_table_t::flags. -@return TRUE if page compressed, FALSE if not compressed */ -UNIV_INLINE -ibool -fsp_flags_is_page_compressed( -/*=========================*/ - ulint flags); /*!< in: tablespace flags */ - /********************************************************************//** Extract the page compression level from tablespace flags. A tablespace has only one physical page compression level diff --git a/storage/innobase/include/fsp0pagecompress.ic b/storage/innobase/include/fsp0pagecompress.ic index e879aa2c16e..48163277feb 100644 --- a/storage/innobase/include/fsp0pagecompress.ic +++ b/storage/innobase/include/fsp0pagecompress.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -25,18 +25,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@mariadb.com ***********************************************************************/ -/********************************************************************//** -Determine if the tablespace is page compressed from dict_table_t::flags. -@return TRUE if page compressed, FALSE if not page compressed */ -UNIV_INLINE -ibool -fsp_flags_is_page_compressed( -/*=========================*/ - ulint flags) /*!< in: tablespace flags */ -{ - return(FSP_FLAGS_GET_PAGE_COMPRESSION(flags)); -} - /********************************************************************//** Determine the tablespace is page compression level from dict_table_t::flags. @return page compression level or 0 if not compressed*/ @@ -125,21 +113,15 @@ Extract the page compression from space. @return true if space is page compressed, false if space is not found or space is not page compressed. */ UNIV_INLINE -ibool +bool fil_space_is_page_compressed( /*=========================*/ ulint id) /*!< in: space id */ { - ulint flags; + ulint flags = fil_space_get_flags(id); - flags = fil_space_get_flags(id); - - if (flags && flags != ULINT_UNDEFINED) { - - return(fsp_flags_is_page_compressed(flags)); - } - - return(0); + return(flags != ULINT_UNDEFINED + && FSP_FLAGS_HAS_PAGE_COMPRESSION(flags)); } #endif /* UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 3a47e3fc6aa..f54c9d589c2 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2016, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -371,8 +371,7 @@ public: m_space(ULINT_UNDEFINED), m_xdes(), m_xdes_page_no(ULINT_UNDEFINED), - m_space_flags(ULINT_UNDEFINED), - m_table_flags(ULINT_UNDEFINED) UNIV_NOTHROW { } + m_space_flags(ULINT_UNDEFINED) UNIV_NOTHROW { } /** Free any extent descriptor instance */ @@ -535,10 +534,6 @@ protected: /** Flags value read from the header page */ ulint m_space_flags; - - /** Derived from m_space_flags and row format type, the row format - type is determined from the page header. */ - ulint m_table_flags; }; /** Determine the page size to use for traversing the tablespace @@ -553,6 +548,19 @@ AbstractCallback::init( const page_t* page = block->frame; m_space_flags = fsp_header_get_flags(page); + if (!fsp_flags_is_valid(m_space_flags)) { + ulint cflags = fsp_flags_convert_from_101(m_space_flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Invalid FSP_SPACE_FLAGS=0x%x", + int(m_space_flags)); + return(DB_CORRUPTION); + } + m_space_flags = cflags; + } + + /* Clear the DATA_DIR flag, which is basically garbage. */ + m_space_flags &= ~(1U << FSP_FLAGS_POS_RESERVED); /* Since we don't know whether it is a compressed table or not, the data is always read into the block->frame. */ @@ -640,46 +648,6 @@ struct FetchIndexRootPages : public AbstractCallback { return(m_space); } - /** - Check if the .ibd file row format is the same as the table's. - @param ibd_table_flags - determined from space and page. - @return DB_SUCCESS or error code. */ - dberr_t check_row_format(ulint ibd_table_flags) UNIV_NOTHROW - { - dberr_t err; - rec_format_t ibd_rec_format; - rec_format_t table_rec_format; - - if (!dict_tf_is_valid(ibd_table_flags)) { - - ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - ".ibd file has invlad table flags: %lx", - ibd_table_flags); - - return(DB_CORRUPTION); - } - - ibd_rec_format = dict_tf_get_rec_format(ibd_table_flags); - table_rec_format = dict_tf_get_rec_format(m_table->flags); - - if (table_rec_format != ibd_rec_format) { - - ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Table has %s row format, .ibd " - "file has %s row format.", - dict_tf_to_row_format_string(m_table->flags), - dict_tf_to_row_format_string(ibd_table_flags)); - - err = DB_CORRUPTION; - } else { - err = DB_SUCCESS; - } - - return(err); - } - /** Called for each block as it is read from the file. @param offset - physical offset in the file @@ -743,12 +711,17 @@ FetchIndexRootPages::operator() ( m_indexes.push_back(Index(id, page_no)); if (m_indexes.size() == 1) { - - m_table_flags = dict_sys_tables_type_to_tf( - m_space_flags, - page_is_comp(page) ? DICT_N_COLS_COMPACT : 0); - - err = check_row_format(m_table_flags); + /* Check that the tablespace flags match the table flags. */ + ulint expected = dict_tf_to_fsp_flags(m_table->flags); + if (!fsp_flags_match(expected, m_space_flags)) { + ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, + ER_TABLE_SCHEMA_MISMATCH, + "Expected FSP_SPACE_FLAGS=0x%x, .ibd " + "file contains 0x%x.", + unsigned(expected), + unsigned(m_space_flags)); + return(DB_CORRUPTION); + } } } @@ -1965,21 +1938,14 @@ PageConverter::update_header( "- ignored"); } - ulint space_flags = fsp_header_get_flags(get_frame(block)); - - if (!fsp_flags_is_valid(space_flags)) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Unsupported tablespace format %lu", - (ulong) space_flags); - - return(DB_UNSUPPORTED); - } - mach_write_to_8( get_frame(block) + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, m_current_lsn); + /* Write back the adjusted flags. */ + mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + + get_frame(block), m_space_flags); + /* Write space_id to the tablespace header, page 0. */ mach_write_to_4( get_frame(block) + FSP_HEADER_OFFSET + FSP_SPACE_ID, diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 1c02590933f..0e539f53641 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4335,6 +4335,7 @@ row_drop_table_for_mysql( switch (err) { ibool is_temp; + ulint table_flags; case DB_SUCCESS: /* Clone the name, in case it has been allocated @@ -4343,6 +4344,7 @@ row_drop_table_for_mysql( space_id = table->space; ibd_file_missing = table->ibd_file_missing; + table_flags = table->flags; is_temp = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY); /* If there is a temp path then the temp flag is set. @@ -4358,9 +4360,9 @@ row_drop_table_for_mysql( } /* We do not allow temporary tables with a remote path. */ - ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table->flags))); + ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table_flags))); - if (space_id && DICT_TF_HAS_DATA_DIR(table->flags)) { + if (space_id && DICT_TF_HAS_DATA_DIR(table_flags)) { dict_get_and_save_data_dir_path(table, true); ut_a(table->data_dir_path); @@ -4426,8 +4428,9 @@ row_drop_table_for_mysql( if (err == DB_SUCCESS && space_id > TRX_SYS_SPACE) { if (!is_temp && !fil_space_for_table_exists_in_mem( - space_id, tablename, FALSE, - print_msg, false, NULL, 0)) { + space_id, tablename, + print_msg, false, NULL, 0, + table_flags)) { /* This might happen if we are dropping a discarded tablespace */ err = DB_SUCCESS; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 40154c11ce1..2fec8b7bc2f 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -673,8 +673,7 @@ create_log_files( sprintf(logfilename + dirnamelen, "ib_logfile%u", INIT_LOG_FILE0); fil_space_create( - logfilename, SRV_LOG_SPACE_FIRST_ID, - fsp_flags_set_page_size(0, UNIV_PAGE_SIZE), + logfilename, SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG, NULL /* no encryption yet */, true /* this is create */); @@ -1159,7 +1158,7 @@ check_first_page: crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); } - flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE); + flags = FSP_FLAGS_PAGE_SSIZE(); fil_space_create(name, 0, flags, FIL_TABLESPACE, crypt_data, (*create_new_db) == true); @@ -1307,7 +1306,7 @@ srv_undo_tablespace_open( fil_set_max_space_id_if_bigger(space); /* Set the compressed page size to 0 (non-compressed) */ - flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE); + flags = FSP_FLAGS_PAGE_SSIZE(); fil_space_create(name, space, flags, FIL_TABLESPACE, NULL /* no encryption */, true /* create */); @@ -2296,9 +2295,7 @@ innobase_start_or_create_for_mysql(void) sprintf(logfilename + dirnamelen, "ib_logfile%u", 0); fil_space_create(logfilename, - SRV_LOG_SPACE_FIRST_ID, - fsp_flags_set_page_size(0, UNIV_PAGE_SIZE), - FIL_LOG, + SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG, NULL /* no encryption yet */, true /* create */); @@ -2714,6 +2711,13 @@ files_checked: } if (!srv_read_only_mode) { + const ulint flags = FSP_FLAGS_PAGE_SSIZE(); + for (ulint id = 0; id <= srv_undo_tablespaces; id++) { + if (fil_space_get(id)) { + fsp_flags_try_adjust(id, flags); + } + } + /* Create the thread which watches the timeouts for lock waits */ thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create( diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc index 9c7eea6410a..68bb83e4903 100644 --- a/storage/xtradb/buf/buf0dblwr.cc +++ b/storage/xtradb/buf/buf0dblwr.cc @@ -589,6 +589,21 @@ buf_dblwr_process() continue; } + if (page_no == 0) { + /* Check the FSP_SPACE_FLAGS. */ + ulint flags = fsp_header_get_flags(page); + if (!fsp_flags_is_valid(flags) + && fsp_flags_convert_from_101(flags) + == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_WARN, + "Ignoring a doublewrite copy of page " + ULINTPF ":0 due to invalid flags 0x%x", + space_id, int(flags)); + continue; + } + /* The flags on the page should be converted later. */ + } + /* Write the good page from the doublewrite buffer to the intended position. */ diff --git a/storage/xtradb/dict/dict0load.cc b/storage/xtradb/dict/dict0load.cc index 39a6ae993c8..776bb873c5c 100644 --- a/storage/xtradb/dict/dict0load.cc +++ b/storage/xtradb/dict/dict0load.cc @@ -1052,8 +1052,6 @@ loop: btr_pcur_store_position(&pcur, &mtr); - mtr_commit(&mtr); - /* For tables created with old versions of InnoDB, SYS_TABLES.MIX_LEN may contain garbage. Such tables would always be in ROW_FORMAT=REDUNDANT. Pretend that @@ -1087,16 +1085,19 @@ loop: if (space_id == 0) { /* The system tablespace always exists. */ ut_ad(!discarded); - goto next_tablespace; + mem_free(name); + goto loop; } + mtr_commit(&mtr); + switch (dict_check) { case DICT_CHECK_ALL_LOADED: /* All tablespaces should have been found in fil_load_single_table_tablespaces(). */ if (fil_space_for_table_exists_in_mem( - space_id, name, TRUE, !(is_temp || discarded), - false, NULL, 0) + space_id, name, !(is_temp || discarded), + false, NULL, 0, flags) && !(is_temp || discarded)) { /* If user changes the path of .ibd files in *.isl files before doing crash recovery , @@ -1128,8 +1129,8 @@ loop: /* Some tablespaces may have been opened in trx_resurrect_table_locks(). */ if (fil_space_for_table_exists_in_mem( - space_id, name, FALSE, FALSE, - false, NULL, 0)) { + space_id, name, false, + false, NULL, 0, flags)) { break; } /* fall through */ @@ -1191,7 +1192,6 @@ loop: max_space_id = space_id; } -next_tablespace: mem_free(name); mtr_start(&mtr); @@ -2383,8 +2383,8 @@ err_exit: table->ibd_file_missing = TRUE; } else if (!fil_space_for_table_exists_in_mem( - table->space, name, FALSE, FALSE, true, heap, - table->id)) { + table->space, name, false, true, heap, + table->id, table->flags)) { if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) { /* Do not bother to retry opening temporary tables. */ diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 133960ae8b4..f4301d47028 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +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 @@ -601,10 +601,7 @@ fil_node_open_file( ibool success; byte* buf2; byte* page; - ulint space_id; - ulint flags=0; ulint page_size; - ulint atomic_writes=0; ut_ad(mutex_own(&(system->mutex))); ut_a(node->n_pending == 0); @@ -626,8 +623,6 @@ fil_node_open_file( /* The following call prints an error message */ os_file_get_last_error(true); - ut_print_timestamp(stderr); - ib_logf(IB_LOG_LEVEL_WARN, "InnoDB: Error: cannot " "open %s\n. InnoDB: Have you deleted .ibd " "files under a running mysqld server?\n", @@ -653,17 +648,13 @@ fil_node_open_file( ut_a(fil_is_user_tablespace_id(space->id)); if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) { - fprintf(stderr, - "InnoDB: Error: the size of single-table" - " tablespace file %s\n" - "InnoDB: is only " UINT64PF "," - " should be at least %lu!\n", - node->name, - size_bytes, - (ulong) (FIL_IBD_FILE_INITIAL_SIZE - * UNIV_PAGE_SIZE)); - - ut_a(0); + ib_logf(IB_LOG_LEVEL_ERROR, + "The size of the file %s is only " UINT64PF + " bytes, should be at least " ULINTPF, + node->name, size_bytes, + FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE); + os_file_close(node->handle); + return(false); } /* Read the first page of the tablespace */ @@ -676,77 +667,34 @@ fil_node_open_file( success = os_file_read(node->handle, page, 0, UNIV_PAGE_SIZE); srv_stats.page0_read.add(1); - space_id = fsp_header_get_space_id(page); - flags = fsp_header_get_flags(page); - - page_size = fsp_flags_get_page_size(flags); - atomic_writes = fsp_flags_get_atomic_writes(flags); + const ulint space_id = fsp_header_get_space_id(page); + ulint flags = fsp_header_get_flags(page); ut_free(buf2); - - /* Close the file now that we have read the space id from it */ - os_file_close(node->handle); + if (!fsp_flags_is_valid(flags)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Expected tablespace flags 0x%x" + " but found 0x%x in the file %s", + int(space->flags), int(flags), + node->name); + return(false); + } + + flags = cflags; + } + + page_size = fsp_flags_get_page_size(flags); + if (UNIV_UNLIKELY(space_id != space->id)) { - fprintf(stderr, - "InnoDB: Error: tablespace id is %lu" - " in the data dictionary\n" - "InnoDB: but in file %s it is %lu!\n", + ib_logf(IB_LOG_LEVEL_ERROR, + "tablespace id is " ULINTPF " in the data dictionary" + " but in file %s it is " ULINTPF "!\n", space->id, node->name, space_id); - - ut_error; - } - - if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED - || space_id == 0)) { - fprintf(stderr, - "InnoDB: Error: tablespace id %lu" - " in file %s is not sensible\n", - (ulong) space_id, node->name); - - ut_error; - } - - if (UNIV_UNLIKELY(fsp_flags_get_page_size(space->flags) - != page_size)) { - fprintf(stderr, - "InnoDB: Error: tablespace file %s" - " has page size 0x%lx\n" - "InnoDB: but the data dictionary" - " expects page size 0x%lx!\n", - node->name, flags, - fsp_flags_get_page_size(space->flags)); - - ut_error; - } - - if (UNIV_UNLIKELY(space->flags != flags)) { - ulint sflags = (space->flags & ~FSP_FLAGS_MASK_DATA_DIR); - ulint fflags = (flags & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - - /* DATA_DIR option is on different place on MariaDB - compared to MySQL. If this is the difference. Fix - it. */ - - if (sflags == fflags) { - fprintf(stderr, - "InnoDB: Warning: Table flags 0x%lx" - " in the data dictionary but in file %s are 0x%lx!\n" - " Temporally corrected because DATA_DIR option to 0x%lx.\n", - space->flags, node->name, flags, space->flags); - - flags = space->flags; - } - - if (!dict_tf_verify_flags(space->flags, flags)) { - fprintf(stderr, - "InnoDB: Error: table flags are 0x%lx" - " in the data dictionary\n" - "InnoDB: but the flags in file %s are 0x%lx!\n", - space->flags, node->name, flags); - ut_error; - } + return(false); } if (size_bytes >= (1024*1024)) { @@ -768,7 +716,7 @@ add_size: space->size += node->size; } - atomic_writes = fsp_flags_get_atomic_writes(space->flags); + ulint atomic_writes = fsp_flags_get_atomic_writes(space->flags); /* printf("Opening file %s\n", node->name); */ @@ -1572,7 +1520,6 @@ fil_space_create( fil_system->tablespace_version++; space->tablespace_version = fil_system->tablespace_version; - space->mark = FALSE; if (purpose == FIL_TABLESPACE && !recv_recovery_on && id > fil_system->max_assigned_id) { @@ -2324,27 +2271,21 @@ fil_write_flushed_lsn_to_data_files( return(DB_SUCCESS); } -/*******************************************************************//** -Checks the consistency of the first data page of a tablespace +/** Check the consistency of the first data page of a tablespace at database startup. +@param[in] page page frame +@param[in] space_id tablespace identifier +@param[in] flags tablespace flags @retval NULL on success, or if innodb_force_recovery is set @return pointer to an error message string */ static MY_ATTRIBUTE((warn_unused_result)) const char* -fil_check_first_page( -/*=================*/ - const page_t* page) /*!< in: data page */ +fil_check_first_page(const page_t* page, ulint space_id, ulint flags) { - ulint space_id; - ulint flags; - if (srv_force_recovery >= SRV_FORCE_IGNORE_CORRUPT) { return(NULL); } - space_id = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page); - flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); - if (UNIV_PAGE_SIZE != fsp_flags_get_page_size(flags)) { fprintf(stderr, "InnoDB: Error: Current page size %lu != " @@ -2393,7 +2334,7 @@ fil_read_first_page( ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ - ulint* flags, /*!< out: tablespace flags */ + ulint* flags, /*!< out: FSP_SPACE_FLAGS */ ulint* space_id, /*!< out: tablespace ID */ lsn_t* min_flushed_lsn, /*!< out: min of flushed lsn values in data files */ @@ -2423,12 +2364,22 @@ fil_read_first_page( *flags and *space_id as they were read from the first file and do not validate the first page. */ if (!one_read_already) { - *flags = fsp_header_get_flags(page); *space_id = fsp_header_get_space_id(page); - } + *flags = fsp_header_get_flags(page); - if (!one_read_already) { - check_msg = fil_check_first_page(page); + if (!fsp_flags_is_valid(*flags)) { + ulint cflags = fsp_flags_convert_from_101(*flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Invalid flags 0x%x in tablespace %u", + unsigned(*flags), unsigned(*space_id)); + return "invalid tablespace flags"; + } else { + *flags = cflags; + } + } + + check_msg = fil_check_first_page(page, *space_id, *flags); } flushed_lsn = mach_read_from_8(page + @@ -2612,6 +2563,7 @@ fil_op_write_log( ulint len; log_ptr = mlog_open(mtr, 11 + 2 + 1); + ut_ad(fsp_flags_is_valid(flags)); if (!log_ptr) { /* Logging in mtr is switched off during crash recovery: @@ -3823,7 +3775,7 @@ fil_create_new_single_table_tablespace( ibool success; /* TRUE if a table is created with CREATE TEMPORARY TABLE */ bool is_temp = !!(flags2 & DICT_TF2_TEMPORARY); - bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags); + bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0; ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags); fil_space_crypt_t *crypt_data = NULL; @@ -3831,7 +3783,7 @@ fil_create_new_single_table_tablespace( ut_ad(!srv_read_only_mode); ut_a(space_id < SRV_LOG_SPACE_FIRST_ID); ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE); - ut_a(fsp_flags_is_valid(flags)); + ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); if (is_temp) { /* Temporary table filepath */ @@ -3924,12 +3876,9 @@ fil_create_new_single_table_tablespace( memset(page, '\0', UNIV_PAGE_SIZE); - /* Add the UNIV_PAGE_SIZE to the table flags and write them to the - tablespace header. */ - flags = fsp_flags_set_page_size(flags, UNIV_PAGE_SIZE); + flags |= FSP_FLAGS_PAGE_SSIZE(); fsp_header_init_fields(page, space_id, flags); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); - ut_ad(fsp_flags_is_valid(flags)); if (!(fsp_flags_is_compressed(flags))) { buf_flush_init_for_writing(page, NULL, 0); @@ -4008,7 +3957,8 @@ fil_create_new_single_table_tablespace( fil_op_write_log(flags ? MLOG_FILE_CREATE2 : MLOG_FILE_CREATE, - space_id, mlog_file_flag, flags, + space_id, mlog_file_flag, + flags & ~FSP_FLAGS_MEM_MASK, tablename, NULL, &mtr); mtr_commit(&mtr); @@ -4072,6 +4022,39 @@ fil_report_bad_tablespace( (ulong) expected_id, (ulong) expected_flags); } +/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations. +(Typically when upgrading from MariaDB 10.1.0..10.1.20.) +@param[in] space_id tablespace ID +@param[in] flags desired tablespace flags */ +UNIV_INTERN +void +fsp_flags_try_adjust(ulint space_id, ulint flags) +{ + ut_ad(!srv_read_only_mode); + ut_ad(fsp_flags_is_valid(flags)); + + mtr_t mtr; + mtr_start(&mtr); + if (buf_block_t* b = buf_page_get( + space_id, fsp_flags_get_zip_size(flags), 0, RW_X_LATCH, + &mtr)) { + ulint f = fsp_header_get_flags(b->frame); + /* Suppress the message if only the DATA_DIR flag to differs. */ + if ((f ^ flags) & ~(1U << FSP_FLAGS_POS_RESERVED)) { + ib_logf(IB_LOG_LEVEL_WARN, + "adjusting FSP_SPACE_FLAGS of tablespace " + ULINTPF " from 0x%x to 0x%x", + space_id, int(f), int(flags)); + } + if (f != flags) { + mlog_write_ulint(FSP_HEADER_OFFSET + + FSP_SPACE_FLAGS + b->frame, + flags, MLOG_4BYTES, &mtr); + } + } + mtr_commit(&mtr); +} + /********************************************************************//** Tries to open a single-table tablespace and optionally checks that the space id in it is correct. If this does not succeed, print an error message @@ -4101,7 +4084,7 @@ fil_open_single_table_tablespace( bool validate, /*!< in: Do we validate tablespace? */ bool fix_dict, /*!< in: Can we fix the dictionary? */ ulint id, /*!< in: space id */ - ulint flags, /*!< in: tablespace flags */ + ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ const char* path_in, /*!< in: tablespace filepath */ @@ -4126,20 +4109,13 @@ fil_open_single_table_tablespace( /* Table flags can be ULINT_UNDEFINED if dict_tf_to_fsp_flags_failure is set. */ - if (flags != ULINT_UNDEFINED) { - if (!fsp_flags_is_valid(flags)) { - return(DB_CORRUPTION); - } - } else { + if (flags == ULINT_UNDEFINED) { return(DB_CORRUPTION); } + ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK)); atomic_writes = fsp_flags_get_atomic_writes(flags); - /* If the tablespace was relocated, we do not - compare the DATA_DIR flag */ - ulint mod_flags = flags & ~FSP_FLAGS_MASK_DATA_DIR; - memset(&def, 0, sizeof(def)); memset(&dict, 0, sizeof(dict)); memset(&remote, 0, sizeof(remote)); @@ -4217,31 +4193,17 @@ fil_open_single_table_tablespace( def.check_msg = fil_read_first_page( def.file, FALSE, &def.flags, &def.id, &def.lsn, &def.lsn, &def.crypt_data); - def.valid = !def.check_msg; if (table) { table->crypt_data = def.crypt_data; table->page_0_read = true; } - /* Validate this single-table-tablespace with SYS_TABLES, - but do not compare the DATA_DIR flag, in case the - tablespace was relocated. */ - - ulint newf = def.flags; - if (newf != mod_flags) { - if (FSP_FLAGS_HAS_DATA_DIR(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR); - } else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - } - } - - if (def.valid && def.id == id - && newf == mod_flags) { + def.valid = !def.check_msg && def.id == id + && fsp_flags_match(flags, def.flags); + if (def.valid) { valid_tablespaces_found++; } else { - def.valid = false; /* Do not use this tablespace. */ fil_report_bad_tablespace( def.filepath, def.check_msg, def.id, @@ -4254,30 +4216,18 @@ fil_open_single_table_tablespace( remote.check_msg = fil_read_first_page( remote.file, FALSE, &remote.flags, &remote.id, &remote.lsn, &remote.lsn, &remote.crypt_data); - remote.valid = !remote.check_msg; if (table) { table->crypt_data = remote.crypt_data; table->page_0_read = true; } - /* Validate this single-table-tablespace with SYS_TABLES, - but do not compare the DATA_DIR flag, in case the - tablespace was relocated. */ - ulint newf = remote.flags; - if (newf != mod_flags) { - if (FSP_FLAGS_HAS_DATA_DIR(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR); - } else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - } - } - - if (remote.valid && remote.id == id - && newf == mod_flags) { + /* Validate this single-table-tablespace with SYS_TABLES. */ + remote.valid = !remote.check_msg && remote.id == id + && fsp_flags_match(flags, remote.flags); + if (remote.valid) { valid_tablespaces_found++; } else { - remote.valid = false; /* Do not use this linked tablespace. */ fil_report_bad_tablespace( remote.filepath, remote.check_msg, remote.id, @@ -4291,30 +4241,19 @@ fil_open_single_table_tablespace( dict.check_msg = fil_read_first_page( dict.file, FALSE, &dict.flags, &dict.id, &dict.lsn, &dict.lsn, &dict.crypt_data); - dict.valid = !dict.check_msg; if (table) { table->crypt_data = dict.crypt_data; table->page_0_read = true; } - /* Validate this single-table-tablespace with SYS_TABLES, - but do not compare the DATA_DIR flag, in case the - tablespace was relocated. */ - ulint newf = dict.flags; - if (newf != mod_flags) { - if (FSP_FLAGS_HAS_DATA_DIR(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR); - } else if(FSP_FLAGS_HAS_DATA_DIR_ORACLE(newf)) { - newf = (newf & ~FSP_FLAGS_MASK_DATA_DIR_ORACLE); - } - } + /* Validate this single-table-tablespace with SYS_TABLES. */ + dict.valid = !dict.check_msg && dict.id == id + && fsp_flags_match(flags, dict.flags); - if (dict.valid && dict.id == id - && newf == mod_flags) { + if (dict.valid) { valid_tablespaces_found++; } else { - dict.valid = false; /* Do not use this tablespace. */ fil_report_bad_tablespace( dict.filepath, dict.check_msg, dict.id, @@ -4512,6 +4451,10 @@ cleanup_and_exit: mem_free(def.filepath); + if (err == DB_SUCCESS && !srv_read_only_mode) { + fsp_flags_try_adjust(id, flags & ~FSP_FLAGS_MEM_MASK); + } + return(err); } #endif /* !UNIV_HOTBACKUP */ @@ -4693,7 +4636,23 @@ fil_user_tablespace_restore_page( goto out; } - flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page); + + if (!fsp_flags_is_valid(flags)) { + ulint cflags = fsp_flags_convert_from_101(flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_WARN, + "Ignoring a doublewrite copy of page " + ULINTPF ":" ULINTPF + " due to invalid flags 0x%x", + fsp->id, page_no, int(flags)); + err = false; + goto out; + } + flags = cflags; + /* The flags on the page should be converted later. */ + } + zip_size = fsp_flags_get_zip_size(flags); page_size = fsp_flags_get_page_size(flags); @@ -5071,6 +5030,16 @@ will_not_choose: } mutex_exit(&fil_system->mutex); #endif /* UNIV_HOTBACKUP */ + /* Adjust the memory-based flags that would normally be set by + dict_tf_to_fsp_flags(). In recovery, we have no data dictionary. */ + if (FSP_FLAGS_HAS_PAGE_COMPRESSION(fsp->flags)) { + fsp->flags |= page_zip_level + << FSP_FLAGS_MEM_COMPRESSION_LEVEL; + } + remote.flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; + /* We will leave atomic_writes at ATOMIC_WRITES_DEFAULT. + That will be adjusted in fil_space_for_table_exists_in_mem(). */ + ibool file_space_create_success = fil_space_create( tablename, fsp->id, fsp->flags, FIL_TABLESPACE, fsp->crypt_data, false); @@ -5380,13 +5349,12 @@ fil_report_missing_tablespace( name, space_id); } -/*******************************************************************//** -Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory +/** Check if a matching tablespace exists in the InnoDB tablespace memory cache. Note that if we have not done a crash recovery at the database startup, there may be many tablespaces which are not yet in the memory cache. -@return TRUE if a matching tablespace exists in the memory cache */ +@return whether a matching tablespace exists in the memory cache */ UNIV_INTERN -ibool +bool fil_space_for_table_exists_in_mem( /*==============================*/ ulint id, /*!< in: space id */ @@ -5394,13 +5362,7 @@ fil_space_for_table_exists_in_mem( fil_space_create(). Either the standard 'dbname/tablename' format or table->dir_path_of_temp_table */ - ibool mark_space, /*!< in: in crash recovery, at database - startup we mark all spaces which have - an associated table in the InnoDB - data dictionary, so that - we can print a warning about orphaned - tablespaces */ - ibool print_error_if_does_not_exist, + bool print_error_if_does_not_exist, /*!< in: print detailed error information to the .err log if a matching tablespace is not found from @@ -5408,12 +5370,13 @@ fil_space_for_table_exists_in_mem( bool adjust_space, /*!< in: whether to adjust space id when find table space mismatch */ mem_heap_t* heap, /*!< in: heap memory */ - table_id_t table_id) /*!< in: table id */ + table_id_t table_id, /*!< in: table id */ + ulint table_flags) /*!< in: table flags */ { fil_space_t* fnamespace; fil_space_t* space; - ut_ad(fil_system); + const ulint expected_flags = dict_tf_to_fsp_flags(table_flags); mutex_enter(&fil_system->mutex); @@ -5425,42 +5388,31 @@ fil_space_for_table_exists_in_mem( directory path from the datadir to the file */ fnamespace = fil_space_get_by_name(name); - if (space && space == fnamespace) { - /* Found */ - - if (mark_space) { - space->mark = TRUE; - } - - mutex_exit(&fil_system->mutex); - - return(TRUE); - } - - /* Info from "fnamespace" comes from the ibd file itself, it can - be different from data obtained from System tables since it is - not transactional. If adjust_space is set, and the mismatching - space are between a user table and its temp table, we shall - adjust the ibd file name according to system table info */ - if (adjust_space - && space != NULL - && row_is_mysql_tmp_table_name(space->name) - && !row_is_mysql_tmp_table_name(name)) { + bool valid = space && !((space->flags ^ expected_flags) + & ~FSP_FLAGS_MEM_MASK); + if (!space) { + } else if (!valid || space == fnamespace) { + /* Found with the same file name, or got a flag mismatch. */ + goto func_exit; + } else if (adjust_space + && row_is_mysql_tmp_table_name(space->name) + && !row_is_mysql_tmp_table_name(name)) { + /* Info from fnamespace comes from the ibd file + itself, it can be different from data obtained from + System tables since renaming files is not + transactional. We shall adjust the ibd file name + according to system table info. */ mutex_exit(&fil_system->mutex); DBUG_EXECUTE_IF("ib_crash_before_adjust_fil_space", DBUG_SUICIDE();); - if (fnamespace) { - char* tmp_name; + char* tmp_name = dict_mem_create_temporary_tablename( + heap, name, table_id); - tmp_name = dict_mem_create_temporary_tablename( - heap, name, table_id); - - fil_rename_tablespace(fnamespace->name, fnamespace->id, - tmp_name, NULL); - } + fil_rename_tablespace(fnamespace->name, fnamespace->id, + tmp_name, NULL); DBUG_EXECUTE_IF("ib_crash_after_adjust_one_fil_space", DBUG_SUICIDE();); @@ -5473,16 +5425,12 @@ fil_space_for_table_exists_in_mem( mutex_enter(&fil_system->mutex); fnamespace = fil_space_get_by_name(name); ut_ad(space == fnamespace); - mutex_exit(&fil_system->mutex); - - return(TRUE); + goto func_exit; } if (!print_error_if_does_not_exist) { - - mutex_exit(&fil_system->mutex); - - return(FALSE); + valid = false; + goto func_exit; } if (space == NULL) { @@ -5509,10 +5457,8 @@ error_exit: fputs("InnoDB: Please refer to\n" "InnoDB: " REFMAN "innodb-troubleshooting-datadict.html\n" "InnoDB: for how to resolve the issue.\n", stderr); - - mutex_exit(&fil_system->mutex); - - return(FALSE); + valid = false; + goto func_exit; } if (0 != strcmp(space->name, name)) { @@ -5539,9 +5485,19 @@ error_exit: goto error_exit; } +func_exit: + if (valid) { + /* Adjust the flags that are in FSP_FLAGS_MEM_MASK. + FSP_SPACE_FLAGS will not be written back here. */ + space->flags = expected_flags; + } mutex_exit(&fil_system->mutex); - return(FALSE); + if (valid && !srv_read_only_mode) { + fsp_flags_try_adjust(id, expected_flags & ~FSP_FLAGS_MEM_MASK); + } + + return(valid); } /*******************************************************************//** @@ -7444,9 +7400,8 @@ fil_space_get_crypt_data( byte *page = static_cast(ut_align(buf, UNIV_PAGE_SIZE)); fil_read(true, space_id, 0, 0, 0, UNIV_PAGE_SIZE, page, NULL, NULL); - ulint flags = fsp_header_get_flags(page); ulint offset = fsp_header_get_crypt_offset( - fsp_flags_get_zip_size(flags), NULL); + fsp_header_get_zip_size(page), NULL); space->crypt_data = fil_space_read_crypt_data(space_id, page, offset); ut_free(buf); diff --git a/storage/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc index 4acfd134c1f..c32fddaabbe 100644 --- a/storage/xtradb/fsp/fsp0fsp.cc +++ b/storage/xtradb/fsp/fsp0fsp.cc @@ -663,6 +663,7 @@ fsp_header_init_fields( ulint space_id, /*!< in: space id */ ulint flags) /*!< in: tablespace flags (FSP_SPACE_FLAGS) */ { + flags &= ~FSP_FLAGS_MEM_MASK; ut_a(fsp_flags_is_valid(flags)); mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page, @@ -713,7 +714,7 @@ fsp_header_init( mlog_write_ulint(header + FSP_SIZE, size, MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_FREE_LIMIT, 0, MLOG_4BYTES, mtr); - mlog_write_ulint(header + FSP_SPACE_FLAGS, flags, + mlog_write_ulint(header + FSP_SPACE_FLAGS, flags & ~FSP_FLAGS_MEM_MASK, MLOG_4BYTES, mtr); mlog_write_ulint(header + FSP_FRAG_N_USED, 0, MLOG_4BYTES, mtr); diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic index d9d40b809d1..2b63ddea51d 100644 --- a/storage/xtradb/include/dict0dict.ic +++ b/storage/xtradb/include/dict0dict.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB +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 @@ -918,10 +918,13 @@ dict_tf_to_fsp_flags( ulint table_flags) /*!< in: dict_table_t::flags */ { ulint fsp_flags; - ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags); - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags); + ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL( + table_flags); ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags); + ut_ad((DICT_TF_GET_PAGE_COMPRESSION(table_flags) == 0) + == (page_compression_level == 0)); + DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure", return(ULINT_UNDEFINED);); @@ -929,30 +932,23 @@ dict_tf_to_fsp_flags( fsp_flags = DICT_TF_HAS_ATOMIC_BLOBS(table_flags) ? 1 : 0; /* ZIP_SSIZE and ATOMIC_BLOBS are at the same position. */ - fsp_flags |= table_flags & DICT_TF_MASK_ZIP_SSIZE; - fsp_flags |= table_flags & DICT_TF_MASK_ATOMIC_BLOBS; + fsp_flags |= table_flags + & (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS); - /* In addition, tablespace flags also contain the page size. */ - fsp_flags |= fsp_flags_set_page_size(fsp_flags, UNIV_PAGE_SIZE); + fsp_flags |= FSP_FLAGS_PAGE_SSIZE(); - /* The DATA_DIR flag is in a different position in fsp_flag */ - fsp_flags |= DICT_TF_HAS_DATA_DIR(table_flags) - ? FSP_FLAGS_MASK_DATA_DIR : 0; - - /* In addition, tablespace flags also contain if the page - compression is used for this table. */ - fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION(fsp_flags, page_compression); - - /* In addition, tablespace flags also contain page compression level - if page compression is used for this table. */ - fsp_flags |= FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(fsp_flags, page_compression_level); - - /* In addition, tablespace flags also contain flag if atomic writes - is used for this table */ - fsp_flags |= FSP_FLAGS_SET_ATOMIC_WRITES(fsp_flags, atomic_writes); + if (page_compression_level) { + fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION; + } ut_a(fsp_flags_is_valid(fsp_flags)); - ut_a(dict_tf_verify_flags(table_flags, fsp_flags)); + + if (DICT_TF_HAS_DATA_DIR(table_flags)) { + fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR; + } + + fsp_flags |= atomic_writes << FSP_FLAGS_MEM_ATOMIC_WRITES; + fsp_flags |= page_compression_level << FSP_FLAGS_MEM_COMPRESSION_LEVEL; return(fsp_flags); } diff --git a/storage/xtradb/include/dict0pagecompress.h b/storage/xtradb/include/dict0pagecompress.h index 19a2a6c52f3..6503c86ffa2 100644 --- a/storage/xtradb/include/dict0pagecompress.h +++ b/storage/xtradb/include/dict0pagecompress.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013 SkySQL Ab. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -56,17 +56,6 @@ dict_table_page_compression_level( const dict_table_t* table) /*!< in: table */ __attribute__((const)); -/********************************************************************//** -Verify that dictionary flags match tablespace flags -@return true if flags match, false if not */ -UNIV_INLINE -ibool -dict_tf_verify_flags( -/*=================*/ - ulint table_flags, /*!< in: dict_table_t::flags */ - ulint fsp_flags) /*!< in: fil_space_t::flags */ - __attribute__((const)); - /********************************************************************//** Extract the atomic writes flag from table flags. @return true if atomic writes are used, false if not used */ diff --git a/storage/xtradb/include/dict0pagecompress.ic b/storage/xtradb/include/dict0pagecompress.ic index 811976434a8..13c2b46c51c 100644 --- a/storage/xtradb/include/dict0pagecompress.ic +++ b/storage/xtradb/include/dict0pagecompress.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013 SkySQL Ab. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,92 +24,6 @@ page compression and atomic writes information to dictionary. Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com ***********************************************************************/ -/********************************************************************//** -Verify that dictionary flags match tablespace flags -@return true if flags match, false if not */ -UNIV_INLINE -ibool -dict_tf_verify_flags( -/*=================*/ - ulint table_flags, /*!< in: dict_table_t::flags */ - ulint fsp_flags) /*!< in: fil_space_t::flags */ -{ - ulint table_unused = DICT_TF_GET_UNUSED(table_flags); - ulint compact = DICT_TF_GET_COMPACT(table_flags); - ulint ssize = DICT_TF_GET_ZIP_SSIZE(table_flags); - ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(table_flags); - ulint data_dir = DICT_TF_HAS_DATA_DIR(table_flags); - ulint page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags); - ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags); - ulint atomic_writes = DICT_TF_GET_ATOMIC_WRITES(table_flags); - ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(fsp_flags); - ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags); - ulint fsp_atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(fsp_flags); - ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags); - ulint fsp_unused = FSP_FLAGS_GET_UNUSED(fsp_flags); - ulint fsp_page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(fsp_flags); - ulint fsp_page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(fsp_flags); - ulint fsp_atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(fsp_flags); - - DBUG_EXECUTE_IF("dict_tf_verify_flags_failure", - return(ULINT_UNDEFINED);); - - ut_a(!table_unused); - ut_a(!fsp_unused); - ut_a(page_ssize == 0 || page_ssize != 0); /* silence compiler */ - ut_a(compact == 0 || compact == 1); /* silence compiler */ - ut_a(data_dir == 0 || data_dir == 1); /* silence compiler */ - ut_a(post_antelope == 0 || post_antelope == 1); /* silence compiler */ - - if (ssize != zip_ssize) { - fprintf(stderr, - "InnoDB: Error: table flags has zip_ssize %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has zip_ssize %ld\n", - ssize, zip_ssize); - return (FALSE); - } - if (atomic_blobs != fsp_atomic_blobs) { - fprintf(stderr, - "InnoDB: Error: table flags has atomic_blobs %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has atomic_blobs %ld\n", - atomic_blobs, fsp_atomic_blobs); - - return (FALSE); - } - if (page_compression != fsp_page_compression) { - fprintf(stderr, - "InnoDB: Error: table flags has page_compression %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file ahas page_compression %ld\n", - page_compression, fsp_page_compression); - - return (FALSE); - } - if (page_compression_level != fsp_page_compression_level) { - fprintf(stderr, - "InnoDB: Error: table flags has page_compression_level %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has page_compression_level %ld\n", - page_compression_level, fsp_page_compression_level); - - return (FALSE); - } - - if (atomic_writes != fsp_atomic_writes) { - fprintf(stderr, - "InnoDB: Error: table flags has atomic writes %ld" - " in the data dictionary\n" - "InnoDB: but the flags in file has atomic_writes %ld\n", - atomic_writes, fsp_atomic_writes); - - return (FALSE); - } - - return(TRUE); -} - /********************************************************************//** Extract the page compression level from dict_table_t::flags. These flags are in memory, so assert that they are valid. diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 38cc09bced3..41e38794ea9 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 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 @@ -45,7 +45,6 @@ Created 10/25/1995 Heikki Tuuri // Forward declaration struct trx_t; -struct fil_space_t; typedef std::list space_name_list_t; @@ -264,10 +263,6 @@ struct fil_space_t { an insert buffer merge request for a page because it actually was for the previous incarnation of the space */ - ibool mark; /*!< this is set to TRUE at database startup if - the space corresponds to a table in the InnoDB - data dictionary; so we can print a warning of - orphaned tablespaces */ ibool stop_ios;/*!< TRUE if we want to rename the .ibd file of tablespace and want to stop temporarily posting of new i/o @@ -296,7 +291,8 @@ struct fil_space_t { /*!< recovered tablespace size in pages; 0 if no size change was read from the redo log, or if the size change was implemented */ - ulint flags; /*!< tablespace flags; see + ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; + see fsp0fsp.h, fsp_flags_is_valid(), fsp_flags_get_zip_size() */ ulint n_reserved_extents; @@ -449,6 +445,7 @@ fil_node_create( ibool is_raw) /*!< in: TRUE if a raw device or a raw disk partition */ MY_ATTRIBUTE((nonnull, warn_unused_result)); + #ifdef UNIV_LOG_ARCHIVE /****************************************************************//** Drops files from the start of a file space, so that its size is cut by @@ -620,7 +617,7 @@ fil_read_first_page( ibool one_read_already, /*!< in: TRUE if min and max parameters below already contain sensible data */ - ulint* flags, /*!< out: tablespace flags */ + ulint* flags, /*!< out: FSP_SPACE_FLAGS */ ulint* space_id, /*!< out: tablespace ID */ lsn_t* min_flushed_lsn, /*!< out: min of flushed lsn values in data files */ @@ -832,6 +829,14 @@ fil_create_new_single_table_tablespace( ulint key_id) /*!< in: encryption key_id */ __attribute__((nonnull, warn_unused_result)); #ifndef UNIV_HOTBACKUP +/** Try to adjust FSP_SPACE_FLAGS if they differ from the expectations. +(Typically when upgrading from MariaDB 10.1.0..10.1.20.) +@param[in] space_id tablespace ID +@param[in] flags desired tablespace flags */ +UNIV_INTERN +void +fsp_flags_try_adjust(ulint space_id, ulint flags); + /********************************************************************//** Tries to open a single-table tablespace and optionally checks the space id is right in it. If does not succeed, prints an error message to the .err log. This @@ -860,7 +865,7 @@ fil_open_single_table_tablespace( bool validate, /*!< in: Do we validate tablespace? */ bool fix_dict, /*!< in: Can we fix the dictionary? */ ulint id, /*!< in: space id */ - ulint flags, /*!< in: tablespace flags */ + ulint flags, /*!< in: expected FSP_SPACE_FLAGS */ const char* tablename, /*!< in: table name in the databasename/tablename format */ const char* filepath, /*!< in: tablespace filepath */ @@ -901,25 +906,18 @@ fil_tablespace_exists_in_mem( /*=========================*/ ulint id); /*!< in: space id */ #ifndef UNIV_HOTBACKUP -/*******************************************************************//** -Returns TRUE if a matching tablespace exists in the InnoDB tablespace memory +/** Check if a matching tablespace exists in the InnoDB tablespace memory cache. Note that if we have not done a crash recovery at the database startup, there may be many tablespaces which are not yet in the memory cache. -@return TRUE if a matching tablespace exists in the memory cache */ +@return whether a matching tablespace exists in the memory cache */ UNIV_INTERN -ibool +bool fil_space_for_table_exists_in_mem( /*==============================*/ ulint id, /*!< in: space id */ const char* name, /*!< in: table name in the standard 'databasename/tablename' format */ - ibool mark_space, /*!< in: in crash recovery, at database - startup we mark all spaces which have - an associated table in the InnoDB - data dictionary, so that - we can print a warning about orphaned - tablespaces */ - ibool print_error_if_does_not_exist, + bool print_error_if_does_not_exist, /*!< in: print detailed error information to the .err log if a matching tablespace is not found from @@ -927,7 +925,8 @@ fil_space_for_table_exists_in_mem( bool adjust_space, /*!< in: whether to adjust space id when find table space mismatch */ mem_heap_t* heap, /*!< in: heap memory */ - table_id_t table_id); /*!< in: table id */ + table_id_t table_id, /*!< in: table id */ + ulint table_flags); /*!< in: table flags */ #else /* !UNIV_HOTBACKUP */ /********************************************************************//** Extends all tablespaces to the size stored in the space header. During the diff --git a/storage/xtradb/include/fil0pagecompress.h b/storage/xtradb/include/fil0pagecompress.h index 10db59fb218..1fe5cb66bf6 100644 --- a/storage/xtradb/include/fil0pagecompress.h +++ b/storage/xtradb/include/fil0pagecompress.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2016 MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017 MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -44,20 +44,11 @@ Returns the page compression flag of the space, or false if the space is not compressed. The tablespace must be cached in the memory cache. @return true if page compressed, false if not or space not found */ UNIV_INLINE -ibool +bool fil_space_is_page_compressed( /*=========================*/ ulint id); /*!< in: space id */ /*******************************************************************//** -Returns the page compression flag of the space, or false if the space -is not compressed. The tablespace must be cached in the memory cache. -@return true if page compressed, false if not or space not found */ -UNIV_INTERN -ibool -fil_space_get_page_compressed( -/*=========================*/ - fil_space_t* space); /*!< in: space id */ -/*******************************************************************//** Returns the atomic writes flag of the space, or false if the space is not using atomic writes. The tablespace must be cached in the memory cache. @return atomic write table option value */ diff --git a/storage/xtradb/include/fsp0fsp.h b/storage/xtradb/include/fsp0fsp.h index 551a8c9ef97..93f98eb0b0b 100644 --- a/storage/xtradb/include/fsp0fsp.h +++ b/storage/xtradb/include/fsp0fsp.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -51,28 +51,67 @@ to the two Barracuda row formats COMPRESSED and DYNAMIC. */ #define FSP_FLAGS_WIDTH_ATOMIC_BLOBS 1 /** Number of flag bits used to indicate the tablespace page size */ #define FSP_FLAGS_WIDTH_PAGE_SSIZE 4 -/** Width of the DATA_DIR flag. This flag indicates that the tablespace -is found in a remote location, not the default data directory. */ -#define FSP_FLAGS_WIDTH_DATA_DIR 1 -/** Number of flag bits used to indicate the page compression and compression level */ -#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1 -#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL 4 +/** Number of reserved bits */ +#define FSP_FLAGS_WIDTH_RESERVED 6 +/** Number of flag bits used to indicate the page compression */ +#define FSP_FLAGS_WIDTH_PAGE_COMPRESSION 1 -/** Number of flag bits used to indicate atomic writes for this tablespace */ -#define FSP_FLAGS_WIDTH_ATOMIC_WRITES 2 - -/** Width of all the currently known tablespace flags */ +/** Width of all the currently known persistent tablespace flags */ #define FSP_FLAGS_WIDTH (FSP_FLAGS_WIDTH_POST_ANTELOPE \ + FSP_FLAGS_WIDTH_ZIP_SSIZE \ + FSP_FLAGS_WIDTH_ATOMIC_BLOBS \ + FSP_FLAGS_WIDTH_PAGE_SSIZE \ - + FSP_FLAGS_WIDTH_DATA_DIR \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL \ - + FSP_FLAGS_WIDTH_ATOMIC_WRITES ) + + FSP_FLAGS_WIDTH_RESERVED \ + + FSP_FLAGS_WIDTH_PAGE_COMPRESSION) -/** A mask of all the known/used bits in tablespace flags */ -#define FSP_FLAGS_MASK (~(~0 << FSP_FLAGS_WIDTH)) +/** A mask of all the known/used bits in FSP_SPACE_FLAGS */ +#define FSP_FLAGS_MASK (~(~0U << FSP_FLAGS_WIDTH)) + +/* FSP_SPACE_FLAGS position and name in MySQL 5.6/MariaDB 10.0 or older +and MariaDB 10.1.20 or older MariaDB 10.1 and in MariaDB 10.1.21 +or newer. +MySQL 5.6 MariaDB 10.1.x MariaDB 10.1.21 +==================================================================== +Below flags in same offset +==================================================================== +0: POST_ANTELOPE 0:POST_ANTELOPE 0: POST_ANTELOPE +1..4: ZIP_SSIZE(0..5) 1..4:ZIP_SSIZE(0..5) 1..4: ZIP_SSIZE(0..5) +(NOTE: bit 4 is always 0) +5: ATOMIC_BLOBS 5:ATOMIC_BLOBS 5: ATOMIC_BLOBS +===================================================================== +Below note the order difference: +===================================================================== +6..9: PAGE_SSIZE(3..7) 6: COMPRESSION 6..9: PAGE_SSIZE(3..7) +10: DATA_DIR 7..10: COMP_LEVEL(0..9) 10: RESERVED (5.6 DATA_DIR) +===================================================================== +The flags below were in incorrect position in MariaDB 10.1, +or have been introduced in MySQL 5.7 or 8.0: +===================================================================== +11: UNUSED 11..12:ATOMIC_WRITES 11: RESERVED (5.7 SHARED) + 12: RESERVED (5.7 TEMPORARY) + 13..15:PAGE_SSIZE(3..7) 13: RESERVED (5.7 ENCRYPTION) + 14: RESERVED (8.0 SDI) + 15: RESERVED + 16: PAGE_SSIZE_msb(0) 16: COMPRESSION + 17: DATA_DIR 17: UNUSED + 18: UNUSED +===================================================================== +The flags below only exist in fil_space_t::flags, not in FSP_SPACE_FLAGS: +===================================================================== + 25: DATA_DIR + 26..27: ATOMIC_WRITES + 28..31: COMPRESSION_LEVEL +*/ + +/** A mask of the memory-only flags in fil_space_t::flags */ +#define FSP_FLAGS_MEM_MASK (~0U << FSP_FLAGS_MEM_DATA_DIR) + +/** Zero relative shift position of the DATA_DIR flag */ +#define FSP_FLAGS_MEM_DATA_DIR 25 +/** Zero relative shift position of the ATOMIC_WRITES field */ +#define FSP_FLAGS_MEM_ATOMIC_WRITES 26 +/** Zero relative shift position of the COMPRESSION_LEVEL field */ +#define FSP_FLAGS_MEM_COMPRESSION_LEVEL 28 /** Zero relative shift position of the POST_ANTELOPE field */ #define FSP_FLAGS_POS_POST_ANTELOPE 0 @@ -82,29 +121,16 @@ is found in a remote location, not the default data directory. */ /** Zero relative shift position of the ATOMIC_BLOBS field */ #define FSP_FLAGS_POS_ATOMIC_BLOBS (FSP_FLAGS_POS_ZIP_SSIZE \ + FSP_FLAGS_WIDTH_ZIP_SSIZE) -/** Note that these need to be before the page size to be compatible with -dictionary */ +/** Zero relative shift position of the start of the PAGE_SSIZE bits */ +#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_BLOBS \ + + FSP_FLAGS_WIDTH_ATOMIC_BLOBS) +/** Zero relative shift position of the start of the RESERVED bits +these are only used in MySQL 5.7 and used for compatibility. */ +#define FSP_FLAGS_POS_RESERVED (FSP_FLAGS_POS_PAGE_SSIZE \ + + FSP_FLAGS_WIDTH_PAGE_SSIZE) /** Zero relative shift position of the PAGE_COMPRESSION field */ -#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_ATOMIC_BLOBS \ - + FSP_FLAGS_WIDTH_ATOMIC_BLOBS) -/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */ -#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL (FSP_FLAGS_POS_PAGE_COMPRESSION \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION) -/** Zero relative shift position of the ATOMIC_WRITES field */ -#define FSP_FLAGS_POS_ATOMIC_WRITES (FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL \ - + FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL) -/** Zero relative shift position of the PAGE_SSIZE field */ -#define FSP_FLAGS_POS_PAGE_SSIZE (FSP_FLAGS_POS_ATOMIC_WRITES \ - + FSP_FLAGS_WIDTH_ATOMIC_WRITES) -/** Zero relative shift position of the start of the DATA DIR bits */ -#define FSP_FLAGS_POS_DATA_DIR (FSP_FLAGS_POS_PAGE_SSIZE \ - + FSP_FLAGS_WIDTH_PAGE_SSIZE) -#define FSP_FLAGS_POS_DATA_DIR_ORACLE (FSP_FLAGS_POS_ATOMIC_BLOBS \ - + FSP_FLAGS_WIDTH_ATOMIC_BLOBS \ - + FSP_FLAGS_WIDTH_PAGE_SSIZE) -/** Zero relative shift position of the start of the UNUSED bits */ -#define FSP_FLAGS_POS_UNUSED (FSP_FLAGS_POS_DATA_DIR\ - + FSP_FLAGS_WIDTH_DATA_DIR) +#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_RESERVED \ + + FSP_FLAGS_WIDTH_RESERVED) /** Bit mask of the POST_ANTELOPE field */ #define FSP_FLAGS_MASK_POST_ANTELOPE \ @@ -122,26 +148,23 @@ dictionary */ #define FSP_FLAGS_MASK_PAGE_SSIZE \ ((~(~0U << FSP_FLAGS_WIDTH_PAGE_SSIZE)) \ << FSP_FLAGS_POS_PAGE_SSIZE) -/** Bit mask of the DATA_DIR field */ -#define FSP_FLAGS_MASK_DATA_DIR \ - ((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \ - << FSP_FLAGS_POS_DATA_DIR) -/** Bit mask of the DATA_DIR field */ -#define FSP_FLAGS_MASK_DATA_DIR_ORACLE \ - ((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \ - << FSP_FLAGS_POS_DATA_DIR_ORACLE) +/** Bit mask of the RESERVED1 field */ +#define FSP_FLAGS_MASK_RESERVED \ + ((~(~0U << FSP_FLAGS_WIDTH_RESERVED)) \ + << FSP_FLAGS_POS_RESERVED) /** Bit mask of the PAGE_COMPRESSION field */ -#define FSP_FLAGS_MASK_PAGE_COMPRESSION \ +#define FSP_FLAGS_MASK_PAGE_COMPRESSION \ ((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \ << FSP_FLAGS_POS_PAGE_COMPRESSION) -/** Bit mask of the PAGE_COMPRESSION_LEVEL field */ -#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL \ - ((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION_LEVEL)) \ - << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL) -/** Bit mask of the ATOMIC_WRITES field */ -#define FSP_FLAGS_MASK_ATOMIC_WRITES \ - ((~(~0U << FSP_FLAGS_WIDTH_ATOMIC_WRITES)) \ - << FSP_FLAGS_POS_ATOMIC_WRITES) + +/** Bit mask of the in-memory ATOMIC_WRITES field */ +#define FSP_FLAGS_MASK_MEM_ATOMIC_WRITES \ + (3U << FSP_FLAGS_MEM_ATOMIC_WRITES) + +/** Bit mask of the in-memory COMPRESSION_LEVEL field */ +#define FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL \ + (15U << FSP_FLAGS_MEM_COMPRESSION_LEVEL) + /** Return the value of the POST_ANTELOPE field */ #define FSP_FLAGS_GET_POST_ANTELOPE(flags) \ ((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \ @@ -158,48 +181,78 @@ dictionary */ #define FSP_FLAGS_GET_PAGE_SSIZE(flags) \ ((flags & FSP_FLAGS_MASK_PAGE_SSIZE) \ >> FSP_FLAGS_POS_PAGE_SSIZE) -/** Return the value of the DATA_DIR field */ -#define FSP_FLAGS_HAS_DATA_DIR(flags) \ - ((flags & FSP_FLAGS_MASK_DATA_DIR) \ - >> FSP_FLAGS_POS_DATA_DIR) -#define FSP_FLAGS_HAS_DATA_DIR_ORACLE(flags) \ - ((flags & FSP_FLAGS_MASK_DATA_DIR_ORACLE) \ - >> FSP_FLAGS_POS_DATA_DIR_ORACLE) +/** @return the RESERVED flags */ +#define FSP_FLAGS_GET_RESERVED(flags) \ + ((flags & FSP_FLAGS_MASK_RESERVED) \ + >> FSP_FLAGS_POS_RESERVED) +/** @return the PAGE_COMPRESSION flag */ +#define FSP_FLAGS_HAS_PAGE_COMPRESSION(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \ + >> FSP_FLAGS_POS_PAGE_COMPRESSION) + /** Return the contents of the UNUSED bits */ #define FSP_FLAGS_GET_UNUSED(flags) \ (flags >> FSP_FLAGS_POS_UNUSED) -/** Return the value of the PAGE_COMPRESSION field */ -#define FSP_FLAGS_GET_PAGE_COMPRESSION(flags) \ - ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \ - >> FSP_FLAGS_POS_PAGE_COMPRESSION) -/** Return the value of the PAGE_COMPRESSION_LEVEL field */ + +/** @return the PAGE_SSIZE flags for the current innodb_page_size */ +#define FSP_FLAGS_PAGE_SSIZE() \ + ((UNIV_PAGE_SIZE == UNIV_PAGE_SIZE_ORIG) ? \ + 0 : (UNIV_PAGE_SIZE_SHIFT - UNIV_ZIP_SIZE_SHIFT_MIN + 1) \ + << FSP_FLAGS_POS_PAGE_SSIZE) + +/** @return the value of the DATA_DIR field */ +#define FSP_FLAGS_HAS_DATA_DIR(flags) \ + (flags & 1U << FSP_FLAGS_MEM_DATA_DIR) +/** @return the COMPRESSION_LEVEL field */ #define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags) \ - ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL) \ - >> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL) -/** Return the value of the ATOMIC_WRITES field */ -#define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \ - ((flags & FSP_FLAGS_MASK_ATOMIC_WRITES) \ - >> FSP_FLAGS_POS_ATOMIC_WRITES) + ((flags & FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL) \ + >> FSP_FLAGS_MEM_COMPRESSION_LEVEL) +/** @return the ATOMIC_WRITES field */ +#define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \ + ((flags & FSP_FLAGS_MASK_MEM_ATOMIC_WRITES) \ + >> FSP_FLAGS_MEM_ATOMIC_WRITES) -/** Set a PAGE_SSIZE into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize) \ - (flags | (ssize << FSP_FLAGS_POS_PAGE_SSIZE)) +/* Compatibility macros for MariaDB 10.1.20 or older 10.1 see +table above. */ +/** Zero relative shift position of the PAGE_COMPRESSION field */ +#define FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 \ + (FSP_FLAGS_POS_ATOMIC_BLOBS \ + + FSP_FLAGS_WIDTH_ATOMIC_BLOBS) +/** Zero relative shift position of the PAGE_COMPRESSION_LEVEL field */ +#define FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 \ + (FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101 + 1) +/** Zero relative shift position of the ATOMIC_WRITES field */ +#define FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 \ + (FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101 + 4) +/** Zero relative shift position of the PAGE_SSIZE field */ +#define FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101 \ + (FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101 + 2) -/** Set a PAGE_COMPRESSION into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_PAGE_COMPRESSION(flags, compression) \ - (flags | (compression << FSP_FLAGS_POS_PAGE_COMPRESSION)) +/** Bit mask of the PAGE_COMPRESSION field */ +#define FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101 \ + (1U << FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101) +/** Bit mask of the PAGE_COMPRESSION_LEVEL field */ +#define FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101 \ + (15U << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101) +/** Bit mask of the ATOMIC_WRITES field */ +#define FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101 \ + (3U << FSP_FLAGS_POS_ATOMIC_WRITES_MARIADB101) +/** Bit mask of the PAGE_SSIZE field */ +#define FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101 \ + (15U << FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101) -/** Set a PAGE_COMPRESSION_LEVEL into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_PAGE_COMPRESSION_LEVEL(flags, level) \ - (flags | (level << FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL)) - -/** Set a ATOMIC_WRITES into the correct bits in a given -tablespace flags. */ -#define FSP_FLAGS_SET_ATOMIC_WRITES(flags, atomics) \ - (flags | (atomics << FSP_FLAGS_POS_ATOMIC_WRITES)) +/** Return the value of the PAGE_COMPRESSION field */ +#define FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_MARIADB101) \ + >> FSP_FLAGS_POS_PAGE_COMPRESSION_MARIADB101) +/** Return the value of the PAGE_COMPRESSION_LEVEL field */ +#define FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION_LEVEL_MARIADB101) \ + >> FSP_FLAGS_POS_PAGE_COMPRESSION_LEVEL_MARIADB101) +/** Return the value of the PAGE_SSIZE field */ +#define FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags) \ + ((flags & FSP_FLAGS_MASK_PAGE_SSIZE_MARIADB101) \ + >> FSP_FLAGS_POS_PAGE_SSIZE_MARIADB101) /* @} */ @@ -733,19 +786,193 @@ fseg_print( mtr_t* mtr); /*!< in/out: mini-transaction */ #endif /* UNIV_BTR_PRINT */ -/********************************************************************//** -Validate and return the tablespace flags, which are stored in the -tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for -ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats, -COMPRESSED and DYNAMIC, use a file format > Antelope so they should -have a file format number plus the DICT_TF_COMPACT bit set. -@return true if check ok */ +/** Validate the tablespace flags, which are stored in the +tablespace header at offset FSP_SPACE_FLAGS. +@param[in] flags the contents of FSP_SPACE_FLAGS +@return whether the flags are correct (not in the buggy 10.1) format */ +MY_ATTRIBUTE((warn_unused_result, const)) UNIV_INLINE bool -fsp_flags_is_valid( -/*===============*/ - ulint flags) /*!< in: tablespace flags */ - MY_ATTRIBUTE((warn_unused_result, const)); +fsp_flags_is_valid(ulint flags) +{ + DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", + return(false);); + if (flags == 0) { + return(true); + } + if (flags & ~FSP_FLAGS_MASK) { + return(false); + } + if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS)) + == FSP_FLAGS_MASK_ATOMIC_BLOBS) { + /* If the "atomic blobs" flag (indicating + ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag + is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag + must also be set. */ + return(false); + } + /* Bits 10..14 should be 0b0000d where d is the DATA_DIR flag + of MySQL 5.6 and MariaDB 10.0, which we ignore. + In the buggy FSP_SPACE_FLAGS written by MariaDB 10.1.0 to 10.1.20, + bits 10..14 would be nonzero 0bsssaa where sss is + nonzero PAGE_SSIZE (3, 4, 6, or 7) + and aa is ATOMIC_WRITES (not 0b11). */ + if (FSP_FLAGS_GET_RESERVED(flags) & ~1) { + return(false); + } + + const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); + if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) { + /* the page_size is not between 4k and 64k; + 16k should be encoded as 0, not 5 */ + return(false); + } + const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); + if (zssize == 0) { + /* not ROW_FORMAT=COMPRESSED */ + } else if (zssize > (ssize ? ssize : 5)) { + /* invalid KEY_BLOCK_SIZE */ + return(false); + } else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE + | FSP_FLAGS_MASK_ATOMIC_BLOBS)) { + /* both these flags should be set for + ROW_FORMAT=COMPRESSED */ + return(false); + } + + return(true); +} + +/** Convert FSP_SPACE_FLAGS from the buggy MariaDB 10.1.0..10.1.20 format. +@param[in] flags the contents of FSP_SPACE_FLAGS +@return the flags corrected from the buggy MariaDB 10.1 format +@retval ULINT_UNDEFINED if the flags are not in the buggy 10.1 format */ +MY_ATTRIBUTE((warn_unused_result, const)) +UNIV_INLINE +ulint +fsp_flags_convert_from_101(ulint flags) +{ + DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", + return(ULINT_UNDEFINED);); + if (flags == 0) { + return(flags); + } + + if (flags >> 18) { + /* The most significant FSP_SPACE_FLAGS bit that was ever set + by MariaDB 10.1.0 to 10.1.20 was bit 17 (misplaced DATA_DIR flag). + The flags must be less than 1<<18 in order to be valid. */ + return(ULINT_UNDEFINED); + } + + if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS)) + == FSP_FLAGS_MASK_ATOMIC_BLOBS) { + /* If the "atomic blobs" flag (indicating + ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag + is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag + must also be set. */ + return(ULINT_UNDEFINED); + } + + /* Bits 6..10 denote compression in MariaDB 10.1.0 to 10.1.20. + They must be either 0b00000 or 0b00011 through 0b10011. + In correct versions, these bits would be + 0bd0sss where d is the DATA_DIR flag (garbage bit) and + sss is the PAGE_SSIZE (3, 4, 6, or 7). + + NOTE: MariaDB 10.1.0 to 10.1.20 can misinterpret + uncompressed data files with innodb_page_size=4k or 64k as + compressed innodb_page_size=16k files. Below is an exhaustive + state space analysis. + + -0by1zzz: impossible (the bit 4 must be clean; see above) + -0b101xx: DATA_DIR, innodb_page_size>4k: invalid (COMPRESSION_LEVEL>9) + +0bx0011: innodb_page_size=4k: + !!! Misinterpreted as COMPRESSION_LEVEL=9 or 1, COMPRESSION=1. + -0bx0010: impossible, because sss must be 0b011 or 0b1xx + -0bx0001: impossible, because sss must be 0b011 or 0b1xx + -0b10000: DATA_DIR, innodb_page_size=16: + invalid (COMPRESSION_LEVEL=8 but COMPRESSION=0) + +0b00111: no DATA_DIR, innodb_page_size=64k: + !!! Misinterpreted as COMPRESSION_LEVEL=3, COMPRESSION=1. + -0b00101: impossible, because sss must be 0 for 16k, not 0b101 + -0b001x0: no DATA_DIR, innodb_page_size=32k or 8k: + invalid (COMPRESSION_LEVEL=3 but COMPRESSION=0) + +0b00000: innodb_page_size=16k (looks like COMPRESSION=0) + ??? Could actually be compressed; see PAGE_SSIZE below */ + const ulint level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL_MARIADB101( + flags); + if (FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) != (level != 0) + || level > 9) { + /* The compression flags are not in the buggy MariaDB + 10.1 format. */ + return(ULINT_UNDEFINED); + } + if (!(~flags & FSP_FLAGS_MASK_ATOMIC_WRITES_MARIADB101)) { + /* The ATOMIC_WRITES flags cannot be 0b11. + (The bits 11..12 should actually never be 0b11, + because in MySQL they would be SHARED|TEMPORARY.) */ + return(ULINT_UNDEFINED); + } + + /* Bits 13..16 are the wrong position for PAGE_SSIZE, and they + should contain one of the values 3,4,6,7, that is, be of the form + 0b0011 or 0b01xx (except 0b0110). + In correct versions, these bits should be 0bc0se + where c is the MariaDB COMPRESSED flag + and e is the MySQL 5.7 ENCRYPTION flag + and s is the MySQL 8.0 SDI flag. MariaDB can only support s=0, e=0. + + Compressed innodb_page_size=16k tables with correct FSP_SPACE_FLAGS + will be properly rejected by older MariaDB 10.1.x because they + would read as PAGE_SSIZE>=8 which is not valid. */ + + const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE_MARIADB101(flags); + if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) { + /* the page_size is not between 4k and 64k; + 16k should be encoded as 0, not 5 */ + return(ULINT_UNDEFINED); + } + const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); + if (zssize == 0) { + /* not ROW_FORMAT=COMPRESSED */ + } else if (zssize > (ssize ? ssize : 5)) { + /* invalid KEY_BLOCK_SIZE */ + return(ULINT_UNDEFINED); + } else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE + | FSP_FLAGS_MASK_ATOMIC_BLOBS)) { + /* both these flags should be set for + ROW_FORMAT=COMPRESSED */ + return(ULINT_UNDEFINED); + } + + flags = ((flags & 0x3f) | ssize << FSP_FLAGS_POS_PAGE_SSIZE + | FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags) + << FSP_FLAGS_POS_PAGE_COMPRESSION); + ut_ad(fsp_flags_is_valid(flags)); + return(flags); +} + +/** Compare tablespace flags. +@param[in] expected expected flags from dict_tf_to_fsp_flags() +@param[in] actual flags read from FSP_SPACE_FLAGS +@return whether the flags match */ +MY_ATTRIBUTE((warn_unused_result)) +UNIV_INLINE +bool +fsp_flags_match(ulint expected, ulint actual) +{ + expected &= ~FSP_FLAGS_MEM_MASK; + ut_ad(fsp_flags_is_valid(expected)); + + if (actual == expected) { + return(true); + } + + actual = fsp_flags_convert_from_101(actual); + return(actual == expected); +} + /********************************************************************//** Determine if the tablespace is compressed from dict_table_t::flags. @return TRUE if compressed, FALSE if not compressed */ diff --git a/storage/xtradb/include/fsp0fsp.ic b/storage/xtradb/include/fsp0fsp.ic index ddcb87b0e57..ee4cb1f32c7 100644 --- a/storage/xtradb/include/fsp0fsp.ic +++ b/storage/xtradb/include/fsp0fsp.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, SkySQL Ab. All Rights Reserved. +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 @@ -46,107 +46,6 @@ fsp_descr_page( return((page_no & (zip_size - 1)) == FSP_XDES_OFFSET); } -/********************************************************************//** -Validate and return the tablespace flags, which are stored in the -tablespace header at offset FSP_SPACE_FLAGS. They should be 0 for -ROW_FORMAT=COMPACT and ROW_FORMAT=REDUNDANT. The newer row formats, -COMPRESSED and DYNAMIC, use a file format > Antelope so they should -have a file format number plus the DICT_TF_COMPACT bit set. -@return true if check ok */ -UNIV_INLINE -bool -fsp_flags_is_valid( -/*===============*/ - ulint flags) /*!< in: tablespace flags */ -{ - ulint post_antelope = FSP_FLAGS_GET_POST_ANTELOPE(flags); - ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); - ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags); - ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); - ulint unused = FSP_FLAGS_GET_UNUSED(flags); - ulint page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags); - ulint page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags); - ulint atomic_writes = FSP_FLAGS_GET_ATOMIC_WRITES(flags); - - DBUG_EXECUTE_IF("fsp_flags_is_valid_failure", return(false);); - - /* fsp_flags is zero unless atomic_blobs is set. */ - /* Make sure there are no bits that we do not know about. */ - if (unused != 0 || flags == 1) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted unused %lu\n", - flags, unused); - return(false); - } else if (post_antelope) { - /* The Antelope row formats REDUNDANT and COMPACT did - not use tablespace flags, so this flag and the entire - 4-byte field is zero for Antelope row formats. */ - - if (!atomic_blobs) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_blobs %lu\n", - flags, atomic_blobs); - return(false); - } - } - - if (!atomic_blobs) { - /* Barracuda row formats COMPRESSED and DYNAMIC build on - the page structure introduced for the COMPACT row format - by allowing long fields to be broken into prefix and - externally stored parts. */ - - if (post_antelope || zip_ssize != 0) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu atomic_blobs %lu\n", - flags, zip_ssize, atomic_blobs); - return(false); - } - - } else if (!post_antelope || zip_ssize > PAGE_ZIP_SSIZE_MAX) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted zip_ssize %lu max %d\n", - flags, zip_ssize, PAGE_ZIP_SSIZE_MAX); - return(false); - } else if (page_ssize > UNIV_PAGE_SSIZE_MAX) { - - /* The page size field can be used for any row type, or it may - be zero for an original 16k page size. - Validate the page shift size is within allowed range. */ - - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu\n", - flags, page_ssize, UNIV_PAGE_SSIZE_MAX); - return(false); - - } else if (UNIV_PAGE_SIZE != UNIV_PAGE_SIZE_ORIG && !page_ssize) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_ssize %lu max %lu:%d\n", - flags, page_ssize, UNIV_PAGE_SIZE, UNIV_PAGE_SIZE_ORIG); - return(false); - } - -#if UNIV_FORMAT_MAX != UNIV_FORMAT_B -# error "UNIV_FORMAT_MAX != UNIV_FORMAT_B, Add more validations." -#endif - - /* Page compression level requires page compression and atomic blobs - to be set */ - if (page_compression_level || page_compression) { - if (!page_compression || !atomic_blobs) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted page_compression %lu\n" - "InnoDB: Error: page_compression_level %lu atomic_blobs %lu\n", - flags, page_compression, page_compression_level, atomic_blobs); - return(false); - } - } - - if (atomic_writes > ATOMIC_WRITES_OFF) { - fprintf(stderr, "InnoDB: Error: Tablespace flags %lu corrupted atomic_writes %lu\n", - flags, atomic_writes); - return (false); - } - - /* The DATA_DIR field can be used for any row type so there is - nothing here to validate. */ - - return(true); -} - /********************************************************************//** Determine if the tablespace is compressed from dict_table_t::flags. @return TRUE if compressed, FALSE if not compressed */ @@ -191,10 +90,10 @@ UNIV_INLINE ulint fsp_flags_get_page_size( /*====================*/ - ulint flags) /*!< in: tablespace flags */ + ulint flags) /*!< in: tablespace flags */ { - ulint page_size = 0; - ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); + ulint page_size = 0; + ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); /* Convert from a 'log2 minus 9' to a page size in bytes. */ if (UNIV_UNLIKELY(ssize)) { @@ -211,50 +110,6 @@ fsp_flags_get_page_size( } #ifndef UNIV_INNOCHECKSUM - -/********************************************************************//** -Add the page size to the tablespace flags. -@return tablespace flags after page size is added */ -UNIV_INLINE -ulint -fsp_flags_set_page_size( -/*====================*/ - ulint flags, /*!< in: tablespace flags */ - ulint page_size) /*!< in: page size in bytes */ -{ - ulint ssize = 0; - ulint shift; - - /* Page size should be > UNIV_PAGE_SIZE_MIN */ - ut_ad(page_size >= UNIV_PAGE_SIZE_MIN); - ut_ad(page_size <= UNIV_PAGE_SIZE_MAX); - - if (page_size == UNIV_PAGE_SIZE_ORIG) { - ut_ad(0 == FSP_FLAGS_GET_PAGE_SSIZE(flags)); - return(flags); - } - - for (shift = UNIV_PAGE_SIZE_SHIFT_MAX; - shift >= UNIV_PAGE_SIZE_SHIFT_MIN; - shift--) { - ulint mask = (1 << shift); - if (page_size & mask) { - ut_ad(!(page_size & ~mask)); - ssize = shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1; - break; - } - } - - ut_ad(ssize); - ut_ad(ssize <= UNIV_PAGE_SSIZE_MAX); - - flags = FSP_FLAGS_SET_PAGE_SSIZE(flags, ssize); - - ut_ad(fsp_flags_is_valid(flags)); - - return(flags); -} - /********************************************************************//** Calculates the descriptor index within a descriptor page. @return descriptor index */ diff --git a/storage/xtradb/include/fsp0pagecompress.h b/storage/xtradb/include/fsp0pagecompress.h index 5f943ee2b83..c623d11c326 100644 --- a/storage/xtradb/include/fsp0pagecompress.h +++ b/storage/xtradb/include/fsp0pagecompress.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -47,15 +47,6 @@ fsp_header_get_compression_level( /*=============================*/ const page_t* page); /*!< in: first page of a tablespace */ -/********************************************************************//** -Determine if the tablespace is page compressed from dict_table_t::flags. -@return TRUE if page compressed, FALSE if not compressed */ -UNIV_INLINE -ibool -fsp_flags_is_page_compressed( -/*=========================*/ - ulint flags); /*!< in: tablespace flags */ - /********************************************************************//** Extract the page compression level from tablespace flags. A tablespace has only one physical page compression level diff --git a/storage/xtradb/include/fsp0pagecompress.ic b/storage/xtradb/include/fsp0pagecompress.ic index e879aa2c16e..48163277feb 100644 --- a/storage/xtradb/include/fsp0pagecompress.ic +++ b/storage/xtradb/include/fsp0pagecompress.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2015, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -25,18 +25,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@mariadb.com ***********************************************************************/ -/********************************************************************//** -Determine if the tablespace is page compressed from dict_table_t::flags. -@return TRUE if page compressed, FALSE if not page compressed */ -UNIV_INLINE -ibool -fsp_flags_is_page_compressed( -/*=========================*/ - ulint flags) /*!< in: tablespace flags */ -{ - return(FSP_FLAGS_GET_PAGE_COMPRESSION(flags)); -} - /********************************************************************//** Determine the tablespace is page compression level from dict_table_t::flags. @return page compression level or 0 if not compressed*/ @@ -125,21 +113,15 @@ Extract the page compression from space. @return true if space is page compressed, false if space is not found or space is not page compressed. */ UNIV_INLINE -ibool +bool fil_space_is_page_compressed( /*=========================*/ ulint id) /*!< in: space id */ { - ulint flags; + ulint flags = fil_space_get_flags(id); - flags = fil_space_get_flags(id); - - if (flags && flags != ULINT_UNDEFINED) { - - return(fsp_flags_is_page_compressed(flags)); - } - - return(0); + return(flags != ULINT_UNDEFINED + && FSP_FLAGS_HAS_PAGE_COMPRESSION(flags)); } #endif /* UNIV_INNOCHECKSUM */ diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index d45ce907304..6170eb66195 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -371,8 +371,7 @@ public: m_space(ULINT_UNDEFINED), m_xdes(), m_xdes_page_no(ULINT_UNDEFINED), - m_space_flags(ULINT_UNDEFINED), - m_table_flags(ULINT_UNDEFINED) UNIV_NOTHROW { } + m_space_flags(ULINT_UNDEFINED) UNIV_NOTHROW { } /** Free any extent descriptor instance */ @@ -535,10 +534,6 @@ protected: /** Flags value read from the header page */ ulint m_space_flags; - - /** Derived from m_space_flags and row format type, the row format - type is determined from the page header. */ - ulint m_table_flags; }; /** Determine the page size to use for traversing the tablespace @@ -553,6 +548,19 @@ AbstractCallback::init( const page_t* page = block->frame; m_space_flags = fsp_header_get_flags(page); + if (!fsp_flags_is_valid(m_space_flags)) { + ulint cflags = fsp_flags_convert_from_101(m_space_flags); + if (cflags == ULINT_UNDEFINED) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Invalid FSP_SPACE_FLAGS=0x%x", + int(m_space_flags)); + return(DB_CORRUPTION); + } + m_space_flags = cflags; + } + + /* Clear the DATA_DIR flag, which is basically garbage. */ + m_space_flags &= ~(1U << FSP_FLAGS_POS_RESERVED); /* Since we don't know whether it is a compressed table or not, the data is always read into the block->frame. */ @@ -640,46 +648,6 @@ struct FetchIndexRootPages : public AbstractCallback { return(m_space); } - /** - Check if the .ibd file row format is the same as the table's. - @param ibd_table_flags - determined from space and page. - @return DB_SUCCESS or error code. */ - dberr_t check_row_format(ulint ibd_table_flags) UNIV_NOTHROW - { - dberr_t err; - rec_format_t ibd_rec_format; - rec_format_t table_rec_format; - - if (!dict_tf_is_valid(ibd_table_flags)) { - - ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - ".ibd file has invlad table flags: %lx", - ibd_table_flags); - - return(DB_CORRUPTION); - } - - ibd_rec_format = dict_tf_get_rec_format(ibd_table_flags); - table_rec_format = dict_tf_get_rec_format(m_table->flags); - - if (table_rec_format != ibd_rec_format) { - - ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Table has %s row format, .ibd " - "file has %s row format.", - dict_tf_to_row_format_string(m_table->flags), - dict_tf_to_row_format_string(ibd_table_flags)); - - err = DB_CORRUPTION; - } else { - err = DB_SUCCESS; - } - - return(err); - } - /** Called for each block as it is read from the file. @param offset - physical offset in the file @@ -743,12 +711,17 @@ FetchIndexRootPages::operator() ( m_indexes.push_back(Index(id, page_no)); if (m_indexes.size() == 1) { - - m_table_flags = dict_sys_tables_type_to_tf( - m_space_flags, - page_is_comp(page) ? DICT_N_COLS_COMPACT : 0); - - err = check_row_format(m_table_flags); + /* Check that the tablespace flags match the table flags. */ + ulint expected = dict_tf_to_fsp_flags(m_table->flags); + if (!fsp_flags_match(expected, m_space_flags)) { + ib_errf(m_trx->mysql_thd, IB_LOG_LEVEL_ERROR, + ER_TABLE_SCHEMA_MISMATCH, + "Expected FSP_SPACE_FLAGS=0x%x, .ibd " + "file contains 0x%x.", + unsigned(expected), + unsigned(m_space_flags)); + return(DB_CORRUPTION); + } } } @@ -1968,21 +1941,14 @@ PageConverter::update_header( "- ignored"); } - ulint space_flags = fsp_header_get_flags(get_frame(block)); - - if (!fsp_flags_is_valid(space_flags)) { - - ib_logf(IB_LOG_LEVEL_ERROR, - "Unsupported tablespace format %lu", - (ulong) space_flags); - - return(DB_UNSUPPORTED); - } - mach_write_to_8( get_frame(block) + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, m_current_lsn); + /* Write back the adjusted flags. */ + mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + + get_frame(block), m_space_flags); + /* Write space_id to the tablespace header, page 0. */ mach_write_to_4( get_frame(block) + FSP_HEADER_OFFSET + FSP_SPACE_ID, diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index aff7b758249..c81b10b93f1 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -4362,6 +4362,7 @@ row_drop_table_for_mysql( switch (err) { ibool is_temp; + ulint table_flags; case DB_SUCCESS: /* Clone the name, in case it has been allocated @@ -4370,6 +4371,7 @@ row_drop_table_for_mysql( space_id = table->space; ibd_file_missing = table->ibd_file_missing; + table_flags = table->flags; is_temp = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY); /* If there is a temp path then the temp flag is set. @@ -4385,9 +4387,9 @@ row_drop_table_for_mysql( } /* We do not allow temporary tables with a remote path. */ - ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table->flags))); + ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table_flags))); - if (space_id && DICT_TF_HAS_DATA_DIR(table->flags)) { + if (space_id && DICT_TF_HAS_DATA_DIR(table_flags)) { dict_get_and_save_data_dir_path(table, true); ut_a(table->data_dir_path); @@ -4453,8 +4455,9 @@ row_drop_table_for_mysql( if (err == DB_SUCCESS && space_id > TRX_SYS_SPACE) { if (!is_temp && !fil_space_for_table_exists_in_mem( - space_id, tablename, FALSE, - print_msg, false, NULL, 0)) { + space_id, tablename, + print_msg, false, NULL, 0, + table_flags)) { /* This might happen if we are dropping a discarded tablespace */ err = DB_SUCCESS; diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 77cdfe1affb..b933171e683 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -703,8 +703,7 @@ create_log_files( sprintf(logfilename + dirnamelen, "ib_logfile%u", INIT_LOG_FILE0); fil_space_create( - logfilename, SRV_LOG_SPACE_FIRST_ID, - fsp_flags_set_page_size(0, UNIV_PAGE_SIZE), + logfilename, SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG, NULL /* no encryption yet */, true /* this is create */); @@ -1193,7 +1192,7 @@ check_first_page: crypt_data = fil_space_create_crypt_data(FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); } - flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE); + flags = FSP_FLAGS_PAGE_SSIZE(); fil_space_create(name, 0, flags, FIL_TABLESPACE, crypt_data, (*create_new_db) == true); @@ -1341,7 +1340,7 @@ srv_undo_tablespace_open( fil_set_max_space_id_if_bigger(space); /* Set the compressed page size to 0 (non-compressed) */ - flags = fsp_flags_set_page_size(0, UNIV_PAGE_SIZE); + flags = FSP_FLAGS_PAGE_SSIZE(); fil_space_create(name, space, flags, FIL_TABLESPACE, NULL /* no encryption */, true /* create */); @@ -2374,9 +2373,7 @@ innobase_start_or_create_for_mysql(void) sprintf(logfilename + dirnamelen, "ib_logfile%u", 0); fil_space_create(logfilename, - SRV_LOG_SPACE_FIRST_ID, - fsp_flags_set_page_size(0, UNIV_PAGE_SIZE), - FIL_LOG, + SRV_LOG_SPACE_FIRST_ID, 0, FIL_LOG, NULL /* no encryption yet */, true /* create */); @@ -2771,6 +2768,13 @@ files_checked: } if (!srv_read_only_mode) { + const ulint flags = FSP_FLAGS_PAGE_SSIZE(); + for (ulint id = 0; id <= srv_undo_tablespaces; id++) { + if (fil_space_get(id)) { + fsp_flags_try_adjust(id, flags); + } + } + /* Create the thread which watches the timeouts for lock waits */ thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create( From 34c89d01d285f4e08de2bbb940e30cabffdf1548 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Mon, 16 Jan 2017 01:27:26 +0200 Subject: [PATCH 076/167] Updated list of unstable tests for 10.1.21 --- mysql-test/unstable-tests | 144 +++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 55 deletions(-) diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index 7b5c2756f11..42985e1d66d 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -23,66 +23,83 @@ # ############################################################################## -main.alter_table : Modified in 10.1.19 -main.analyze_stmt_slow_query_log : MDEV-7558 - wrong result -main.create : Modified in 10.1.20 +main.alter_table : Modified in 10.1.21 +main.alter_table_trans : MDEV-11805 - timeout +main.analyze_stmt_slow_query_log : Modified in 10.1.21 +main.cast : Modified in 10.1.21 +main.create : Modified in 10.1.21 main.create_delayed : MDEV-10605 - failed with timeout main.create_drop_binlog : Uses binlog_start_pos.inc modified in 10.1.20 -main.create_or_replace : Modified in 10.1.19 +main.ctype_ucs : Modified in 10.1.21 +main.ctype_ucs2_def : Modified in 10.1.21 +main.ctype_ucs2_query_cache : Modified in 10.1.21 +main.ctype_utf16 : Modified in 10.1.21 +main.ctype_utf16_def : Modified in 10.1.21 main.ctype_utf16le : MDEV-10675: timeout or extra warnings +main.ctype_utf32 : Modified in 10.1.21 main.ctype_utf8 : Modified in 10.1.20 main.ctype_utf8mb4 : Modified in 10.1.20 main.default : Modified in 10.1.20 main.derived : Modified in 10.1.20 main.derived_view : Modified in 10.1.20 -main.drop : Modified in 10.1.19 main.events_restart : MDEV-11221: assertion failure +main.events_slowlog : Added in 10.1.21 main.fulltext_charsets : Added in 10.1.20 -main.func_time : Modified in 10.1.20 +main.func_time : Modified in 10.1.21 main.group_by : Modified in 10.1.20 main.group_by_innodb : Modified in 10.1.20 main.host_cache_size_functionality : MDEV-10606 - sporadic failure on shutdown main.index_intersect_innodb : MDEV-10643 - failed with timeout -main.index_merge_innodb : MDEV-7142 - Wrong execution plan -main.information_schema : Modified in 10.1.19 +main.index_merge_innodb : MDEV-7142 - Wrong execution plan, also modified in 10.1.21 +main.information_schema_part : Modified in 10.1.21 main.innodb_mysql_lock : MDEV-7861 - sporadic lock detection failure +main.join_cache : Modified in 10.1.21 main.kill_processlist-6619 : MDEV-10793 - wrong result in processlist -main.loaddata : Modified in 10.1.20 +main.loaddata : Modified in 10.1.21 +main.log_slow : Modified in 10.1.21 main.lowercase_fs_on : Uses search_pattern_in_file.inc modified in 10.1.20 main.mdev-504 : MDEV-10607 - sporadic "can't connect" main.mdev375 : MDEV-10607 - sporadic "can't connect" main.merge : MDEV-10607 - sporadic "can't connect" -main.mysql : Modified in 10.1.19 -main.mysql_not_windows : Modified in 10.1.19 main.mysqlbinlog : Uses binlog_start_pos.inc modified in 10.1.20 main.mysqldump-max : Uses binlog_start_pos.inc modified in 10.1.20 -main.mysqldump-nl : Added in 10.1.19 -main.mysqltest : MDEV-9269 - fails on Alpha; also modified in 10.1.19 +main.mysqlslap : MDEV-11801 - timeout +main.mysqltest : MDEV-9269 - fails on Alpha main.named_pipe : Uses search_pattern_in_file.inc modified in 10.1.20 -main.null : Modified in 10.1.19 +main.order_by : Modified in 10.1.21 main.order_by_optimizer_innodb : MDEV-10683 - wrong execution plan main.parser : Modified in 10.1.20 -main.pool_of_threads : MDEV-10100 - sporadic error on detecting max connections +main.pool_of_threads : Modified in 10.1.21 main.ps : MDEV-11017 - sporadic wrong Prepared_stmt_count main.selectivity : Modified in 10.1.20 -main.selectivity_innodb : Modified in 10.1.19 main.show_explain : MDEV-10674 - sporadic failure -main.sp : Modified in 10.1.20 +main.signal_demo3 : MDEV-11720 - Thread stack overrun on labrador +main.sp : Modified in 10.1.21 +main.sp-prelocking : Modified in 10.1.21 main.sp-security : MDEV-10607 - sporadic "can't connect" main.stat_tables_par_innodb : MDEV-10515 - sporadic wrong results main.statistics : Modified in 10.1.20 main.status : MDEV-8510 - sporadic wrong result -main.subselect : Modified in 10.1.20 +main.subselect : Modified in 10.1.21 +main.subselect2 : Modified in 10.1.21 +main.subselect4 : Modified in 10.1.21 main.subselect_innodb : MDEV-10614 - sporadic wrong results +main.subselect_no_exists_to_in : Uses subselect.test modified in 10.1.21 +main.subselect_no_mat : Uses subselect.test modified in 10.1.21 +main.subselect_no_opts : Uses subselect.test modified in 10.1.21 +main.subselect_no_scache : Uses subselect.test modified in 10.1.21 +main.subselect_no_semijoin : Uses subselect.test modified in 10.1.21 +main.trigger_null-8605 : Modified in 10.1.21 main.type_datetime_hires : MDEV-10687 - timeout main.type_decimal : Modified in 10.1.20 -main.view : Uses search_pattern_in_file.inc modified in 10.1.20 +main.union : Modified in 10.1.21 +main.view : Modified in 10.1.21 main.wait_timeout_not_windows : Uses search_pattern_in_file.inc modified in 10.1.20 #---------------------------------------------------------------- archive.archive-big : MDEV-10615 - table is marked as crashed -archive.discover : MDEV-10510 - table is marked as crashed +archive.discover : MDEV-10510 - table is marked as crashed; modified in 10.1.21 #---------------------------------------------------------------- @@ -101,6 +118,8 @@ binlog_encryption.* : Added in 10.1.20 #---------------------------------------------------------------- +connect.jdbc : Modified in 10.1.21 +connect.jdbc_new : Modified in 10.1.21 connect.tbl : MDEV-9844, MDEV-10179 - sporadic crashes, valgrind warnings, wrong results #---------------------------------------------------------------- @@ -115,27 +134,28 @@ encryption.filekeys_nofile : Uses search_pattern_in_file.inc mo encryption.filekeys_syntax : Uses search_pattern_in_file.inc modified in 10.1.20 encryption.filekeys_tooshort : Uses search_pattern_in_file.inc modified in 10.1.20 encryption.filekeys_unencfile : Uses search_pattern_in_file.inc modified in 10.1.20 -encryption.innodb-bad-key-change : uses keys2.txt modified in 10.1.19 -encryption.innodb-bad-key-change2 : uses keys2.txt modified in 10.1.19 -encryption.innodb-bad-key-change3 : Uses search_pattern_in_file.inc modified in 10.1.20 -encryption.innodb-bad-key-change4 : uses keys2.txt modified in 10.1.19 -encryption.innodb-bad-key-change5 : uses keys2.txt modified in 10.1.19 -encryption.innodb-bad-key-shutdown : MDEV-9105 - valgrind warnings, assertion failures, and uses keys2.txt modified in 10.1.19 -encryption.innodb-discard-import : Uses search_pattern_in_file.inc modified in 10.1.20 -encryption.innodb_encryption_discard_import : MDEV-11218 - wrong result, also uses search_pattern_in_file.inc modified in 10.1.20 +encryption.innodb-bad-key-change3 : Modified in 10.1.21 +encryption.innodb-bad-key-shutdown : MDEV-9105 - valgrind warnings, assertion failures +encryption.innodb-discard-import : Modified in 10.1.21 +encryption.innodb-discard-import-change : Modified in 10.1.21 +encryption.innodb_encryption_discard_import : MDEV-11218 - wrong result, also modified in 10.1.21 encryption.innodb_encryption_filekeys : MDEV-9962 - timeouts +encryption.innodb_encryption-page-compression : MDEV-11420 - Trying to access missing tablespace encryption.innodb_encryption_row_compressed : Uses search_pattern_in_file.inc modified in 10.1.20 encryption.innodb_first_page : MDEV-10689 - crashes -encryption.innodb-log-encrypt : Uses search_pattern_in_file.inc modified in 10.1.20 -encryption.innodb_lotoftables : MDEV-11531 - InnoDB error -encryption.innodb-missing-key : Added in 10.1.19 +encryption.innodb-log-encrypt : Modified in 10.1.21 +encryption.innodb_lotoftables : MDEV-11531 - InnoDB error, also modified in 10.1.21 +encryption.innodb-missing-key : MDEV-9359 - assertion failure encryption.innodb_onlinealter_encryption : MDEV-10099 - wrong results; also uses search_pattern_in_file.inc modified in 10.1.20 encryption.innodb-page_encryption : MDEV-10641 - mutex problem -encryption.innodb_page_encryption_key_change : uses keys2.txt modified in 10.1.19 +encryption.innodb_scrub : MDEV-8139, also was modified in 10.1.21 +encryption.innodb_scrub_background : MDEV_8139, also was modified in 10.1.21 +encryption.innodb_scrub_compressed : MDEV-8139; also was modified and re-enabled in 10.1.21 #---------------------------------------------------------------- -extra/binlog_tests.database : Modified in 10.1.19 (merge) +engines/iuds.* : Not maintained in timely manner +engines/funcs.* : Not maintained in timely manner #---------------------------------------------------------------- @@ -147,51 +167,57 @@ federated.federated_transactions : MDEV-10617, MDEV-10417 - Wrong checksum, time #---------------------------------------------------------------- funcs_1.processlist_val_no_prot : MDEV-11223 - Wrong result + +funcs_2.innodb_charset : Modified in 10.1.21 funcs_2.memory_charset : MDEV-10290 - Timeout funcs_2.myisam_charset : MDEV-11535 - Timeout #---------------------------------------------------------------- -galera.* : Added to default suites in 10.1.19 - -galera.galera_var_dirty_reads : Modified in 10.1.20 +galera.galera_var_cluster_address : Modified in 10.1.21 +galera.galera_var_dirty_reads : Modified in 10.1.21 +galera.MW-284 : Modified in 10.1.21 galera.rpl_row_annotate : Uses binlog_start_pos.inc modified in 10.1.20 +galera_split_brain : Modified in 10.1.21 -galera_3nodes.* : Added to default suites in 10.1.19, MDEV-11490 +galera_3nodes.* : MDEV-11490 - Warnings not suppressed #---------------------------------------------------------------- +innodb.101_compatibility : Added in 10.1.21 innodb.binlog_consistent : MDEV-10618 - Server fails to start; also uses binlog_start_pos.inc modified in 10.1.20 +innodb.doublewrite : Added in 10.1.21 innodb.group_commit_binlog_pos : Uses binlog_start_pos.inc modified in 10.1.20 innodb.group_commit_binlog_pos_no_optimize_thread : Uses binlog_start_pos.inc modified in 10.1.20 +innodb.group_commit_crash : Modified in 10.1.21 +innodb.group_commit_crash_no_optimize_thread : Modified in 10.1.21 innodb.innodb-alter-table : MDEV-10619 - Testcase timeout -innodb.innodb-bug-14068765 : MDEV-9105 - valgrind warnings, assertion failures, also uses innodb-util.pl added in 10.1.19 -innodb.innodb-bug-14084530 : MDEV-9105 - valgrind warnings, assertion failures, also uses innodb-util.pl added in 10.1.19 +innodb.innodb-bug-14068765 : MDEV-9105 - valgrind warnings, assertion failures +innodb.innodb-bug-14084530 : MDEV-9105 - valgrind warnings, assertion failures +innodb.innodb_bug14147491 : MDEV-11808, also modified in 10.1.21 +innodb.innodb_bug14676111 : MDEV-11802 - wrong result innodb.innodb_bug30423 : MDEV-7311 - Wrong number of rows in the plan -innodb.innodb-change-buffer-recovery : Uses search_pattern_in_file.inc modified in 10.1.20 +innodb.innodb-change-buffer-recovery : Modified in 10.1.21 innodb.innodb_defragment_fill_factor : Modified in 10.1.20 innodb.innodb-lock-schedule-algorithm : Modified in 10.1.20 innodb.innodb-page_compression_zip : MDEV-10641 - mutex problem innodb.innodb_stats : MDEV-10682 - wrong result innodb.innodb_sys_semaphore_waits : MDEV-10331 - wrong result -innodb.innodb-wl5522 : MDEV-9105 - valgrind warnings, assertion failures, also uses innodb-util.pl added in 10.1.19 -innodb.innodb-wl5522-1 : MDEV-9105 - valgrind warnings, assertion failures, also uses innodb-util.pl added in 10.1.19 -innodb.innodb-wl5522-debug : Modified in 10.1.19 -innodb.innodb-wl5522-debug-zip : Modified in 10.1.20 -innodb.innodb-wl5522-zip : MDEV-9105 - valgrind warnings, assertion failures, also uses innodb-util.pl added in 10.1.19 +innodb.innodb-wl5522 : MDEV-9105 - valgrind warnings, assertion failures +innodb.innodb-wl5522-1 : MDEV-9105 - valgrind warnings, assertion failures +innodb.innodb-wl5522-debug-zip : Modified in 10.1.21 +innodb.log_data_file_size : Added in 10.1.21 innodb.table_index_statistics : Added in 10.1.20 innodb.trigger : Modified in 10.1.20 -innodb.xa_recovery : Modified in 10.1.19 +innodb.xa_recovery : Modified in 10.1.21 #---------------------------------------------------------------- innodb_fts.create : Added in 10.1.20 -innodb_fts.innodb_fts_misc : MDEV-11233 - Crash on CREATE FULLTEXT INDEX #---------------------------------------------------------------- maria.collations : Added in 10.1.20 -maria.encrypt-wrong-key : uses keys2.txt modified in 10.1.19 maria.maria-connect : Uses binlog_start_pos.inc modified in 10.1.20 #---------------------------------------------------------------- @@ -225,24 +251,26 @@ perfschema.func_file_io : MDEV-5708 - fails for s390x perfschema.func_mutex : MDEV-5708 - fails for s390x perfschema.setup_actors : MDEV-10679 - rare crash perfschema.socket_summary_by_event_name_func : MDEV-10622 - Socket summary tables do not match +perfschema.stage_mdl_global : MDEV-11803 - wrong result on slow builders perfschema.threads_mysql : MDEV-10677 - sporadic wrong result #---------------------------------------------------------------- +plugins.cracklib_password_check : MDEV-11650 - valgrind warnings plugins.feedback_plugin_send : MDEV-7932 - ssl failed for url plugins.server_audit : MDEV-9562 - crashes on sol10-sparc plugins.thread_pool_server_audit : MDEV-9562 - crashes on sol10-sparc - +plugins.two_password_validations : MDEV-11650 - valgrind warnings #---------------------------------------------------------------- roles.role_case_sensitive-10744 : Added in 10.1.20 roles.create_and_drop_role : Modified in 10.1.20 -roles.create_and_grant_role : MDEV-11533 - Extra grant in output #---------------------------------------------------------------- rpl.last_insert_id : MDEV-10625 - warnings in error log +rpl.rpl_alter_extra_persistent : Added in 10.1.21 rpl.rpl_auto_increment : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_bug45679 : MDEV-10417 - Fails on Mips rpl.rpl_auto_increment_update_failure : MDEV-10625 - warnings in error log @@ -252,7 +280,6 @@ rpl.rpl_checksum_cache : MDEV-10626 - Testcase timeout rpl.rpl_circular_for_4_hosts : MDEV-10627 - Testcase timeout rpl.rpl_ddl : MDEV-10417 - Fails on Mips rpl.rpl_domain_id_filter_restart : MDEV-10684 - Wrong result -rpl.rpl_drop_db : Modified in 10.1.19 rpl.rpl_gtid_basic : MDEV-10681 - server startup problem rpl.rpl_gtid_crash : MDEV-9501 - Warning: failed registering on master rpl.rpl_gtid_errorlog : Uses search_pattern_in_file.inc modified in 10.1.20 @@ -260,6 +287,7 @@ rpl.rpl_gtid_master_promote : MDEV-10628 - Timeout in sync_with_master rpl.rpl_gtid_mdev9033 : MDEV-10680 - warnings rpl.rpl_gtid_stop_start : MDEV-10629 - Crash on shutdown rpl.rpl_gtid_until : MDEV-10625 - warnings in error log +rpl.rpl_heartbeat_basic : MDEV-11668 - wrong result rpl.rpl_innodb_bug30888 : MDEV-10417 - Fails on Mips rpl.rpl_insert : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_insert_delayed : MDEV-9329 - Fails on Ubuntu/s390x @@ -278,17 +306,21 @@ rpl.rpl_password_boundaries : MDEV-11534 - Slave IO warnings rpl.rpl_row_drop_create_temp_table : MDEV-10626 - Testcase timeout rpl.rpl_row_flsh_tbls : Uses binlog_start_pos.inc modified in 10.1.20 rpl.rpl_row_log_innodb : MDEV-10688 - Wrong result +rpl.rpl_row_mysqlbinlog : Modified in 10.1.21 rpl.rpl_row_sp001 : MDEV-9329 - Fails on Ubuntu/s390x rpl.rpl_semi_sync : MDEV-11220 - Wrong result +rpl.rpl_semi_sync_event_after_sync : MDEV-11806 - warnings rpl.rpl_semi_sync_uninstall_plugin : MDEV-7140 - Wrong plugin status +rpl.rpl_semi_sync_wait_point : MDEV-11807 - timeout in wait condition rpl.rpl_show_slave_hosts : MDEV-10681 - server startup problem rpl.rpl_skip_replication : MDEV-9268 - Fails with timeout in sync_slave_with_master on Alpha rpl.rpl_slave_grp_exec : MDEV-10514 - Unexpected deadlock +rpl.rpl_special_charset : Modified in 10.1.21 rpl.rpl_stm_flsh_tbls : Uses binlog_start_pos.inc modified in 10.1.20 rpl.rpl_stop_slave_error : Uses search_pattern_in_file.inc modified in 10.1.20 rpl.rpl_sync : MDEV-10633 - Database page corruption rpl.rpl_temporary_error2 : MDEV-10634 - Wrong number of retries -rpl.sec_behind_master-5114 : MDEV-8518 - Wrong value of Seconds_Behind_Master +rpl.sec_behind_master-5114 : Modified in 10.1.21 #---------------------------------------------------------------- @@ -301,9 +333,11 @@ spider/bg.ha_part : MDEV-9329 - Fails on Ubuntu/s390x spider/bg.spider_fixes : MDEV-7098, MDEV-9329 - Mutex problem, failures on s390x spider/bg.vp_fixes : MDEV-9329 - Fails on Ubuntu/s390x +spider/handler.* : MDEV-10987, MDEV-10990 - Tests have not been maintained + #---------------------------------------------------------------- -sphinx.* : MDEV-10985, MDEV-10986 - Tests have not been maintained +sphinx.* : MDEV-10986 - Tests have not been maintained #---------------------------------------------------------------- @@ -325,6 +359,7 @@ sys_vars.replicate_ignore_db_basic : Modified in 10.1.20 sys_vars.replicate_ignore_table_basic : Modified in 10.1.20 sys_vars.replicate_wild_do_table_basic : Modified in 10.1.20 sys_vars.replicate_wild_ignore_table_basic : Modified in 10.1.20 +sys_vars.rpl_init_slave_func : MDEV-10149 - wrong results sys_vars.sysvars_innodb : MDEV-6958 - error-prone rdiffs sys_vars.sysvars_server_embedded : MDEV-6958 - error-prone rdiffs sys_vars.table_open_cache_instances_basic : Modified in 10.1.20 @@ -339,6 +374,7 @@ tokudb.table_index_statistics : Added in 10.1.20 tokudb_bugs.checkpoint_lock : MDEV-10637 - Wrong processlist output tokudb_bugs.checkpoint_lock_3 : MDEV-10637 - Wrong processlist output +tokudb_bugs.xa : MDEV-11804 - Lock wait timeout tokudb_rpl.rpl_parallel_optimistic : Added in 10.1.20 tokudb_rpl.rpl_tokudb_rfr_partition_table : Added in 10.1.20 @@ -355,9 +391,7 @@ vcol.vcol_keys_innodb : MDEV-10639 - Testcase timeout #---------------------------------------------------------------- wsrep.binlog_format : MDEV-11532 - WSREP has not yet prepared node -wsrep.mdev_10186 : Modified in 10.1.19 #---------------------------------------------------------------- -wsrep_info.* : suite.pm modified in 10.1.19 wsrep_info.plugin : MDEV-11530 - Warnings; also modified in 10.1.20 From 3a91dec1243773627d08965e7e258571a7844deb Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Mon, 16 Jan 2017 02:36:31 +0200 Subject: [PATCH 077/167] 101_compatibility test fails on CentOS 5 Apparently, in older versions of Perl unpack does not have a logic for using $_ as a default value for the second argument. Fixed by specifying it explicitly --- mysql-test/suite/innodb/include/ibd_convert.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/include/ibd_convert.pl b/mysql-test/suite/innodb/include/ibd_convert.pl index aba742ac649..32eef96fd23 100644 --- a/mysql-test/suite/innodb/include/ibd_convert.pl +++ b/mysql-test/suite/innodb/include/ibd_convert.pl @@ -10,7 +10,7 @@ sub convert_to_mariadb_101 sysseek(FILE, 0, 0)||die "Unable to seek $file\n"; # FIL_PAGE_DATA + FSP_SPACE_FLAGS = 38 + 16 = 54 bytes from the start - my($flags) = unpack "x[54]N"; + my($flags) = unpack "x[54]N", $_; my $badflags = ($flags & 0x3f); my $compression_level=6; $badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16); From 7e3f3deb41a875778a540718abd8f90278e4cb67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 16 Jan 2017 09:15:56 +0200 Subject: [PATCH 078/167] MDEV-11623 follow-up: Adjust tests. innodb.doublewrite: Similar to what was done to innodb.101_compatibility, add an explicit $_ parameter to the Perl unpack function. Also, fix some diagnostic messages in the Perl code. innodb.innodb-wl5522-debug: Adjust for the changed error codes and messages on fault injection. --- mysql-test/suite/innodb/r/innodb-wl5522-debug.result | 3 ++- mysql-test/suite/innodb/t/doublewrite.test | 10 +++++----- mysql-test/suite/innodb/t/innodb-wl5522-debug.test | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result index ee8bd22c58f..031f382401f 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-debug.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug.result @@ -1,4 +1,5 @@ call mtr.add_suppression("InnoDB: Page for tablespace .* "); +call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS="); FLUSH TABLES; SET GLOBAL innodb_file_per_table = 1; SELECT @@innodb_file_per_table; @@ -912,7 +913,7 @@ ERROR HY000: Tablespace has been discarded for table 't1' restore: t1 .ibd and .cfg files SET SESSION debug_dbug="+d,fsp_flags_is_valid_failure"; ALTER TABLE test_wl5522.t1 IMPORT TABLESPACE; -ERROR HY000: Internal error: Cannot reset LSNs in table '"test_wl5522"."t1"' : Unsupported +ERROR HY000: Internal error: Cannot reset LSNs in table '"test_wl5522"."t1"' : Data structure corruption SET SESSION debug_dbug="-d,fsp_flags_is_valid_failure"; DROP TABLE test_wl5522.t1; unlink: t1.ibd diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index 245b4e1a676..6e0a4a70200 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -74,15 +74,15 @@ my $fname= "$ENV{'MYSQLD_DATADIR'}test/t1.ibd"; my $page_size = $ENV{INNODB_PAGE_SIZE}; my $page; open(FILE, "+<", $fname) or die; -sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $file\n"; -sysseek(FILE, 0, 0)||die "Unable to seek $file\n"; +sysread(FILE, $page, $page_size)==$page_size||die "Unable to read $name\n"; +sysseek(FILE, 0, 0)||die "Unable to seek $fname\n"; die unless syswrite(FILE, chr(0) x $page_size, $page_size) == $page_size; close FILE; open(FILE, "+<", "$ENV{MYSQLD_DATADIR}ibdata1")||die "cannot open ibdata1\n"; sysseek(FILE, 6 * $page_size - 190, 0)||die "Unable to seek ibdata1\n"; sysread(FILE, $_, 12) == 12||die "Unable to read TRX_SYS\n"; -my($magic,$d1,$d2)=unpack "NNN"; +my($magic,$d1,$d2)=unpack "NNN", $_; die "magic=$magic, $d1, $d2\n" unless $magic == 536853855 && $d2 >= $d1 + 64; sysseek(FILE, $d1 * $page_size, 0)||die "Unable to seek ibdata1\n"; # Find the page in the doublewrite buffer @@ -92,7 +92,7 @@ for (my $d = $d1; $d < $d2 + 64; $d++) next unless $_ eq $page; sysseek(FILE, $d * $page_size, 0)||die "Unable to seek ibdata1\n"; # Write buggy MariaDB 10.1.x FSP_SPACE_FLAGS to the doublewrite buffer - my($flags) = unpack "x[54]N"; + my($flags) = unpack "x[54]N", $_; my $badflags = ($flags & 0x3f); my $compression_level=6; $badflags |= 1<<6|$compression_level<<7 if ($flags & 1 << 16); @@ -102,7 +102,7 @@ for (my $d = $d1; $d < $d2 + 64; $d++) # Replace the innodb_checksum_algorithm=none checksum substr ($_, 0, 4) = pack("N", 0xdeadbeef); substr ($_, $page_size - 8, 4) = pack("N", 0xdeadbeef); - syswrite(FILE, $_, $page_size)==$page_size||die "Unable to write $file\n"; + syswrite(FILE, $_, $page_size)==$page_size||die; close(FILE); exit 0; } diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test index e8a037ab2f1..6c94f408ae9 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug.test @@ -16,6 +16,7 @@ -- source include/have_innodb.inc call mtr.add_suppression("InnoDB: Page for tablespace .* "); +call mtr.add_suppression("InnoDB: Invalid FSP_SPACE_FLAGS="); FLUSH TABLES; let MYSQLD_DATADIR =`SELECT @@datadir`; From 03497129371fe2c16d847b7e83a5eeecab9c34a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 16 Jan 2017 18:26:14 +0200 Subject: [PATCH 079/167] MDEV-11623 follow-up: Adjust one more test. The function fsp_flags_try_adjust(), which is called on startup, is incrementing the Innodb_pages0_read counts for every affected file. Adjust the result of encryption.innodb_lotoftables accordingly. --- .../encryption/r/innodb_lotoftables.result | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb_lotoftables.result b/mysql-test/suite/encryption/r/innodb_lotoftables.result index b7cfdd2db9d..418ab175a01 100644 --- a/mysql-test/suite/encryption/r/innodb_lotoftables.result +++ b/mysql-test/suite/encryption/r/innodb_lotoftables.result @@ -12,13 +12,13 @@ create database innodb_encrypted_1; use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 set autocommit=0; set autocommit=1; commit work; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 3 # should be 100 SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE NAME LIKE 'innodb_encrypted%'; COUNT(*) @@ -88,47 +88,47 @@ Innodb_pages0_read 3 # Restart Success! show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 303 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 303 use test; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 303 use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 303 use innodb_encrypted_2; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 303 use innodb_encrypted_3; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 303 use innodb_encrypted_1; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 1 +Innodb_pages0_read 303 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 101 +Innodb_pages0_read 303 use innodb_encrypted_2; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 101 +Innodb_pages0_read 303 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 201 +Innodb_pages0_read 303 use innodb_encrypted_3; show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 201 +Innodb_pages0_read 303 show status like 'innodb_pages0_read%'; Variable_name Value -Innodb_pages0_read 301 +Innodb_pages0_read 303 SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 AND NAME LIKE 'innodb_encrypted%'; COUNT(*) 100 From bb109aeea3e696f89357c946a3c04ca112925d11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 16 Jan 2017 13:57:39 +0200 Subject: [PATCH 080/167] MDEV-6076: Fix a broken assertion. --- 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 5f330b9e071..704ed55f2b3 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -480,7 +480,7 @@ page_create_zip( /* PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC are always 0 for temporary tables. */ - ut_ad(!dict_table_is_temporary(index->table) || max_trx_id == 0); + ut_ad(max_trx_id == 0 || !dict_table_is_temporary(index->table)); /* In secondary indexes and the change buffer, PAGE_MAX_TRX_ID must be zero on non-leaf pages. max_trx_id can be 0 when the index consists of an empty root (leaf) page. */ From c849b7df616cc8a5378609f243898644c7689f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 17 Jan 2017 11:52:31 +0200 Subject: [PATCH 081/167] MDEV-11785 Remove INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO The INFORMATION_SCHEMA view INNODB_TEMP_TABLE_INFO was added to MySQL 5.7 as part of the work to implement temporary tables without any redo logging. The only use case of this view was SELECT COUNT(*) in some tests, to see how many temporary tables exist in InnoDB. The columns do not report much useful information. For example, the table name would not be the user-specified table name, but a generated #sql name. Also, the session that created the table is not identified. --- storage/innobase/handler/ha_innodb.cc | 1 - storage/innobase/handler/i_s.cc | 283 +------------------------- storage/innobase/handler/i_s.h | 3 +- 3 files changed, 2 insertions(+), 285 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9e9a6a5994d..4e1d8e3367b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -23396,7 +23396,6 @@ i_s_innodb_cmp_per_index_reset, i_s_innodb_buffer_page, i_s_innodb_buffer_page_lru, i_s_innodb_buffer_stats, -i_s_innodb_temp_table_info, i_s_innodb_metrics, i_s_innodb_ft_default_stopword, i_s_innodb_ft_deleted, diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 4a13faa480f..01fadaf8e10 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. -Copyrigth (c) 2014, 2016, MariaDB Corporation +Copyrigth (c) 2014, 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 @@ -4097,287 +4097,6 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_ft_config = STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; -/* Fields of the dynamic table INNODB_TEMP_TABLE_INFO. */ -static ST_FIELD_INFO i_s_innodb_temp_table_info_fields_info[] = -{ -#define IDX_TEMP_TABLE_ID 0 - {STRUCT_FLD(field_name, "TABLE_ID"), - STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - -#define IDX_TEMP_TABLE_NAME 1 - {STRUCT_FLD(field_name, "NAME"), - STRUCT_FLD(field_length, MAX_TABLE_UTF8_LEN), - STRUCT_FLD(field_type, MYSQL_TYPE_STRING), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - -#define IDX_TEMP_TABLE_N_COLS 2 - {STRUCT_FLD(field_name, "N_COLS"), - STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - -#define IDX_TEMP_TABLE_SPACE_ID 3 - {STRUCT_FLD(field_name, "SPACE"), - STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS), - STRUCT_FLD(field_type, MYSQL_TYPE_LONG), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - -#define IDX_TEMP_TABLE_PTT 4 - {STRUCT_FLD(field_name, "PER_TABLE_TABLESPACE"), - STRUCT_FLD(field_length, 64), - STRUCT_FLD(field_type, MYSQL_TYPE_STRING), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - -#define IDX_TEMP_TABLE_IS_COMPRESSED 5 - {STRUCT_FLD(field_name, "IS_COMPRESSED"), - STRUCT_FLD(field_length, 64), - STRUCT_FLD(field_type, MYSQL_TYPE_STRING), - STRUCT_FLD(value, 0), - STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), - STRUCT_FLD(old_name, ""), - STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, - END_OF_ST_FIELD_INFO -}; - -struct temp_table_info_t{ - table_id_t m_table_id; - char m_table_name[MAX_TABLE_UTF8_LEN]; - unsigned m_n_cols; - unsigned m_space_id; - char m_per_table_tablespace[64]; - char m_is_compressed[64]; -}; - -typedef std::vector > - temp_table_info_cache_t; - -/*******************************************************************//** -Fill Information Schema table INNODB_TEMP_TABLE_INFO for a particular -temp-table -@return 0 on success, 1 on failure */ -static -int -i_s_innodb_temp_table_info_fill( -/*=============================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables - to fill */ - const temp_table_info_t* info) /*!< in: temp-table - information */ -{ - TABLE* table; - Field** fields; - - DBUG_ENTER("i_s_innodb_temp_table_info_fill"); - - table = tables->table; - - fields = table->field; - - OK(fields[IDX_TEMP_TABLE_ID]->store(info->m_table_id, true)); - - OK(field_store_string( - fields[IDX_TEMP_TABLE_NAME], info->m_table_name)); - - OK(fields[IDX_TEMP_TABLE_N_COLS]->store(info->m_n_cols)); - - OK(fields[IDX_TEMP_TABLE_SPACE_ID]->store(info->m_space_id)); - - OK(field_store_string( - fields[IDX_TEMP_TABLE_PTT], info->m_per_table_tablespace)); - - OK(field_store_string( - fields[IDX_TEMP_TABLE_IS_COMPRESSED], info->m_is_compressed)); - - DBUG_RETURN(schema_table_store_record(thd, table)); -} - -/*******************************************************************//** -Populate current table information to cache */ -static -void -innodb_temp_table_populate_cache( -/*=============================*/ - const dict_table_t* table, /*! in: table */ - temp_table_info_t* cache) /*! in/out: populate data in this - cache */ -{ - cache->m_table_id = table->id; - - char db_utf8[MAX_DB_UTF8_LEN]; - char table_utf8[MAX_TABLE_UTF8_LEN]; - - dict_fs2utf8(table->name.m_name, - db_utf8, sizeof(db_utf8), - table_utf8, sizeof(table_utf8)); - strcpy(cache->m_table_name, table_utf8); - - cache->m_n_cols = table->n_cols; - - cache->m_space_id = table->space; - - if (fsp_is_system_temporary(table->space)) { - strcpy(cache->m_per_table_tablespace, "FALSE"); - } else { - strcpy(cache->m_per_table_tablespace, "TRUE"); - } - - if (dict_table_page_size(table).is_compressed()) { - strcpy(cache->m_is_compressed, "TRUE"); - } else { - strcpy(cache->m_is_compressed, "FALSE"); - } -} - -/*******************************************************************//** -This function will iterate over all available table and will fill -stats for temp-tables to INNODB_TEMP_TABLE_INFO. -@return 0 on success, 1 on failure */ -static -int -i_s_innodb_temp_table_info_fill_table( -/*===================================*/ - THD* thd, /*!< in: thread */ - TABLE_LIST* tables, /*!< in/out: tables to fill */ - Item* ) /*!< in: condition (ignored) */ -{ - int status = 0; - dict_table_t* table = NULL; - - DBUG_ENTER("i_s_innodb_temp_table_info_fill_table"); - - /* Only allow the PROCESS privilege holder to access the stats */ - if (check_global_access(thd, PROCESS_ACL)) { - DBUG_RETURN(0); - } - - /* First populate all temp-table info by acquiring dict_sys->mutex. - Note: Scan is being done on NON-LRU list which mainly has system - table entries and temp-table entries. This means 2 things: list - is smaller so processing would be faster and most of the data - is relevant */ - temp_table_info_cache_t all_temp_info_cache; - all_temp_info_cache.reserve(UT_LIST_GET_LEN(dict_sys->table_non_LRU)); - - mutex_enter(&dict_sys->mutex); - for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU); - table != NULL; - table = UT_LIST_GET_NEXT(table_LRU, table)) { - - if (!dict_table_is_temporary(table)) { - continue; - } - - temp_table_info_t current_temp_table_info; - - innodb_temp_table_populate_cache( - table, ¤t_temp_table_info); - - all_temp_info_cache.push_back(current_temp_table_info); - } - mutex_exit(&dict_sys->mutex); - - /* Now populate the info to MySQL table */ - temp_table_info_cache_t::const_iterator end = all_temp_info_cache.end(); - for (temp_table_info_cache_t::const_iterator it - = all_temp_info_cache.begin(); - it != end; - it++) { - status = i_s_innodb_temp_table_info_fill(thd, tables, &(*it)); - if (status) { - break; - } - } - - DBUG_RETURN(status); -} - -/*******************************************************************//** -Bind the dynamic table INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO. -@return 0 on success, 1 on failure */ -static -int -i_s_innodb_temp_table_info_init( -/*=============================*/ - void* p) /*!< in/out: table schema object */ -{ - ST_SCHEMA_TABLE* schema; - - DBUG_ENTER("i_s_innodb_temp_table_info_init"); - - schema = reinterpret_cast(p); - - schema->fields_info = i_s_innodb_temp_table_info_fields_info; - schema->fill_table = i_s_innodb_temp_table_info_fill_table; - - DBUG_RETURN(0); -} - -struct st_maria_plugin i_s_innodb_temp_table_info = -{ - /* the plugin type (a MYSQL_XXX_PLUGIN value) */ - /* int */ - STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), - - /* pointer to type-specific plugin descriptor */ - /* void* */ - STRUCT_FLD(info, &i_s_info), - - /* plugin name */ - /* const char* */ - STRUCT_FLD(name, "INNODB_TEMP_TABLE_INFO"), - - /* plugin author (for SHOW PLUGINS) */ - /* const char* */ - STRUCT_FLD(author, plugin_author), - - /* general descriptive text (for SHOW PLUGINS) */ - /* const char* */ - STRUCT_FLD(descr, "InnoDB Temp Table Stats"), - - /* the plugin license (PLUGIN_LICENSE_XXX) */ - /* int */ - STRUCT_FLD(license, PLUGIN_LICENSE_GPL), - - /* the function to invoke when plugin is loaded */ - /* int (*)(void*); */ - STRUCT_FLD(init, i_s_innodb_temp_table_info_init), - - /* the function to invoke when plugin is unloaded */ - /* int (*)(void*); */ - STRUCT_FLD(deinit, i_s_common_deinit), - - /* plugin version (for SHOW PLUGINS) */ - /* unsigned int */ - STRUCT_FLD(version, INNODB_VERSION_SHORT), - - /* struct st_mysql_show_var* */ - STRUCT_FLD(status_vars, NULL), - - /* struct st_mysql_sys_var** */ - STRUCT_FLD(system_vars, NULL), - - STRUCT_FLD(version_info, INNODB_VERSION_STR), - STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_GAMMA) -}; - /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] = { diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index d272490dd27..8d34fbf8fbb 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyrigth (c) 2014, 2016, MariaDB Corporation +Copyrigth (c) 2014, 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 @@ -50,7 +50,6 @@ extern struct st_maria_plugin i_s_innodb_ft_config; extern struct st_maria_plugin i_s_innodb_buffer_page; extern struct st_maria_plugin i_s_innodb_buffer_page_lru; extern struct st_maria_plugin i_s_innodb_buffer_stats; -extern struct st_maria_plugin i_s_innodb_temp_table_info; extern struct st_maria_plugin i_s_innodb_sys_tables; extern struct st_maria_plugin i_s_innodb_sys_tablestats; extern struct st_maria_plugin i_s_innodb_sys_indexes; From 6a65de6cda17cc955d73b992f91acb76e8ef7512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 17 Jan 2017 15:28:50 +0200 Subject: [PATCH 082/167] Correct a test broken in the merge 7c81f15ec3bcc --- mysql-test/suite/innodb_zip/t/innochecksum_3.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb_zip/t/innochecksum_3.test b/mysql-test/suite/innodb_zip/t/innochecksum_3.test index 4b386099f86..60c4b167d9a 100644 --- a/mysql-test/suite/innodb_zip/t/innochecksum_3.test +++ b/mysql-test/suite/innodb_zip/t/innochecksum_3.test @@ -163,9 +163,9 @@ foreach (glob("$ENV{MYSQLD_DATADIR}/*/*.ibd")) { } EOF -let $restart_parameters = restart: --innodb_checksum_algorithm=strict_none --default_storage_engine=InnoDB; +--let $restart_parameters = --innodb_checksum_algorithm=strict_none --default_storage_engine=InnoDB --source include/start_mysqld.inc - +--let $restart_parameters= # check the table status is GOOD with DML INSERT INTO tab1 (pk, linestring_key, linestring_nokey) VALUES (4, ST_GeomFromText('MULTIPOINT(0 0,5 5,10 10,20 20) '), ST_GeomFromText('MULTIPOINT(0 0,5 5,10 10,20 20) ')); From 45f11a729c9ccacd57a82a3b523ba73e4113311b Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 18 Jan 2017 00:56:24 +0300 Subject: [PATCH 083/167] MDEV-10773: ANALYZE FORMAT=JSON query_with_CTE crashes Added testcase --- mysql-test/r/cte_recursive.result | 65 +++++++++++++++++++++++++++++++ mysql-test/t/cte_recursive.test | 12 ++++++ 2 files changed, 77 insertions(+) diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index d5476aec1c4..e68d5a38283 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -2343,3 +2343,68 @@ select id + 1, uuid() from data_generator where id < 150000 select * from data_generator ) as a; drop table t1; +# +# MDEV-10773: ANALYZE FORMAT=JSON query_with_CTE crashes +# +analyze format=json +with recursive src(counter) as +(select 1 +union +select counter+1 from src where counter<10 +) select * from src; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 10, + "r_total_time_ms": "REPLACED"e-4, + "filtered": 100, + "r_filtered": 100, + "materialized": { + "query_block": { + "recursive_union": { + "table_name": "", + "access_type": "ALL", + "r_loops": 0, + "r_rows": null, + "query_specifications": [ + { + "query_block": { + "select_id": 2, + "table": { + "message": "No tables used" + } + } + }, + { + "query_block": { + "select_id": 3, + "r_loops": 10, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "", + "access_type": "ALL", + "r_loops": 10, + "rows": 2, + "r_rows": 1, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 90, + "attached_condition": "src.counter < 10" + } + } + } + ] + } + } + } + } + } +} diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index ea0f73be259..bb57a8600b6 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -1505,3 +1505,15 @@ select id, test_data ) as a; drop table t1; + +--echo # +--echo # MDEV-10773: ANALYZE FORMAT=JSON query_with_CTE crashes +--echo # +--replace_regex /"r_total_time_ms": [0-9]*[.]?[0-9]*/"r_total_time_ms": "REPLACED"/ +analyze format=json +with recursive src(counter) as +(select 1 + union + select counter+1 from src where counter<10 +) select * from src; + From 70c11485d2d5982ffbf31740b24798565760a16f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 16 Jan 2017 11:11:14 +0200 Subject: [PATCH 084/167] Remove MYSQL_ENCRYPTION. MariaDB will likely never support MySQL-style encryption for InnoDB, because we cannot link with the Oracle encryption plugin. This is preparation for merging MDEV-11623. --- storage/innobase/btr/btr0btr.cc | 4 +- storage/innobase/dict/dict0crea.cc | 4 +- storage/innobase/dict/dict0dict.cc | 7 +- storage/innobase/dict/dict0load.cc | 9 +- storage/innobase/fil/fil0fil.cc | 255 +----- storage/innobase/fsp/fsp0file.cc | 58 -- storage/innobase/fsp/fsp0fsp.cc | 363 --------- storage/innobase/handler/ha_innodb.cc | 217 +----- storage/innobase/handler/handler0alter.cc | 15 - storage/innobase/include/db0err.h | 6 - storage/innobase/include/dict0dict.h | 14 +- storage/innobase/include/dict0dict.ic | 12 - storage/innobase/include/dict0mem.h | 9 - storage/innobase/include/fil0fil.h | 35 +- storage/innobase/include/fsp0file.h | 14 - storage/innobase/include/fsp0fsp.h | 40 +- storage/innobase/include/fsp0fsp.ic | 8 +- storage/innobase/include/fsp0types.h | 8 - storage/innobase/include/ha_prototypes.h | 1 - storage/innobase/include/log0recv.h | 13 - storage/innobase/include/os0file.h | 254 ------ storage/innobase/include/sync0sync.h | 1 - storage/innobase/include/sync0types.h | 1 - storage/innobase/log/log0recv.cc | 183 ----- storage/innobase/os/os0file.cc | 901 +--------------------- storage/innobase/row/row0import.cc | 274 +------ storage/innobase/row/row0mysql.cc | 58 +- storage/innobase/row/row0quiesce.cc | 238 ------ storage/innobase/srv/srv0start.cc | 44 -- storage/innobase/sync/sync0debug.cc | 2 - storage/innobase/sync/sync0sync.cc | 1 - storage/innobase/ut/ut0ut.cc | 4 - 32 files changed, 24 insertions(+), 3029 deletions(-) diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 8acb96f1910..d1d9dfe64fe 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -336,9 +336,7 @@ btr_root_adjust_on_import( /* Check that the table flags and the tablespace flags match. */ ulint flags = dict_tf_to_fsp_flags( - table->flags, - false, - dict_table_is_encrypted(table)); + table->flags, false); ulint fsp_flags = fil_space_get_flags(table->space); err = fsp_flags_are_equal(flags, fsp_flags) ? DB_SUCCESS : DB_CORRUPTION; diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index cfea64d51c2..58b1e5b46b1 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -494,11 +494,9 @@ dict_build_tablespace_for_table( /* Determine the tablespace flags. */ bool is_temp = dict_table_is_temporary(table); - bool is_encrypted = dict_table_is_encrypted(table); bool has_data_dir = DICT_TF_HAS_DATA_DIR(table->flags); ulint fsp_flags = dict_tf_to_fsp_flags(table->flags, - is_temp, - is_encrypted); + is_temp); /* Determine the full filepath */ if (is_temp) { diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 0013a5f690f..122ab2c54f0 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -7255,13 +7255,11 @@ dict_table_t::flags | 0 | 1 | 1 | 1 fil_space_t::flags | 0 | 0 | 1 | 1 @param[in] table_flags dict_table_t::flags @param[in] is_temp whether the tablespace is temporary -@param[in] is_encrypted whether the tablespace is encrypted @return tablespace flags (fil_space_t::flags) */ ulint dict_tf_to_fsp_flags( ulint table_flags, - bool is_temp, - bool is_encrypted) + bool is_temp) { DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure", return(ULINT_UNDEFINED);); @@ -7289,8 +7287,7 @@ dict_tf_to_fsp_flags( is_temp, 0, 0, - 0, - is_encrypted); + 0); /* In addition, tablespace flags also contain if the page compression is used for this table. */ diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index b40d659e362..ffa7f48beae 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1453,10 +1453,7 @@ dict_check_sys_tables( /* Check that the .ibd file exists. */ bool is_temp = flags2 & DICT_TF2_TEMPORARY; - bool is_encrypted = flags2 & DICT_TF2_ENCRYPTION; - ulint fsp_flags = dict_tf_to_fsp_flags(flags, - is_temp, - is_encrypted); + ulint fsp_flags = dict_tf_to_fsp_flags(flags, is_temp); validate = true; /* Encryption */ dberr_t err = fil_ibd_open( @@ -2991,9 +2988,7 @@ dict_load_tablespace( /* Try to open the tablespace. We set the 2nd param (fix_dict) to false because we do not have an x-lock on dict_operation_lock */ - ulint fsp_flags = dict_tf_to_fsp_flags(table->flags, - false, - dict_table_is_encrypted(table)); + ulint fsp_flags = dict_tf_to_fsp_flags(table->flags, false); dberr_t err = fil_ibd_open( true, false, FIL_TYPE_TABLESPACE, table->space, fsp_flags, space_name, filepath, table); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 773eb0406ae..a00b287dc3f 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -139,7 +139,7 @@ const char* fil_path_to_mysql_datadir; Folder folder_mysql_datadir; /** Common InnoDB file extentions */ -const char* dot_ext[] = { "", ".ibd", ".isl", ".cfg", ".cfp" }; +const char* dot_ext[] = { "", ".ibd", ".isl", ".cfg" }; /** The number of fsyncs done to the log */ ulint fil_n_log_flushes = 0; @@ -747,21 +747,6 @@ retry: ut_free(buf2); -#ifdef MYSQL_ENCRYPTION - /* For encrypted tablespace, we need to check the - encrytion key and iv(initial vector) is readed. */ - if (FSP_FLAGS_GET_ENCRYPTION(flags) - && !recv_recovery_is_on()) { - if (space->encryption_type != Encryption::AES) { - ib::error() - << "Can't read encryption" - << " key from file " - << node->name << "!"; - return(false); - } - } -#endif - if (node->size == 0) { ulint extent_size; @@ -1695,8 +1680,6 @@ fil_space_create( << " " << fil_crypt_get_type(crypt_data)); } - space->encryption_type = Encryption::NONE; - rw_lock_create(fil_space_latch_key, &space->latch, SYNC_FSP); if (space->purpose == FIL_TYPE_TEMPORARY) { @@ -4021,17 +4004,6 @@ fil_ibd_create( goto error_exit_1; } -#ifdef MYSQL_ENCRYPTION - /* For encryption tablespace, initial encryption information. */ - if (FSP_FLAGS_GET_ENCRYPTION(space->flags)) { - err = fil_set_encryption(space->id, - Encryption::AES, - NULL, - NULL); - ut_ad(err == DB_SUCCESS); - } -#endif /* MYSQL_ENCRYPTION */ - if (!is_temp) { mtr_t mtr; const fil_node_t* file = UT_LIST_GET_FIRST(space->chain); @@ -4107,7 +4079,6 @@ fil_ibd_open( bool link_file_found = false; bool link_file_is_bad = false; bool is_shared = FSP_FLAGS_GET_SHARED(flags); - bool is_encrypted = FSP_FLAGS_GET_ENCRYPTION(flags); Datafile df_default; /* default location */ Datafile df_dict; /* dictionary location */ RemoteDatafile df_remote; /* remote location */ @@ -4228,7 +4199,7 @@ fil_ibd_open( normal, we only found 1. */ /* For encrypted tablespace, we need to check the encryption in header of first page. */ - if (!validate && tablespaces_found == 1 && !is_encrypted) { + if (!validate && tablespaces_found == 1) { goto skip_validate; } @@ -4249,21 +4220,12 @@ fil_ibd_open( /* Make sense of these three possible locations. First, bail out if no tablespace files were found. */ if (valid_tablespaces_found == 0) { - if (!is_encrypted) { - /* The following call prints an error message. - For encrypted tablespace we skip print, since it should - be keyring plugin issues. */ - os_file_get_last_error(true); - ib::error() << "Could not find a valid tablespace file for `" - << space_name << "`. " << TROUBLESHOOT_DATADICT_MSG; - } - + os_file_get_last_error(true); + ib::error() << "Could not find a valid tablespace file for `" + << space_name << "`. " << TROUBLESHOOT_DATADICT_MSG; return(DB_CORRUPTION); } - if (!validate && !is_encrypted) { - return(DB_SUCCESS); - } - if (validate && is_encrypted && fil_space_get(id)) { + if (!validate) { return(DB_SUCCESS); } @@ -4428,25 +4390,6 @@ skip_validate: true, TRUE) == NULL) { err = DB_ERROR; } - -#ifdef MYSQL_ENCRYPTION - /* For encryption tablespace, initialize encryption - information.*/ - if (err == DB_SUCCESS && is_encrypted && !for_import) { - Datafile& df_current = df_remote.is_open() ? - df_remote: df_dict.is_open() ? - df_dict : df_default; - - byte* key = df_current.m_encryption_key; - byte* iv = df_current.m_encryption_iv; - ut_ad(key && iv); - - err = fil_set_encryption(space->id, Encryption::AES, - key, iv); - ut_ad(err == DB_SUCCESS); - } -#endif /* MYSQL_ENCRYPTION */ - } return(err); @@ -4812,21 +4755,6 @@ fil_ibd_load( ut_error; } -#ifdef MYSQL_ENCRYPTION - /* For encryption tablespace, initial encryption information. */ - if (FSP_FLAGS_GET_ENCRYPTION(space->flags) - && file.m_encryption_key != NULL) { - dberr_t err = fil_set_encryption(space->id, - Encryption::AES, - file.m_encryption_key, - file.m_encryption_iv); - if (err != DB_SUCCESS) { - ib::error() << "Can't set encryption information for" - " tablespace " << space->name << "!"; - } - } -#endif /* MYSQL_ENCRYPTION */ - return(FIL_LOAD_OK); } @@ -5296,33 +5224,6 @@ fil_report_invalid_page_access( _exit(1); } -#ifdef MYSQL_ENCRYPTION -/** Set encryption information for IORequest. -@param[in,out] req_type IO request -@param[in] page_id page id -@param[in] space table space */ -inline -void -fil_io_set_encryption( - IORequest& req_type, - const page_id_t& page_id, - fil_space_t* space) -{ - /* Don't encrypt the log, page 0 of all tablespaces, all pages - from the system tablespace. */ - if (!req_type.is_log() && page_id.page_no() > 0 - && space->encryption_type != Encryption::NONE) - { - req_type.encryption_key(space->encryption_key, - space->encryption_klen, - space->encryption_iv); - req_type.encryption_algorithm(Encryption::AES); - } else { - req_type.clear_encrypted(); - } -} -#endif /* MYSQL_ENCRYPTION */ - /** Reads or writes data. This operation could be asynchronous (aio). @param[in,out] type IO context @@ -5609,11 +5510,6 @@ fil_io( } #endif /* MYSQL_COMPRESSION */ -#ifdef MYSQL_ENCRYPTION - /* Set encryption information. */ - fil_io_set_encryption(req_type, page_id, space); -#endif /* MYSQL_ENCRYPTION */ - req_type.block_size(node->block_size); /* Queue the aio request */ @@ -6001,8 +5897,6 @@ struct fil_iterator_t { byte* io_buffer; /*!< Buffer to use for IO */ fil_space_crypt_t *crypt_data; /*!< MariaDB Crypt data (if encrypted) */ byte* crypt_io_buffer; /*!< MariaDB IO buffer when encrypted */ - byte* encryption_key; /*!< Encryption key */ - byte* encryption_iv; /*!< Encryption iv */ }; /********************************************************************//** @@ -6080,16 +5974,6 @@ fil_iterate( dberr_t err = DB_SUCCESS; IORequest read_request(read_type); -#ifdef MYSQL_ENCRYPTION - /* For encrypted table, set encryption information. */ - if (iter.encryption_key != NULL && offset != 0) { - read_request.encryption_key(iter.encryption_key, - ENCRYPTION_KEY_LEN, - iter.encryption_iv); - read_request.encryption_algorithm(Encryption::AES); - } -#endif /* MYSQL_ENCRYPTION */ - byte* readptr = io_buffer; byte* writeptr = io_buffer; bool encrypted = false; @@ -6266,16 +6150,6 @@ fil_iterate( IORequest write_request(write_type); -#ifdef MYSQL_ENCRYPTION - /* For encrypted table, set encryption information. */ - if (iter.encryption_key != NULL && offset != 0) { - write_request.encryption_key(iter.encryption_key, - ENCRYPTION_KEY_LEN, - iter.encryption_iv); - write_request.encryption_algorithm(Encryption::AES); - } -#endif /* MYSQL_ENCRYPTION */ - /* A page was updated in the set, write back to disk. Note: We don't have the compression algorithm, we write out the imported file as uncompressed. */ @@ -6423,26 +6297,6 @@ fil_tablespace_iterate( + fsp_header_get_encryption_offset( callback.get_page_size())); -#ifdef MYSQL_ENCRYPTION - /* Set encryption info. */ - iter.encryption_key = table->encryption_key; - iter.encryption_iv = table->encryption_iv; - - /* Check encryption is matched or not. */ - ulint space_flags = callback.get_space_flags(); - if (FSP_FLAGS_GET_ENCRYPTION(space_flags)) { - ut_ad(table->encryption_key != NULL); - - if (!dict_table_is_encrypted(table)) { - ib::error() << "Table is not in an encrypted" - " tablespace, but the data file which" - " trying to import is an encrypted" - " tablespace"; - err = DB_IO_NO_ENCRYPT_TABLESPACE; - } - } -#endif /* MYSQL_ENCRYPTION */ - if (err == DB_SUCCESS) { /* Compressed pages can't be optimised for block IO @@ -7046,101 +6900,6 @@ fil_get_compression( return(space == NULL ? Compression::NONE : space->compression_type); } - -/** Set the encryption type for the tablespace -@param[in] space_id Space ID of tablespace for which to set -@param[in] algorithm Encryption algorithm -@param[in] key Encryption key -@param[in] iv Encryption iv -@return DB_SUCCESS or error code */ -dberr_t -fil_set_encryption( - ulint space_id, - Encryption::Type algorithm, - byte* key, - byte* iv) -{ - ut_ad(!is_system_or_undo_tablespace(space_id)); - - if (is_system_tablespace(space_id)) { - return(DB_IO_NO_ENCRYPT_TABLESPACE); - } - - mutex_enter(&fil_system->mutex); - - fil_space_t* space = fil_space_get_by_id(space_id); - - if (space == NULL) { - mutex_exit(&fil_system->mutex); - return(DB_NOT_FOUND); - } - - ut_ad(algorithm != Encryption::NONE); - space->encryption_type = algorithm; - if (key == NULL) { - Encryption::random_value(space->encryption_key); - } else { - memcpy(space->encryption_key, - key, ENCRYPTION_KEY_LEN); - } - - space->encryption_klen = ENCRYPTION_KEY_LEN; - if (iv == NULL) { - Encryption::random_value(space->encryption_iv); - } else { - memcpy(space->encryption_iv, - iv, ENCRYPTION_KEY_LEN); - } - - mutex_exit(&fil_system->mutex); - - return(DB_SUCCESS); -} - -/** Rotate the tablespace keys by new master key. -@return true if the re-encrypt suceeds */ -bool -fil_encryption_rotate() -{ - fil_space_t* space; - mtr_t mtr; - byte encrypt_info[ENCRYPTION_INFO_SIZE_V2]; - - for (space = UT_LIST_GET_FIRST(fil_system->space_list); - space != NULL; ) { - /* Skip unencypted tablespaces. */ - if (is_system_or_undo_tablespace(space->id) - || fsp_is_system_temporary(space->id) - || space->purpose == FIL_TYPE_LOG) { - space = UT_LIST_GET_NEXT(space_list, space); - continue; - } - - if (space->encryption_type != Encryption::NONE) { - mtr_start(&mtr); - mtr.set_named_space(space->id); - - space = mtr_x_lock_space(space->id, &mtr); - - memset(encrypt_info, 0, ENCRYPTION_INFO_SIZE_V2); - - if (!fsp_header_rotate_encryption(space, - encrypt_info, - &mtr)) { - mtr_commit(&mtr); - return(false); - } - - mtr_commit(&mtr); - } - - space = UT_LIST_GET_NEXT(space_list, space); - DBUG_EXECUTE_IF("ib_crash_during_rotation_for_encryption", - DBUG_SUICIDE();); - } - - return(true); -} #endif /* MYSQL_COMPRESSION */ /** Build the basic folder name from the path and length provided @@ -7300,7 +7059,6 @@ test_make_filepath() path = MF("/this/is/a/path/with/a/filename", NULL, IBD, false); DISPLAY; path = MF("/this/is/a/path/with/a/filename", NULL, ISL, false); DISPLAY; path = MF("/this/is/a/path/with/a/filename", NULL, CFG, false); DISPLAY; - path = MF("/this/is/a/path/with/a/filename", NULL, CFP, false); DISPLAY; path = MF("/this/is/a/path/with/a/filename.ibd", NULL, IBD, false); DISPLAY; path = MF("/this/is/a/path/with/a/filename.ibd", NULL, IBD, false); DISPLAY; path = MF("/this/is/a/path/with/a/filename.dat", NULL, IBD, false); DISPLAY; @@ -7310,7 +7068,6 @@ test_make_filepath() path = MF(NULL, "dbname/tablespacename", IBD, false); DISPLAY; path = MF(NULL, "dbname/tablespacename", ISL, false); DISPLAY; path = MF(NULL, "dbname/tablespacename", CFG, false); DISPLAY; - path = MF(NULL, "dbname/tablespacename", CFP, false); DISPLAY; path = MF(NULL, "dbname\\tablespacename", NO_EXT, false); DISPLAY; path = MF(NULL, "dbname\\tablespacename", IBD, false); DISPLAY; path = MF("/this/is/a/path", "dbname/tablespacename", IBD, false); DISPLAY; diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 0e1d2f3233b..3b89da2301b 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -47,8 +47,6 @@ Datafile::init( m_name = mem_strdup(name); m_flags = flags; - m_encryption_key = NULL; - m_encryption_iv = NULL; } /** Release the resources. */ @@ -60,16 +58,10 @@ Datafile::shutdown() ut_free(m_name); m_name = NULL; - ut_free(m_encryption_key); - m_encryption_key = NULL; - /* The fil_space_t::crypt_data was freed in fil_space_free_low(). Invalidate our redundant pointer. */ m_crypt_info = NULL; - ut_free(m_encryption_iv); - m_encryption_iv = NULL; - free_filepath(); free_first_page(); } @@ -459,11 +451,6 @@ Datafile::validate_for_recovery() break; default: - /* For encryption tablespace, we skip the retry step, - since it is only because the keyring is not ready. */ - if (FSP_FLAGS_GET_ENCRYPTION(m_flags)) { - return(err); - } /* Re-open the file in read-write mode Attempt to restore page 0 from doublewrite and read the space ID from a survey of the first few pages. */ @@ -602,51 +589,6 @@ Datafile::validate_first_page(lsn_t* flush_lsn, } -#ifdef MYSQL_ENCRYPTION - /* For encrypted tablespace, check the encryption info in the - first page can be decrypt by master key, otherwise, this table - can't be open. And for importing, we skip checking it. */ - if (FSP_FLAGS_GET_ENCRYPTION(m_flags) && !for_import) { - m_encryption_key = static_cast( - ut_zalloc_nokey(ENCRYPTION_KEY_LEN)); - m_encryption_iv = static_cast( - ut_zalloc_nokey(ENCRYPTION_KEY_LEN)); -#ifdef UNIV_ENCRYPT_DEBUG - fprintf(stderr, "Got from file %lu:", m_space_id); -#endif - if (!fsp_header_get_encryption_key(m_flags, - m_encryption_key, - m_encryption_iv, - m_first_page)) { - ib::error() - << "Encryption information in" - << " datafile: " << m_filepath - << " can't be decrypted" - << " , please confirm the keyfile" - << " is match and keyring plugin" - << " is loaded."; - - m_is_valid = false; - free_first_page(); - ut_free(m_encryption_key); - ut_free(m_encryption_iv); - m_encryption_key = NULL; - m_encryption_iv = NULL; - return(DB_CORRUPTION); - } - - if (recv_recovery_is_on() - && memcmp(m_encryption_key, - m_encryption_iv, - ENCRYPTION_KEY_LEN) == 0) { - ut_free(m_encryption_key); - ut_free(m_encryption_iv); - m_encryption_key = NULL; - m_encryption_iv = NULL; - } - } -#endif /* MYSQL_ENCRYPTION */ - if (fil_space_read_name_and_filepath( m_space_id, &prev_name, &prev_filepath)) { diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 4fa1d92a6fd..2dd96bdbd04 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -230,7 +230,6 @@ fsp_flags_is_valid( bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags); bool is_shared = FSP_FLAGS_GET_SHARED(flags); bool is_temp = FSP_FLAGS_GET_TEMPORARY(flags); - bool is_encryption = FSP_FLAGS_GET_ENCRYPTION(flags); ulint unused = FSP_FLAGS_GET_UNUSED(flags); bool page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags); ulint page_compression_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(flags); @@ -285,12 +284,6 @@ fsp_flags_is_valid( return(false); } - /* Only single-table and not temp tablespaces use the encryption - clause. */ - if (is_encryption && (is_shared || is_temp)) { - GOTO_ERROR; - } - /* Page compression level requires page compression and atomic blobs to be set */ if (page_compression_level || page_compression) { @@ -320,7 +313,6 @@ err_exit: << " has_data_dir: " << has_data_dir << " is_shared: " << is_shared << " is_temp: " << is_temp - << " is_encryption: " << is_encryption << " page_compressed: " << page_compression << " page_compression_level: " << page_compression_level; return (false); @@ -869,178 +861,6 @@ fsp_header_init_fields( flags); } -#if 0 /* MySQL 5.7 Encryption */ -/** Fill the encryption info. -@param[in] space tablespace -@param[in,out] encrypt_info buffer for encrypt key. -@return true if success. */ -bool -fsp_header_fill_encryption_info( - fil_space_t* space, - byte* encrypt_info) -{ - byte* ptr; - lint elen; - ulint master_key_id; - byte* master_key; - byte key_info[ENCRYPTION_KEY_LEN * 2]; - ulint crc; - Encryption::Version version; -#ifdef UNIV_ENCRYPT_DEBUG - const byte* data; - ulint i; -#endif - - /* Get master key from key ring */ - Encryption::get_master_key(&master_key_id, &master_key, &version); - if (master_key == NULL) { - return(false); - } - - memset(encrypt_info, 0, ENCRYPTION_INFO_SIZE_V2); - memset(key_info, 0, ENCRYPTION_KEY_LEN * 2); - - /* Use the new master key to encrypt the tablespace - key. */ - ut_ad(encrypt_info != NULL); - ptr = encrypt_info; - - /* Write magic header. */ - if (version == Encryption::ENCRYPTION_VERSION_1) { - memcpy(ptr, ENCRYPTION_KEY_MAGIC_V1, ENCRYPTION_MAGIC_SIZE); - } else { - memcpy(ptr, ENCRYPTION_KEY_MAGIC_V2, ENCRYPTION_MAGIC_SIZE); - } - ptr += ENCRYPTION_MAGIC_SIZE; - - /* Write master key id. */ - mach_write_to_4(ptr, master_key_id); - ptr += sizeof(ulint); - - /* Write server uuid. */ - if (version == Encryption::ENCRYPTION_VERSION_2) { - memcpy(ptr, Encryption::uuid, ENCRYPTION_SERVER_UUID_LEN); - ptr += ENCRYPTION_SERVER_UUID_LEN; - } - - /* Write tablespace key to temp space. */ - memcpy(key_info, - space->encryption_key, - ENCRYPTION_KEY_LEN); - - /* Write tablespace iv to temp space. */ - memcpy(key_info + ENCRYPTION_KEY_LEN, - space->encryption_iv, - ENCRYPTION_KEY_LEN); - -#ifdef UNIV_ENCRYPT_DEBUG - fprintf(stderr, "Set %lu:%lu ",space->id, - Encryption::master_key_id); - for (data = (const byte*) master_key, i = 0; - i < ENCRYPTION_KEY_LEN; i++) - fprintf(stderr, "%02lx", (ulong)*data++); - fprintf(stderr, " "); - for (data = (const byte*) space->encryption_key, - i = 0; i < ENCRYPTION_KEY_LEN; i++) - fprintf(stderr, "%02lx", (ulong)*data++); - fprintf(stderr, " "); - for (data = (const byte*) space->encryption_iv, - i = 0; i < ENCRYPTION_KEY_LEN; i++) - fprintf(stderr, "%02lx", (ulong)*data++); - fprintf(stderr, "\n"); -#endif - /* Encrypt tablespace key and iv. */ - elen = my_aes_encrypt( - key_info, - ENCRYPTION_KEY_LEN * 2, - ptr, - master_key, - ENCRYPTION_KEY_LEN, - my_aes_256_ecb, - NULL, false); - - if (elen == MY_AES_BAD_DATA) { - my_free(master_key); - return(false); - } - - ptr += ENCRYPTION_KEY_LEN * 2; - - /* Write checksum bytes. */ - crc = ut_crc32(key_info, ENCRYPTION_KEY_LEN * 2); - mach_write_to_4(ptr, crc); - - my_free(master_key); - return(true); -} -#endif /* ! */ - -/** Rotate the encryption info in the space header. -@param[in] space tablespace -@param[in] encrypt_info buffer for re-encrypt key. -@param[in,out] mtr mini-transaction -@return true if success. */ -bool -fsp_header_rotate_encryption( - fil_space_t* space, - byte* encrypt_info, - mtr_t* mtr) -{ - buf_block_t* block; - ulint offset; - - ut_ad(mtr); - - const page_size_t page_size(space->flags); - -#if MYSQL_ENCRYPTION - page_t* page; - ulint master_key_id; - ut_ad(space->encryption_type != Encryption::NONE); - /* Fill encryption info. */ - if (!fsp_header_fill_encryption_info(space, - encrypt_info)) { - return(false); - } -#endif - - /* Save the encryption info to the page 0. */ - block = buf_page_get(page_id_t(space->id, 0), - page_size, - RW_SX_LATCH, mtr); - buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - ut_ad(space->id == page_get_space_id(buf_block_get_frame(block))); - - offset = fsp_header_get_encryption_offset(page_size); - ut_ad(offset != 0 && offset < UNIV_PAGE_SIZE); - - -#if MYSQL_ENCRYPTION - page = buf_block_get_frame(block); - /* If is in recovering, skip all master key id is rotated - tablespaces. */ - master_key_id = mach_read_from_4( - page + offset + ENCRYPTION_MAGIC_SIZE); - if (recv_recovery_is_on() - && master_key_id == Encryption::master_key_id) { - ut_ad(memcmp(page + offset, - ENCRYPTION_KEY_MAGIC_V1, - ENCRYPTION_MAGIC_SIZE) == 0 - || memcmp(page + offset, - ENCRYPTION_KEY_MAGIC_V2, - ENCRYPTION_MAGIC_SIZE) == 0); - return(true); - } - - mlog_write_string(page + offset, - encrypt_info, - ENCRYPTION_INFO_SIZE_V2, - mtr); -#endif /* MYSQL_ENCRYPTION */ - - return(true); -} - /** Initializes the space header of a new created space and creates also the insert buffer tree root if space == 0. @param[in] space_id space id @@ -1102,31 +922,6 @@ fsp_header_init( fsp_fill_free_list(!is_system_tablespace(space_id), space, header, mtr); -#if 0 /* MySQL 5.7 Encryption */ - /* For encryption tablespace, we need to save the encryption - info to the page 0. */ - if (FSP_FLAGS_GET_ENCRYPTION(space->flags)) { - ulint offset = fsp_header_get_encryption_offset(page_size); - byte encryption_info[ENCRYPTION_INFO_SIZE_V2]; - - if (offset == 0) - return(false); - - if (!fsp_header_fill_encryption_info(space, - encryption_info)) { - space->encryption_type = Encryption::NONE; - memset(space->encryption_key, 0, ENCRYPTION_KEY_LEN); - memset(space->encryption_iv, 0, ENCRYPTION_KEY_LEN); - return(false); - } - - mlog_write_string(page + offset, - encryption_info, - ENCRYPTION_INFO_SIZE_V2, - mtr); - } -#endif /* ! */ - if (space_id == srv_sys_space.space_id()) { if (btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, 0, univ_page_size, DICT_IBUF_ID_MIN + space_id, @@ -1181,164 +976,6 @@ fsp_header_get_page_size( return(page_size_t(fsp_header_get_flags(page))); } -#if 0 /* MySQL 5.7 Encryption */ -/** Decoding the encryption info -from the first page of a tablespace. -@param[in/out] key key -@param[in/out] iv iv -@param[in] encryption_info encrytion info. -@return true if success */ -bool -fsp_header_decode_encryption_info( - byte* key, - byte* iv, - byte* encryption_info) -{ - byte* ptr; - ulint master_key_id; - byte* master_key = NULL; - lint elen; - byte key_info[ENCRYPTION_KEY_LEN * 2]; - ulint crc1; - ulint crc2; - char srv_uuid[ENCRYPTION_SERVER_UUID_LEN + 1]; - Encryption::Version version; -#ifdef UNIV_ENCRYPT_DEBUG - const byte* data; - ulint i; -#endif - - ptr = encryption_info; - - /* For compatibility with 5.7.11, we need to handle the - encryption information which created in this old version. */ - if (memcmp(ptr, ENCRYPTION_KEY_MAGIC_V1, - ENCRYPTION_MAGIC_SIZE) == 0) { - version = Encryption::ENCRYPTION_VERSION_1; - } else { - version = Encryption::ENCRYPTION_VERSION_2; - } - /* Check magic. */ - if (version == Encryption::ENCRYPTION_VERSION_2 - && memcmp(ptr, ENCRYPTION_KEY_MAGIC_V2, ENCRYPTION_MAGIC_SIZE) != 0) { - /* We ignore report error for recovery, - since the encryption info maybe hasn't writen - into datafile when the table is newly created. */ - if (!recv_recovery_is_on()) { - return(false); - } else { - return(true); - } - } - ptr += ENCRYPTION_MAGIC_SIZE; - - /* Get master key id. */ - master_key_id = mach_read_from_4(ptr); - ptr += sizeof(ulint); - - /* Get server uuid. */ - if (version == Encryption::ENCRYPTION_VERSION_2) { - memset(srv_uuid, 0, ENCRYPTION_SERVER_UUID_LEN + 1); - memcpy(srv_uuid, ptr, ENCRYPTION_SERVER_UUID_LEN); - ptr += ENCRYPTION_SERVER_UUID_LEN; - } - - /* Get master key by key id. */ - memset(key_info, 0, ENCRYPTION_KEY_LEN * 2); - if (version == Encryption::ENCRYPTION_VERSION_1) { - Encryption::get_master_key(master_key_id, NULL, &master_key); - } else { - Encryption::get_master_key(master_key_id, srv_uuid, &master_key); - } - if (master_key == NULL) { - return(false); - } - -#ifdef UNIV_ENCRYPT_DEBUG - fprintf(stderr, "%lu ", master_key_id); - for (data = (const byte*) master_key, i = 0; - i < ENCRYPTION_KEY_LEN; i++) - fprintf(stderr, "%02lx", (ulong)*data++); -#endif - - /* Decrypt tablespace key and iv. */ - elen = my_aes_decrypt( - ptr, - ENCRYPTION_KEY_LEN * 2, - key_info, - master_key, - ENCRYPTION_KEY_LEN, - my_aes_256_ecb, NULL, false); - - if (elen == MY_AES_BAD_DATA) { - my_free(master_key); - return(NULL); - } - - /* Check checksum bytes. */ - ptr += ENCRYPTION_KEY_LEN * 2; - - crc1 = mach_read_from_4(ptr); - crc2 = ut_crc32(key_info, ENCRYPTION_KEY_LEN * 2); - if (crc1 != crc2) { - ib::error() << "Failed to decrpt encryption information," - << " please check key file is not changed!"; - return(false); - } - - /* Get tablespace key */ - memcpy(key, key_info, ENCRYPTION_KEY_LEN); - - /* Get tablespace iv */ - memcpy(iv, key_info + ENCRYPTION_KEY_LEN, - ENCRYPTION_KEY_LEN); - -#ifdef UNIV_ENCRYPT_DEBUG - fprintf(stderr, " "); - for (data = (const byte*) key, - i = 0; i < ENCRYPTION_KEY_LEN; i++) - fprintf(stderr, "%02lx", (ulong)*data++); - fprintf(stderr, " "); - for (data = (const byte*) iv, - i = 0; i < ENCRYPTION_KEY_LEN; i++) - fprintf(stderr, "%02lx", (ulong)*data++); - fprintf(stderr, "\n"); -#endif - - my_free(master_key); - - if (Encryption::master_key_id < master_key_id) { - Encryption::master_key_id = master_key_id; - memcpy(Encryption::uuid, srv_uuid, ENCRYPTION_SERVER_UUID_LEN); - } - - return(true); -} - -/** Reads the encryption key from the first page of a tablespace. -@param[in] fsp_flags tablespace flags -@param[in/out] key tablespace key -@param[in/out] iv tablespace iv -@param[in] page first page of a tablespace -@return true if success */ -bool -fsp_header_get_encryption_key( - ulint fsp_flags, - byte* key, - byte* iv, - page_t* page) -{ - ulint offset; - const page_size_t page_size(fsp_flags); - offset = fsp_header_get_encryption_offset(page_size); - if (offset == 0) { - return(false); - } - - return(fsp_header_decode_encryption_info(key, iv, page + offset)); -} -#endif /* ! */ - /**********************************************************************//** Increases the space size field of a space. */ void diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 4e1d8e3367b..0fe23301c32 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -608,8 +608,7 @@ static PSI_mutex_info all_innodb_mutexes[] = { PSI_KEY(rtr_path_mutex), PSI_KEY(rtr_ssn_mutex), PSI_KEY(trx_sys_mutex), - PSI_KEY(zip_pad_mutex), - PSI_KEY(master_key_id_mutex), + PSI_KEY(zip_pad_mutex) }; # endif /* UNIV_PFS_MUTEX */ @@ -2887,60 +2886,6 @@ Compression::validate(const char* algorithm) } #endif /* MYSQL_COMPRESSION */ -#ifdef MYSQL_ENCRYPTION -/** Check if the string is "" or "n". -@param[in] algorithm Encryption algorithm to check -@return true if no algorithm requested */ -bool -Encryption::is_none(const char* algorithm) -{ - /* NULL is the same as NONE */ - if (algorithm == NULL - || innobase_strcasecmp(algorithm, "n") == 0 - || innobase_strcasecmp(algorithm, "") == 0) { - return(true); - } - - return(false); -} - -/** Check the encryption option and set it -@param[in] option encryption option -@param[in/out] encryption The encryption algorithm -@return DB_SUCCESS or DB_UNSUPPORTED */ -dberr_t -Encryption::set_algorithm( - const char* option, - Encryption* encryption) -{ - if (is_none(option)) { - - encryption->m_type = NONE; - - } else if (innobase_strcasecmp(option, "y") == 0) { - - encryption->m_type = AES; - - } else { - return(DB_UNSUPPORTED); - } - - return(DB_SUCCESS); -} - -/** Check for supported ENCRYPT := (Y | N) supported values -@param[in] option Encryption option -@param[out] encryption The encryption algorithm -@return DB_SUCCESS or DB_UNSUPPORTED */ -dberr_t -Encryption::validate(const char* option) -{ - Encryption encryption; - - return(encryption.set_algorithm(option, &encryption)); -} -#endif /* MYSQL_ENCRYPTION */ - /*********************************************************************//** Compute the next autoinc value. @@ -3961,67 +3906,6 @@ innobase_init_abort() DBUG_RETURN(1); } - -#ifdef MYSQL_ENCRYPTION -/* mutex protecting the master_key_id */ -ib_mutex_t master_key_id_mutex; - -/** Rotate the encrypted tablespace keys according to master key -rotation. -@return false on success, true on failure */ -bool -innobase_encryption_key_rotation() -{ - byte* master_key = NULL; - bool ret = FALSE; - - /* Require the mutex to block other rotate request. */ - mutex_enter(&master_key_id_mutex); - - /* Check if keyring loaded and the currently master key - can be fetched. */ - if (Encryption::master_key_id != 0) { - ulint master_key_id; - Encryption::Version version; - - Encryption::get_master_key(&master_key_id, - &master_key, - &version); - if (master_key == NULL) { - mutex_exit(&master_key_id_mutex); - my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); - return(true); - } - my_free(master_key); - } - - master_key = NULL; - - /* Generate the new master key. */ - Encryption::create_master_key(&master_key); - - if (master_key == NULL) { - my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); - mutex_exit(&master_key_id_mutex); - return(true); - } - - ret = !fil_encryption_rotate(); - - my_free(master_key); - - /* If rotation failure, return error */ - if (ret) { - my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); - } - - /* Release the mutex. */ - mutex_exit(&master_key_id_mutex); - - return(ret); -} -#endif /* MYSQL_ENCRYPTION */ - /** Return partitioning flags. */ static uint innobase_partition_flags() { @@ -4160,11 +4044,6 @@ innobase_init( innodb_remember_check_sysvar_funcs(); -#ifdef MYSQL_ENCRYPTION - innobase_hton->rotate_encryption_master_key = - innobase_encryption_key_rotation; -#endif - ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); #ifndef DBUG_OFF @@ -4742,11 +4621,6 @@ innobase_change_buffering_inited_ok: DBUG_RETURN(innobase_init_abort()); } -#ifdef MYSQL_ENCRYPTION - /* Create mutex to protect encryption master_key_id. */ - mutex_create(LATCH_ID_MASTER_KEY_ID_MUTEX, &master_key_id_mutex); -#endif - /* Adjust the innodb_undo_logs config object */ innobase_undo_logs_init_default_max(); @@ -4850,10 +4724,6 @@ innobase_end( hash_table_free(innobase_open_tables); innobase_open_tables = NULL; -#ifdef MYSQL_ENCRYPTION - mutex_free(&master_key_id_mutex); -#endif - if (!abort_loop && thd_destructor_myvar) { // may be UNINSTALL PLUGIN statement thd_destructor_myvar->abort = 1; @@ -6887,28 +6757,6 @@ ha_innobase::open( is_part = NULL; } -#ifdef MYSQL_ENCRYPTION - /* For encrypted table, check if the encryption info in data - file can't be retrieved properly, mark it as corrupted. */ - if (ib_table != NULL - && dict_table_is_encrypted(ib_table) - && ib_table->ibd_file_missing - && !dict_table_is_discarded(ib_table)) { - - /* Mark this table as corrupted, so the drop table - or force recovery can still use it, but not others. */ - - dict_table_close(ib_table, FALSE, FALSE); - ib_table = NULL; - is_part = NULL; - - free_share(m_share); - my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, MYF(0)); - - DBUG_RETURN(HA_ERR_TABLE_CORRUPT); - } -#endif - if (NULL == ib_table) { if (is_part) { @@ -12262,13 +12110,6 @@ err_col: err = DB_UNSUPPORTED; - dict_mem_table_free(table); - } else if (m_create_info->encrypt_type.length > 0 - && !Encryption::is_none( - m_create_info->encrypt_type.str)) { - - my_error(ER_TABLESPACE_CANNOT_ENCRYPT, MYF(0)); - err = DB_UNSUPPORTED; dict_mem_table_free(table); } else { #endif /* MYSQL_COMPRESSION */ @@ -12325,39 +12166,6 @@ err_col: algorithm = NULL; } - - const char* encrypt = m_create_info->encrypt_type.str; - - if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE) - && m_create_info->encrypt_type.length > 0 - && !Encryption::is_none(encrypt)) { - - my_error(ER_TABLESPACE_CANNOT_ENCRYPT, MYF(0)); - err = DB_UNSUPPORTED; - dict_mem_table_free(table); - - } else if (!Encryption::is_none(encrypt)) { - /* Set the encryption flag. */ - byte* master_key = NULL; - ulint master_key_id; - Encryption::Version version; - - /* Check if keyring is ready. */ - Encryption::get_master_key(&master_key_id, - &master_key, - &version); - - if (master_key == NULL) { - my_error(ER_CANNOT_FIND_KEY_IN_KEYRING, - MYF(0)); - err = DB_UNSUPPORTED; - dict_mem_table_free(table); - } else { - my_free(master_key); - DICT_TF2_FLAG_SET(table, - DICT_TF2_ENCRYPTION); - } - } #endif /* MYSQL_COMPRESSION */ if (err == DB_SUCCESS) { @@ -13472,29 +13280,6 @@ create_table_info_t::innobase_table_flags() } #endif -#ifdef MYSQL_ENCRYPTION - /* Validate the page encryption parameter. */ - if (m_create_info->encrypt_type.length > 0) { - - const char* encryption = m_create_info->encrypt_type.str; - - if (Encryption::validate(encryption) != DB_SUCCESS) { - /* Incorrect encryption option */ - my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); - DBUG_RETURN(false); - } - - if (m_use_shared_space - || (m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - if (!Encryption::is_none(encryption)) { - /* Can't encrypt shared tablespace */ - my_error(ER_TABLESPACE_CANNOT_ENCRYPT, MYF(0)); - DBUG_RETURN(false); - } - } - } -#endif /* MYSQL_ENCRYPTION */ - /* Check if there are any FTS indexes defined on this table. */ for (uint i = 0; i < m_form->s->keys; i++) { const KEY* key = &m_form->key_info[i]; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index ca14542c9b5..004b6863a9f 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -588,21 +588,6 @@ ha_innobase::check_if_supported_inplace_alter( DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } -#ifdef MYSQL_ENCRYPTION - /* We don't support change encryption attribute with - inplace algorithm. */ - char* old_encryption = this->table->s->encrypt_type.str; - char* new_encryption = altered_table->s->encrypt_type.str; - - if (Encryption::is_none(old_encryption) - != Encryption::is_none(new_encryption)) { - ha_alter_info->unsupported_reason = - innobase_get_err_msg( - ER_UNSUPPORTED_ALTER_ENCRYPTION_INPLACE); - DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); - } -#endif /* MYSQL_ENCRYPTION */ - update_thd(); trx_search_latch_release_if_reserved(m_prebuilt->trx); diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index 32f9117af84..d4757d93509 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -158,12 +158,6 @@ enum dberr_t { DB_IO_NO_PUNCH_HOLE_TABLESPACE, /*!< The tablespace doesn't support punch hole */ - DB_IO_DECRYPT_FAIL, /*!< Failure to decrypt a page - after reading it from disk */ - - DB_IO_NO_ENCRYPT_TABLESPACE, /*!< The tablespace doesn't support - encrypt */ - DB_IO_PARTIAL_FAILED, /*!< Partial IO request failed */ DB_FORCED_ABORT, /*!< Transaction was forced to rollback diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index ca3951dd309..b29e6aedcc0 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1035,13 +1035,11 @@ fil_space_t::flags | 0 | 0 | 1 | 1 ================================================================== @param[in] table_flags dict_table_t::flags @param[in] is_temp whether the tablespace is temporary -@param[in] is_encrypted whether the tablespace is encrypted @return tablespace flags (fil_space_t::flags) */ ulint dict_tf_to_fsp_flags( ulint table_flags, - bool is_temp, - bool is_encrypted = false) + bool is_temp) MY_ATTRIBUTE((const)); /** Extract the page size from table flags. @@ -1975,16 +1973,6 @@ dict_table_is_temporary( const dict_table_t* table) /*!< in: table to check */ MY_ATTRIBUTE((warn_unused_result)); -/********************************************************************//** -Check if it is a encrypted table. -@return true if table encryption flag is set. */ -UNIV_INLINE -bool -dict_table_is_encrypted( -/*====================*/ - const dict_table_t* table) /*!< in: table to check */ - MY_ATTRIBUTE((warn_unused_result)); - /** Check if the table is in a shared tablespace (System or General). @param[in] id Space ID to check @return true if id is a shared tablespace, false if not. */ diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index c7d553f5daa..c8624ea8b7d 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1744,18 +1744,6 @@ dict_table_is_temporary( return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)); } -/********************************************************************//** -Check if it is a encrypted table. -@return true if table encrypted flag is set. */ -UNIV_INLINE -bool -dict_table_is_encrypted( -/*====================*/ - const dict_table_t* table) /*!< in: table to check */ -{ - return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_ENCRYPTION)); -} - /** Check if the table is in a shared tablespace (System or General). @param[in] id Space ID to check @return true if id is a shared tablespace, false if not. */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 538306f7af8..68d2f5d07fa 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -334,9 +334,6 @@ use its own tablespace instead of the system tablespace. */ index tables) of a FTS table are in HEX format. */ #define DICT_TF2_FTS_AUX_HEX_NAME 64 -/** Encryption table bit. */ -#define DICT_TF2_ENCRYPTION 256 - /* @} */ #define DICT_TF2_FLAG_SET(table, flag) \ @@ -1779,12 +1776,6 @@ public: /** mysql_row_templ_t for base columns used for compute the virtual columns */ dict_vcol_templ_t* vc_templ; - - /** encryption key, it's only for export/import */ - byte* encryption_key; - - /** encryption iv, it's only for export/import */ - byte* encryption_iv; }; /*******************************************************************//** diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 0197dfaabb4..6410c86939b 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -169,18 +169,6 @@ struct fil_space_t { /** Compression algorithm */ Compression::Type compression_type; - /** Encryption algorithm */ - Encryption::Type encryption_type; - - /** Encrypt key */ - byte encryption_key[ENCRYPTION_KEY_LEN]; - - /** Encrypt key length*/ - ulint encryption_klen; - - /** Encrypt initial vector */ - byte encryption_iv[ENCRYPTION_KEY_LEN]; - /** MariaDB encryption data */ fil_space_crypt_t* crypt_data; @@ -267,14 +255,12 @@ enum ib_extention { NO_EXT = 0, IBD = 1, ISL = 2, - CFG = 3, - CFP = 4 + CFG = 3 }; extern const char* dot_ext[]; #define DOT_IBD dot_ext[IBD] #define DOT_ISL dot_ext[ISL] #define DOT_CFG dot_ext[CFG] -#define DOT_CPF dot_ext[CFP] /** Wrapper for a path to a directory. This folder may or may not yet esist. Since not all directory paths @@ -1654,25 +1640,6 @@ fil_get_compression( ulint space_id) MY_ATTRIBUTE((warn_unused_result)); -/** Set the encryption type for the tablespace -@param[in] space Space ID of tablespace for which to set -@param[in] algorithm Encryption algorithm -@param[in] key Encryption key -@param[in] iv Encryption iv -@return DB_SUCCESS or error code */ -dberr_t -fil_set_encryption( - ulint space_id, - Encryption::Type algorithm, - byte* key, - byte* iv) - MY_ATTRIBUTE((warn_unused_result)); - -/** -@return true if the re-encrypt success */ -bool -fil_encryption_rotate(); - /** Write MLOG_FILE_NAME records if a persistent tablespace was modified for the first time since the latest fil_names_clear(). @param[in,out] space tablespace diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 82d086bcf7a..610c4e9927b 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -67,8 +67,6 @@ public: m_first_page(), m_last_os_error(), m_file_info(), - m_encryption_key(NULL), - m_encryption_iv(NULL), m_crypt_info() { /* No op */ @@ -92,8 +90,6 @@ public: m_first_page(), m_last_os_error(), m_file_info(), - m_encryption_key(NULL), - m_encryption_iv(NULL), m_crypt_info() { ut_ad(m_name != NULL); @@ -115,8 +111,6 @@ public: m_first_page(), m_last_os_error(), m_file_info(), - m_encryption_key(NULL), - m_encryption_iv(NULL), m_crypt_info() { m_name = mem_strdup(file.m_name); @@ -175,8 +169,6 @@ public: it should be reread if needed */ m_first_page_buf = NULL; m_first_page = NULL; - m_encryption_key = NULL; - m_encryption_iv = NULL; /* Do not copy crypt info it is read from first page */ m_crypt_info = NULL; @@ -484,12 +476,6 @@ public: struct stat m_file_info; #endif /* WIN32 */ - /** Encryption key read from first page */ - byte* m_encryption_key; - - /** Encryption iv read from first page */ - byte* m_encryption_iv; - /** Encryption information */ fil_space_crypt_t* m_crypt_info; }; diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 6ddcec78a01..edfb1bb47ef 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -336,31 +336,6 @@ page_size_t fsp_header_get_page_size( const page_t* page); -/** Decoding the encryption info -from the first page of a tablespace. -@param[in/out] key key -@param[in/out] iv iv -@param[in] encryption_info encrytion info. -@return true if success */ -bool -fsp_header_decode_encryption_info( - byte* key, - byte* iv, - byte* encryption_info); - -/** Reads the encryption key from the first page of a tablespace. -@param[in] fsp_flags tablespace flags -@param[in/out] key tablespace key -@param[in/out] iv tablespace iv -@param[in] page first page of a tablespace -@return true if success */ -bool -fsp_header_get_encryption_key( - ulint fsp_flags, - byte* key, - byte* iv, - page_t* page); - /** Get the byte offset of encryption information in page 0. @param[in] ps page size @return byte offset relative to FSP_HEADER_OFFSET */ @@ -392,17 +367,6 @@ fsp_header_init_fields( ulint flags); /*!< in: tablespace flags (FSP_SPACE_FLAGS): 0, or table->flags if newer than COMPACT */ -/** Rotate the encryption info in the space header. -@param[in] space tablespace -@param[in] encrypt_info buffer for re-encrypt key. -@param[in,out] mtr mini-transaction -@return true if success. */ -bool -fsp_header_rotate_encryption( - fil_space_t* space, - byte* encrypt_info, - mtr_t* mtr); - /** Initializes the space header of a new created space and creates also the insert buffer tree root if space == 0. @param[in] space_id space id @@ -696,7 +660,6 @@ fsp_flags_are_equal( @param[in] has_data_dir This tablespace is in a remote location. @param[in] is_shared This tablespace can be shared by many tables. @param[in] is_temporary This tablespace is temporary. -@param[in] is_encrypted This tablespace is encrypted. @return tablespace flags after initialization */ UNIV_INLINE ulint @@ -708,8 +671,7 @@ fsp_flags_init( bool is_temporary, bool page_compression, ulint page_compression_level, - ulint not_used, - bool is_encrypted = false); + ulint not_used); /** Convert a 32 bit integer tablespace flags to the 32 bit table flags. This can only be done for a tablespace that was built as a file-per-table diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index 31317969bf0..7f50bddb662 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -181,7 +181,6 @@ fsp_flags_set_page_size( @param[in] has_data_dir This tablespace is in a remote location. @param[in] is_shared This tablespace can be shared by many tables. @param[in] is_temporary This tablespace is temporary. -@param[in] is_encrypted This tablespace is encrypted. @param[in] page_compressed Table uses page compression @param[in] page_compression_level Page compression level @param[in] not_used For future @@ -196,8 +195,7 @@ fsp_flags_init( bool is_temporary, bool page_compression, ulint page_compression_level, - ulint not_used, - bool is_encrypted) + ulint not_used) { ut_ad(page_size.physical() <= page_size.logical()); ut_ad(!page_size.is_compressed() || atomic_blobs); @@ -231,10 +229,6 @@ fsp_flags_init( flags |= FSP_FLAGS_MASK_TEMPORARY; } - if (is_encrypted) { - flags |= FSP_FLAGS_MASK_ENCRYPTION; - } - /* In addition, tablespace flags also contain if the page compression is used for this table. */ if (page_compression) { diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h index c264fe1b595..9bbe58bb1dd 100644 --- a/storage/innobase/include/fsp0types.h +++ b/storage/innobase/include/fsp0types.h @@ -351,10 +351,6 @@ is a tablespace with encryption. */ #define FSP_FLAGS_MASK_TEMPORARY \ ((~(~0U << FSP_FLAGS_WIDTH_TEMPORARY)) \ << FSP_FLAGS_POS_TEMPORARY) -/** Bit mask of the ENCRYPTION field */ -#define FSP_FLAGS_MASK_ENCRYPTION \ - ((~(~0U << FSP_FLAGS_WIDTH_ENCRYPTION)) \ - << FSP_FLAGS_POS_ENCRYPTION) /** Bit mask of the PAGE_COMPRESSION field */ #define FSP_FLAGS_MASK_PAGE_COMPRESSION \ ((~(~0U << FSP_FLAGS_WIDTH_PAGE_COMPRESSION)) \ @@ -396,10 +392,6 @@ is a tablespace with encryption. */ #define FSP_FLAGS_GET_TEMPORARY(flags) \ ((flags & FSP_FLAGS_MASK_TEMPORARY) \ >> FSP_FLAGS_POS_TEMPORARY) -/** Return the contents of the ENCRYPTION field */ -#define FSP_FLAGS_GET_ENCRYPTION(flags) \ - ((flags & FSP_FLAGS_MASK_ENCRYPTION) \ - >> FSP_FLAGS_POS_ENCRYPTION) /** Return the contents of the UNUSED bits */ #define FSP_FLAGS_GET_UNUSED(flags) \ (flags >> FSP_FLAGS_POS_UNUSED) diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index c10644be832..cf4702cb366 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -42,7 +42,6 @@ struct fts_string_t; // JAN: TODO missing features: #undef MYSQL_57_SELECT_COUNT_OPTIMIZATION #undef MYSQL_COMPRESSION -#undef MYSQL_ENCRYPTION #undef MYSQL_FT_INIT_EXT #undef MYSQL_INNODB_API_CB #undef MYSQL_INNODB_PARTITIONING diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index a9d98b08d85..f54c935027b 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -190,16 +190,6 @@ struct recv_dblwr_t { list pages; }; -/* Recovery encryption information */ -typedef struct recv_encryption { - ulint space_id; /*!< the page number */ - byte* key; /*!< encryption key */ - byte* iv; /*!< encryption iv */ -} recv_encryption_t; - -typedef std::vector > - encryption_list_t; - /** Recovery system data structure */ struct recv_sys_t{ ib_mutex_t mutex; /*!< mutex protecting the fields apply_log_recs, @@ -266,9 +256,6 @@ struct recv_sys_t{ addresses in the hash table */ recv_dblwr_t dblwr; - - encryption_list_t* /*!< Encryption information list */ - encryption_list; }; /** The recovery system */ diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index f65d5f8dc1b..474c6848b09 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -293,209 +293,6 @@ struct Compression { Type m_type; }; -/** Encryption key length */ -static const ulint ENCRYPTION_KEY_LEN = 32; - -/** Encryption magic bytes size */ -static const ulint ENCRYPTION_MAGIC_SIZE = 3; - -/** Encryption magic bytes for 5.7.11, it's for checking the encryption information -version. */ -static const char ENCRYPTION_KEY_MAGIC_V1[] = "lCA"; - -/** Encryption magic bytes for 5.7.12+, it's for checking the encryption information -version. */ -static const char ENCRYPTION_KEY_MAGIC_V2[] = "lCB"; - -/** Encryption master key prifix */ -static const char ENCRYPTION_MASTER_KEY_PRIFIX[] = "INNODBKey"; - -/** Encryption master key prifix size */ -static const ulint ENCRYPTION_MASTER_KEY_PRIFIX_LEN = 9; - -/** Encryption master key prifix size */ -static const ulint ENCRYPTION_MASTER_KEY_NAME_MAX_LEN = 100; - -/** UUID of server instance, it's needed for composing master key name */ -static const ulint ENCRYPTION_SERVER_UUID_LEN = 36; - -/** Encryption information total size for 5.7.11: magic number + master_key_id + -key + iv + checksum */ -static const ulint ENCRYPTION_INFO_SIZE_V1 = (ENCRYPTION_MAGIC_SIZE \ - + (ENCRYPTION_KEY_LEN * 2) \ - + 2 * sizeof(ulint)); - -/** Encryption information total size: magic number + master_key_id + -key + iv + server_uuid + checksum */ -static const ulint ENCRYPTION_INFO_SIZE_V2 = (ENCRYPTION_MAGIC_SIZE \ - + (ENCRYPTION_KEY_LEN * 2) \ - + ENCRYPTION_SERVER_UUID_LEN \ - + 2 * sizeof(ulint)); - -class IORequest; - -/** Encryption algorithm. */ -struct Encryption { - - /** Algorithm types supported */ - enum Type { - - /** No encryption */ - NONE = 0, - - /** Use AES */ - AES = 1, - }; - - /** Encryption information format version */ - enum Version { - - /** Version in 5.7.11 */ - ENCRYPTION_VERSION_1 = 0, - - /** Version in > 5.7.11 */ - ENCRYPTION_VERSION_2 = 1, - }; - - /** Default constructor */ - Encryption() : m_type(NONE) { }; - - /** Specific constructor - @param[in] type Algorithm type */ - explicit Encryption(Type type) - : - m_type(type) - { -#ifdef UNIV_DEBUG - switch (m_type) { - case NONE: - case AES: - - default: - ut_error; - } -#endif /* UNIV_DEBUG */ - } - - /** Copy constructor */ - Encryption(const Encryption& other) - : - m_type(other.m_type), - m_key(other.m_key), - m_klen(other.m_klen), - m_iv(other.m_iv) - { }; - - /** Check if page is encrypted page or not - @param[in] page page which need to check - @return true if it is a encrypted page */ - static bool is_encrypted_page(const byte* page) - MY_ATTRIBUTE((warn_unused_result)); - - /** Check the encryption option and set it - @param[in] option encryption option - @param[in/out] encryption The encryption type - @return DB_SUCCESS or DB_UNSUPPORTED */ - dberr_t set_algorithm(const char* option, Encryption* type) - MY_ATTRIBUTE((warn_unused_result)); - - /** Validate the algorithm string. - @param[in] algorithm Encryption algorithm to check - @return DB_SUCCESS or error code */ - static dberr_t validate(const char* algorithm) - MY_ATTRIBUTE((warn_unused_result)); - - /** Convert to a "string". - @param[in] type The encryption type - @return the string representation */ - static const char* to_string(Type type) - MY_ATTRIBUTE((warn_unused_result)); - - /** Check if the string is "empty" or "none". - @param[in] algorithm Encryption algorithm to check - @return true if no algorithm requested */ - static bool is_none(const char* algorithm) - MY_ATTRIBUTE((warn_unused_result)); - - /** Generate random encryption value for key and iv. - @param[in,out] value Encryption value */ - static void random_value(byte* value); - - /** Create new master key for key rotation. - @param[in,out] master_key master key */ - static void create_master_key(byte** master_key); - - /** Get master key by key id. - @param[in] master_key_id master key id - @param[in] srv_uuid uuid of server instance - @param[in,out] master_key master key */ - static void get_master_key(ulint master_key_id, - char* srv_uuid, - byte** master_key); - - /** Get current master key and key id. - @param[in,out] master_key_id master key id - @param[in,out] master_key master key - @param[in,out] version encryption information version */ - static void get_master_key(ulint* master_key_id, - byte** master_key, - Encryption::Version* version); - - /** Encrypt the page data contents. Page type can't be - FIL_PAGE_ENCRYPTED, FIL_PAGE_COMPRESSED_AND_ENCRYPTED, - FIL_PAGE_ENCRYPTED_RTREE. - @param[in] type IORequest - @param[in,out] src page data which need to encrypt - @param[in] src_len Size of the source in bytes - @param[in,out] dst destination area - @param[in,out] dst_len Size of the destination in bytes - @return buffer data, dst_len will have the length of the data */ - byte* encrypt( - const IORequest& type, - byte* src, - ulint src_len, - byte* dst, - ulint* dst_len) - MY_ATTRIBUTE((warn_unused_result)); - - /** Decrypt the page data contents. Page type must be - FIL_PAGE_ENCRYPTED, FIL_PAGE_COMPRESSED_AND_ENCRYPTED, - FIL_PAGE_ENCRYPTED_RTREE, if not then the source contents are - left unchanged and DB_SUCCESS is returned. - @param[in] type IORequest - @param[in,out] src Data read from disk, decrypt - data will be copied to this page - @param[in] src_len source data length - @param[in,out] dst Scratch area to use for decrypt - @param[in] dst_len Size of the scratch area in bytes - @return DB_SUCCESS or error code */ - dberr_t decrypt( - const IORequest& type, - byte* src, - ulint src_len, - byte* dst, - ulint dst_len) - MY_ATTRIBUTE((warn_unused_result)); - - /** Encrypt type */ - Type m_type; - - /** Encrypt key */ - byte* m_key; - - /** Encrypt key length*/ - ulint m_klen; - - /** Encrypt initial vector */ - byte* m_iv; - - /** Current master key id */ - static ulint master_key_id; - - /** Current uuid of server instance */ - static char uuid[ENCRYPTION_SERVER_UUID_LEN + 1]; -}; - /** Types for AIO operations @{ */ /** No transformations during read/write, write as is. */ @@ -744,54 +541,6 @@ public: m_type |= NO_COMPRESSION; } - /** Set encryption algorithm - @param[in] type The encryption algorithm to use */ - void encryption_algorithm(Encryption::Type type) - { - if (type == Encryption::NONE) { - return; - } - - m_encryption.m_type = type; - } - - /** Set encryption key and iv - @param[in] key The encryption key to use - @param[in] key_len length of the encryption key - @param[in] iv The encryption iv to use */ - void encryption_key(byte* key, - ulint key_len, - byte* iv) - { - m_encryption.m_key = key; - m_encryption.m_klen = key_len; - m_encryption.m_iv = iv; - } - - /** Get the encryption algorithm. - @return the encryption algorithm */ - Encryption encryption_algorithm() const - MY_ATTRIBUTE((warn_unused_result)) - { - return(m_encryption); - } - - /** @return true if the page should be encrypted. */ - bool is_encrypted() const - MY_ATTRIBUTE((warn_unused_result)) - { - return(m_encryption.m_type != Encryption::NONE); - } - - /** Clear all encryption related flags */ - void clear_encrypted() - { - m_encryption.m_key = NULL; - m_encryption.m_klen = 0; - m_encryption.m_iv = NULL; - m_encryption.m_type = Encryption::NONE; - } - /** Note that the IO is for double write recovery. */ void dblwr_recover() { @@ -832,9 +581,6 @@ private: /** Compression algorithm */ Compression m_compression; - - /** Encryption algorithm */ - Encryption m_encryption; }; /* @} */ diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index 7fddada10f8..7157b07e9d0 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -136,7 +136,6 @@ extern mysql_pfs_key_t index_online_log_key; extern mysql_pfs_key_t dict_table_stats_key; extern mysql_pfs_key_t trx_sys_rw_lock_key; extern mysql_pfs_key_t hash_table_locks_key; -extern mysql_pfs_key_t master_key_id_mutex_key; #endif /* UNIV_PFS_RWLOCK */ /** Prints info of the sync system. diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index bd49e034384..68b6a44dc25 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -384,7 +384,6 @@ enum latch_id_t { LATCH_ID_HASH_TABLE_RW_LOCK, LATCH_ID_BUF_CHUNK_MAP_LATCH, LATCH_ID_SYNC_DEBUG_MUTEX, - LATCH_ID_MASTER_KEY_ID_MUTEX, LATCH_ID_SCRUB_STAT_MUTEX, LATCH_ID_DEFRAGMENT_MUTEX, LATCH_ID_BTR_DEFRAGMENT_MUTEX, diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 1ecebe098bd..e2f5265261b 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -224,42 +224,6 @@ fil_name_process( case FIL_LOAD_OK: ut_ad(space != NULL); -#ifdef MYSQL_ENCRYPTION - /* For encrypted tablespace, set key and iv. */ - if (FSP_FLAGS_GET_ENCRYPTION(space->flags) - && recv_sys->encryption_list != NULL) { - dberr_t err; - encryption_list_t::iterator it; - - for (it = recv_sys->encryption_list->begin(); - it != recv_sys->encryption_list->end(); - it++) { - if (it->space_id == space->id) { - err = fil_set_encryption( - space->id, - Encryption::AES, - it->key, - it->iv); - if (err != DB_SUCCESS) { - ib::error() - << "Can't set" - " encryption" - " information" - " for" - " tablespace" - << space->name - << "!"; - } - ut_free(it->key); - ut_free(it->iv); - it->key = NULL; - it->iv = NULL; - it->space_id = 0; - } - } - } -#endif /* MYSQL_ENCRYPTION */ - if (f.space == NULL || f.space == space) { f.name = fname.name; f.space = space; @@ -682,7 +646,6 @@ recv_sys_init( /* Call the constructor for recv_sys_t::dblwr member */ new (&recv_sys->dblwr) recv_dblwr_t(); - recv_sys->encryption_list = NULL; mutex_exit(&(recv_sys->mutex)); } @@ -732,28 +695,6 @@ recv_sys_debug_free(void) os_event_set(recv_sys->flush_start); } - if (recv_sys->encryption_list != NULL) { - encryption_list_t::iterator it; - - for (it = recv_sys->encryption_list->begin(); - it != recv_sys->encryption_list->end(); - it++) { - if (it->key != NULL) { - ut_free(it->key); - it->key = NULL; - } - if (it->iv != NULL) { - ut_free(it->iv); - it->iv = NULL; - } - } - - recv_sys->encryption_list->swap(*recv_sys->encryption_list); - - UT_DELETE(recv_sys->encryption_list); - recv_sys->encryption_list = NULL; - } - mutex_exit(&(recv_sys->mutex)); } @@ -1101,116 +1042,6 @@ log_block_checksum_is_ok( == log_block_calc_checksum(block)); } -#ifdef MYSQL_ENCRYPTION - -/** Parse or process a write encryption info record. -@param[in] ptr redo log record -@param[in] end end of the redo log buffer -@param[in] space_id the tablespace ID -@return log record end, NULL if not a complete record */ -static -byte* -fil_write_encryption_parse( - byte* ptr, - const byte* end, - ulint space_id) -{ - fil_space_t* space; - ulint offset; - ulint len; - byte* key = NULL; - byte* iv = NULL; - bool is_new = false; - - space = fil_space_get(space_id); - if (space == NULL) { - encryption_list_t::iterator it; - - if (recv_sys->encryption_list == NULL) { - recv_sys->encryption_list = - UT_NEW_NOKEY(encryption_list_t()); - } - - for (it = recv_sys->encryption_list->begin(); - it != recv_sys->encryption_list->end(); - it++) { - if (it->space_id == space_id) { - key = it->key; - iv = it->iv; - } - } - - if (key == NULL) { - key = static_cast(ut_malloc_nokey( - ENCRYPTION_KEY_LEN)); - iv = static_cast(ut_malloc_nokey( - ENCRYPTION_KEY_LEN)); - is_new = true; - } - } else { - key = space->encryption_key; - iv = space->encryption_iv; - } - - offset = mach_read_from_2(ptr); - ptr += 2; - len = mach_read_from_2(ptr); - - ptr += 2; - if (end < ptr + len) { - return(NULL); - } - - if (offset >= UNIV_PAGE_SIZE - || len + offset > UNIV_PAGE_SIZE - || (len != ENCRYPTION_INFO_SIZE_V1 - && len != ENCRYPTION_INFO_SIZE_V2)) { - recv_sys->found_corrupt_log = TRUE; - return(NULL); - } - -#ifdef UNIV_ENCRYPT_DEBUG - if (space) { - fprintf(stderr, "Got %lu from redo log:", space->id); - } -#endif - - if (!fsp_header_decode_encryption_info(key, - iv, - ptr)) { - recv_sys->found_corrupt_log = TRUE; - ib::warn() << "Encryption information" - << " in the redo log of space " - << space_id << " is invalid"; - } - - ut_ad(len == ENCRYPTION_INFO_SIZE_V1 - || len == ENCRYPTION_INFO_SIZE_V2); - - ptr += len; - - if (space == NULL) { - if (is_new) { - recv_encryption_t info; - - /* Add key and iv to list */ - info.space_id = space_id; - info.key = key; - info.iv = iv; - - recv_sys->encryption_list->push_back(info); - } - } else { - ut_ad(FSP_FLAGS_GET_ENCRYPTION(space->flags)); - - space->encryption_type = Encryption::AES; - space->encryption_klen = ENCRYPTION_KEY_LEN; - } - - return(ptr); -} -#endif /* MYSQL_ENCRYPTION */ - /** Try to parse a single log record body and also applies it if specified. @param[in] type redo log entry type @@ -1257,20 +1088,6 @@ recv_parse_or_apply_log_rec_body( return(ptr + 8); case MLOG_TRUNCATE: return(truncate_t::parse_redo_entry(ptr, end_ptr, space_id)); - case MLOG_WRITE_STRING: - /* For encrypted tablespace, we need to get the - encryption key information before the page 0 is recovered. - Otherwise, redo will not find the key to decrypt - the data pages. */ -#ifdef MYSQL_ENCRYPTION - if (page_no == 0 && !is_system_tablespace(space_id) - && !apply) { - return(fil_write_encryption_parse(ptr, - end_ptr, - space_id)); - } -#endif - break; default: break; diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 58cc1ff8d3e..e228a89b946 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -783,26 +783,6 @@ os_file_handle_error_no_exit( const char* operation, bool silent); -/** Decompress after a read and punch a hole in the file if it was a write -@param[in] type IO context -@param[in] fh Open file handle -@param[in,out] buf Buffer to transform -@param[in,out] scratch Scratch area for read decompression -@param[in] src_len Length of the buffer before compression -@param[in] len Compressed buffer length for write and size - of buf len for read -@return DB_SUCCESS or error code */ -static -dberr_t -os_file_io_complete( - const IORequest&type, - os_file_t fh, - byte* buf, - byte* scratch, - ulint src_len, - ulint offset, - ulint len); - /** Does simulated AIO. This function should be called by an i/o-handler thread. @@ -938,33 +918,7 @@ public: @return DB_SUCCESS or error code. */ static dberr_t post_io_processing(Slot* slot); - /** Decompress after a read and punch a hole in the file if - it was a write */ - static dberr_t io_complete(const Slot* slot) - { - ut_a(slot->offset > 0); - ut_a(slot->type.is_read() || !slot->skip_punch_hole); - - return(os_file_io_complete( - slot->type, slot->file, slot->buf, - slot->compressed_page, slot->original_len, - static_cast(slot->offset), - slot->len)); - } - private: - /** Check whether the page was encrypted. - @param[in] slot The slot that contains the IO request - @return true if it was an encyrpted page */ - static bool is_encrypted_page(const Slot* slot) - { -#ifdef MYSQL_ENCRYPTION - return(Encryption::is_encrypted_page(slot->buf)); -#else - return (false); -#endif - } - /** Check whether the page was compressed. @param[in] slot The slot that contains the IO request @return true if it was a compressed page */ @@ -1146,29 +1100,12 @@ AIOHandler::check_read(Slot* slot, ulint n_bytes) #else slot->n_bytes = static_cast(n_bytes); #endif /* _WIN32 */ - - err = io_complete(slot); - ut_a(err == DB_SUCCESS); - } else { /* Read the next block in */ ut_ad(compressed_page_size(slot) >= n_bytes); err = DB_FAIL; } - } else if (is_encrypted_page(slot)) { - ut_a(slot->offset > 0); - - slot->len = slot->original_len; -#ifdef _WIN32 - slot->n_bytes = static_cast(n_bytes); -#else - slot->n_bytes = static_cast(n_bytes); -#endif /* _WIN32 */ - - err = io_complete(slot); - ut_a(err == DB_SUCCESS); - } else { err = DB_FAIL; } @@ -1202,9 +1139,7 @@ AIOHandler::post_io_processing(Slot* slot) && slot->len == static_cast(slot->n_bytes))) { #ifdef MYSQL_COMPRESSION - if (!slot->type.is_log() - && (is_compressed_page(slot) - || is_encrypted_page(slot))) { + if (!slot->type.is_log() && is_compressed_page(slot)) { ut_a(slot->offset > 0); @@ -1652,87 +1587,6 @@ os_file_read_string( } } -/** Decompress after a read and punch a hole in the file if it was a write -@param[in] type IO context -@param[in] fh Open file handle -@param[in,out] buf Buffer to transform -@param[in,out] scratch Scratch area for read decompression -@param[in] src_len Length of the buffer before compression -@param[in] len Used buffer length for write and output - buf len for read -@return DB_SUCCESS or error code */ -static -dberr_t -os_file_io_complete( - const IORequest&type, - os_file_t fh, - byte* buf, - byte* scratch, - ulint src_len, - ulint offset, - ulint len) -{ -#ifdef MYSQL_ENCRYPTION - /* We never compress/decompress the first page */ - ut_a(offset > 0); - ut_ad(type.validate()); - - if (!type.is_compression_enabled()) { - - return(DB_SUCCESS); - - } else if (type.is_read()) { - dberr_t ret = DB_SUCCESS; - Encryption encryption(type.encryption_algorithm()); - - ut_ad(!type.is_log()); - - ret = encryption.decrypt(type, buf, src_len, scratch, len); - if (ret == DB_SUCCESS) { - return(os_file_decompress_page( - type.is_dblwr_recover(), - buf, scratch, len)); - } else { - return(ret); - } - - } else if (type.punch_hole()) { - - ut_ad(len <= src_len); - ut_ad(!type.is_log()); - ut_ad(type.is_write()); - ut_ad(type.is_compressed()); - - /* Nothing to do. */ - if (len == src_len) { - return(DB_SUCCESS); - } - -#ifdef UNIV_DEBUG - const ulint block_size = type.block_size(); -#endif /* UNIV_DEBUG */ - - /* We don't support multiple page sizes in the server - at the moment. */ - ut_ad(src_len == srv_page_size); - - /* Must be a multiple of the compression unit size. */ - ut_ad((len % block_size) == 0); - ut_ad((offset % block_size) == 0); - - ut_ad(len + block_size <= src_len); - - offset += len; - - return(os_file_punch_hole(fh, offset, src_len - len)); - } - - ut_ad(!type.is_log()); -#endif /* MYSQL_ENCRYPTION */ - - return(DB_SUCCESS); -} - /** This function returns a new path name after replacing the basename in an old path with a new basename. The old_path is a full path name including the extension. The tablename is in the normal @@ -2109,51 +1963,6 @@ os_file_compress_page( } #endif /* MYSQL_COMPRESSION */ -#ifdef MYSQL_ENCRYPTION -/** Encrypt a page content when write it to disk. -@param[in] type IO flags -@param[out] buf buffer to read or write -@param[in,out] n number of bytes to read/write, starting from - offset -@return pointer to the encrypted page */ -static -Block* -os_file_encrypt_page( - const IORequest& type, - void*& buf, - ulint* n) -{ - - byte* encrypted_page; - ulint encrypted_len = *n; - byte* buf_ptr; - Encryption encryption(type.encryption_algorithm()); - - ut_ad(!type.is_log()); - ut_ad(type.is_write()); - ut_ad(type.is_encrypted()); - - Block* block = os_alloc_block(); - - encrypted_page = static_cast( - ut_align(block->m_ptr, UNIV_SECTOR_SIZE)); - - buf_ptr = encryption.encrypt(type, - reinterpret_cast(buf), *n, - encrypted_page, &encrypted_len); - - bool encrypted = buf_ptr != buf; - - if (encrypted) { - - buf = buf_ptr; - *n = encrypted_len; - } - - return(block); -} -#endif /* MYSQL_ENCRYPTION */ - #ifndef _WIN32 /** Do the read/write @@ -5501,23 +5310,6 @@ os_file_io( } #endif /* MYSQL_COMPRESSION */ -#ifdef MYSQL_ENCRYPTION - /* We do encryption after compression, since if we do encryption - before compression, the encrypted data will cause compression fail - or low compression rate. */ - if (type.is_encrypted() && type.is_write()) { - /* We don't encrypt the first page of any file. */ - Block* compressed_block = block; - ut_ad(offset > 0); - - block = os_file_encrypt_page(type, buf, &n); - - if (compressed_block != NULL) { - os_free_block(compressed_block); - } - } -#endif /* MYSQL_ENCRYPTION */ - SyncFileIO sync_file_io(file, buf, n, offset); for (ulint i = 0; i < NUM_RETRIES_ON_PARTIAL_IO; ++i) { @@ -5532,20 +5324,7 @@ os_file_io( } else if ((ulint) n_bytes + bytes_returned == n) { bytes_returned += n_bytes; - - if (offset > 0 - && (type.is_compressed() || type.is_read())) { - - *err = os_file_io_complete( - type, file, - reinterpret_cast(buf), - compressed_page, original_n, - static_cast(offset), n); - - } else { - - *err = DB_SUCCESS; - } + *err = DB_SUCCESS; #ifdef MYSQL_COMPRESSION if (block != NULL) { os_free_block(block); @@ -7008,45 +6787,6 @@ AIO::reserve_slot( } #endif /* MYSQL_COMPRESSION */ -#ifdef MYSQL_ENCRYPTION - /* We do encryption after compression, since if we do encryption - before compression, the encrypted data will cause compression fail - or low compression rate. */ - if (srv_use_native_aio - && offset > 0 - && type.is_write() - && type.is_encrypted()) { - ulint encrypted_len = slot->len; - Block* encrypted_block; - - ut_ad(!type.is_log()); - - release(); - - void* src_buf = slot->buf; - encrypted_block = os_file_encrypt_page( - type, - src_buf, - &encrypted_len); - - if (slot->buf_block != NULL) { - os_free_block(slot->buf_block); - } - - slot->buf_block = encrypted_block; - slot->buf = static_cast(src_buf); - slot->ptr = slot->buf; - -#ifdef _WIN32 - slot->len = static_cast(encrypted_len); -#else - slot->len = static_cast(encrypted_len); -#endif /* _WIN32 */ - - acquire(); - } -#endif /* MYSQL_ENCRYPTION */ - #ifdef WIN_ASYNC_IO { OVERLAPPED* control; @@ -7713,13 +7453,6 @@ public: } } - /** Do the decompression of the pages read in */ - void io_complete() - { - // Note: For non-compressed tables. Not required - // for correctness. - } - /** Mark the i/os done in slots */ void done() { @@ -8064,8 +7797,6 @@ os_aio_simulated_handler( srv_set_io_thread_op_info(global_segment, "file i/o done"); - handler.io_complete(); - array->acquire(); handler.done(); @@ -8689,634 +8420,6 @@ os_file_decompress_page( } #endif /* MYSQL_COMPRESSION */ -#ifdef MYSQL_ENCRYPTION - -/** -@param[in] type The encryption type -@return the string representation */ -const char* -Encryption::to_string(Type type) -{ - switch(type) { - case NONE: - return("N"); - case AES: - return("Y"); - } - - ut_ad(0); - - return(""); -} - -/** Generate random encryption value for key and iv. -@param[in,out] value Encryption value */ -void Encryption::random_value(byte* value) -{ - ut_ad(value != NULL); - - my_rand_buffer(value, ENCRYPTION_KEY_LEN); -} - -/** Create new master key for key rotation. -@param[in,out] master_key master key */ -void -Encryption::create_master_key(byte** master_key) -{ -#ifndef UNIV_INNOCHECKSUM - char* key_type = NULL; - size_t key_len; - char key_name[ENCRYPTION_MASTER_KEY_NAME_MAX_LEN]; - int ret; - - /* If uuid does not match with current server uuid, - set uuid as current server uuid. */ - if (strcmp(uuid, server_uuid) != 0) { - memcpy(uuid, server_uuid, ENCRYPTION_SERVER_UUID_LEN); - } - memset(key_name, 0, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN); - - /* Generate new master key */ - ut_snprintf(key_name, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN, - "%s-%s-%lu", ENCRYPTION_MASTER_KEY_PRIFIX, - uuid, master_key_id + 1); - - /* We call key ring API to generate master key here. */ - ret = my_key_generate(key_name, "AES", - NULL, ENCRYPTION_KEY_LEN); - - /* We call key ring API to get master key here. */ - ret = my_key_fetch(key_name, &key_type, NULL, - reinterpret_cast(master_key), - &key_len); - - if (ret || *master_key == NULL) { - ib::error() << "Encryption can't find master key, please check" - " the keyring plugin is loaded."; - *master_key = NULL; - } else { - master_key_id++; - } - - if (key_type) { - my_free(key_type); - } -#endif -} - -/** Get master key by key id. -@param[in] master_key_id master key id -@param[in] srv_uuid uuid of server instance -@param[in,out] master_key master key */ -void -Encryption::get_master_key(ulint master_key_id, - char* srv_uuid, - byte** master_key) -{ -#ifndef UNIV_INNOCHECKSUM - char* key_type = NULL; - size_t key_len; - char key_name[ENCRYPTION_MASTER_KEY_NAME_MAX_LEN]; - int ret; - - memset(key_name, 0, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN); - - if (srv_uuid != NULL) { - ut_snprintf(key_name, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN, - "%s-%s-%lu", ENCRYPTION_MASTER_KEY_PRIFIX, - srv_uuid, master_key_id); - } else { - /* For compitable with 5.7.11, we need to get master key with - server id. */ - memset(key_name, 0, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN); - ut_snprintf(key_name, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN, - "%s-%lu-%lu", ENCRYPTION_MASTER_KEY_PRIFIX, - server_id, master_key_id); - } - - /* We call key ring API to get master key here. */ - ret = my_key_fetch(key_name, &key_type, NULL, - reinterpret_cast(master_key), &key_len); - - if (key_type) { - my_free(key_type); - } - - if (ret) { - *master_key = NULL; - ib::error() << "Encryption can't find master key, please check" - " the keyring plugin is loaded."; - } - -#ifdef UNIV_ENCRYPT_DEBUG - if (!ret && *master_key) { - fprintf(stderr, "Fetched master key:%lu ", master_key_id); - ut_print_buf(stderr, *master_key, key_len); - fprintf(stderr, "\n"); - } -#endif /* DEBUG_TDE */ - -#endif -} - -/** Current master key id */ -ulint Encryption::master_key_id = 0; - -/** Current uuid of server instance */ -char Encryption::uuid[ENCRYPTION_SERVER_UUID_LEN + 1] = {0}; - -/** Get current master key and master key id -@param[in,out] master_key_id master key id -@param[in,out] master_key master key -@param[in,out] version encryption information version */ -void -Encryption::get_master_key(ulint* master_key_id, - byte** master_key, - Encryption::Version* version) -{ -#ifndef UNIV_INNOCHECKSUM - char* key_type = NULL; - size_t key_len; - char key_name[ENCRYPTION_MASTER_KEY_NAME_MAX_LEN]; - int ret; - - memset(key_name, 0, ENCRYPTION_KEY_LEN); - *version = Encryption::ENCRYPTION_VERSION_2; - - if (Encryption::master_key_id == 0) { - /* If m_master_key is 0, means there's no encrypted - tablespace, we need to generate the first master key, - and store it to key ring. */ - memset(uuid, 0, ENCRYPTION_SERVER_UUID_LEN + 1); - memcpy(uuid, server_uuid, ENCRYPTION_SERVER_UUID_LEN); - - /* Prepare the server uuid. */ - ut_snprintf(key_name, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN, - "%s-%s-1", ENCRYPTION_MASTER_KEY_PRIFIX, - uuid); - - /* We call key ring API to generate master key here. */ - ret = my_key_generate(key_name, "AES", - NULL, ENCRYPTION_KEY_LEN); - - /* We call key ring API to get master key here. */ - ret = my_key_fetch(key_name, &key_type, NULL, - reinterpret_cast(master_key), - &key_len); - - if (!ret && *master_key != NULL) { - Encryption::master_key_id++; - *master_key_id = Encryption::master_key_id; - } -#ifdef UNIV_ENCRYPT_DEBUG - if (!ret && *master_key) { - fprintf(stderr, "Generated new master key:"); - ut_print_buf(stderr, *master_key, key_len); - fprintf(stderr, "\n"); - } -#endif - } else { - *master_key_id = Encryption::master_key_id; - - ut_snprintf(key_name, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN, - "%s-%s-%lu", ENCRYPTION_MASTER_KEY_PRIFIX, - uuid, *master_key_id); - - /* We call key ring API to get master key here. */ - ret = my_key_fetch(key_name, &key_type, NULL, - reinterpret_cast(master_key), - &key_len); - - /* For compitable with 5.7.11, we need to try to get master key with - server id when get master key with server uuid failure. */ - if (ret || *master_key == NULL) { - if (key_type) { - my_free(key_type); - } - - memset(key_name, 0, - ENCRYPTION_MASTER_KEY_NAME_MAX_LEN); - ut_snprintf(key_name, ENCRYPTION_MASTER_KEY_NAME_MAX_LEN, - "%s-%lu-%lu", ENCRYPTION_MASTER_KEY_PRIFIX, - server_id, *master_key_id); - - ret = my_key_fetch(key_name, &key_type, NULL, - reinterpret_cast(master_key), - &key_len); - *version = Encryption::ENCRYPTION_VERSION_1; - } -#ifdef UNIV_ENCRYPT_DEBUG - if (!ret && *master_key) { - fprintf(stderr, "Fetched master key:%lu ", - *master_key_id); - ut_print_buf(stderr, *master_key, key_len); - fprintf(stderr, "\n"); - } -#endif - } - - if (ret) { - *master_key = NULL; - ib::error() << "Encryption can't find master key, please check" - " the keyring plugin is loaded."; - } - - if (key_type) { - my_free(key_type); - } -#endif -} - -/** Check if page is encrypted page or not -@param[in] page page which need to check -@return true if it is a encrypted page */ -bool -Encryption::is_encrypted_page(const byte* page) -{ - ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE); - - return(page_type == FIL_PAGE_ENCRYPTED - || page_type == FIL_PAGE_COMPRESSED_AND_ENCRYPTED - || page_type == FIL_PAGE_ENCRYPTED_RTREE); -} - -/** Encrypt the page data contents. Page type can't be -FIL_PAGE_ENCRYPTED, FIL_PAGE_COMPRESSED_AND_ENCRYPTED, -FIL_PAGE_ENCRYPTED_RTREE. -@param[in] type IORequest -@param[in,out] src page data which need to encrypt -@param[in] src_len Size of the source in bytes -@param[in,out] dst destination area -@param[in,out] dst_len Size of the destination in bytes -@return buffer data, dst_len will have the length of the data */ -byte* -Encryption::encrypt( - const IORequest& type, - byte* src, - ulint src_len, - byte* dst, - ulint* dst_len) -{ - ulint len = 0; - ulint page_type = mach_read_from_2(src + FIL_PAGE_TYPE); - ulint data_len; - ulint main_len; - ulint remain_len; - byte remain_buf[MY_AES_BLOCK_SIZE * 2]; - -#ifdef UNIV_ENCRYPT_DEBUG - ulint space_id = - mach_read_from_4(src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - ulint page_no = mach_read_from_4(src + FIL_PAGE_OFFSET); - - fprintf(stderr, "Encrypting page:%lu.%lu len:%lu\n", - space_id, page_no, src_len); -#endif - - /* Shouldn't encrypte an already encrypted page. */ - ut_ad(page_type != FIL_PAGE_ENCRYPTED - && page_type != FIL_PAGE_COMPRESSED_AND_ENCRYPTED - && page_type != FIL_PAGE_ENCRYPTED_RTREE); - - ut_ad(m_type != Encryption::NONE); - - /* This is data size which need to encrypt. */ - data_len = src_len - FIL_PAGE_DATA; - main_len = (data_len / MY_AES_BLOCK_SIZE) * MY_AES_BLOCK_SIZE; - remain_len = data_len - main_len; - - /* Only encrypt the data + trailer, leave the header alone */ - - switch (m_type) { - case Encryption::NONE: - ut_error; - - case Encryption::AES: { - lint elen; - - ut_ad(m_klen == ENCRYPTION_KEY_LEN); - - elen = my_aes_encrypt( - src + FIL_PAGE_DATA, - static_cast(main_len), - dst + FIL_PAGE_DATA, - reinterpret_cast(m_key), - static_cast(m_klen), - my_aes_256_cbc, - reinterpret_cast(m_iv), - false); - - if (elen == MY_AES_BAD_DATA) { - ulint page_no =mach_read_from_4( - src + FIL_PAGE_OFFSET); - ulint space_id = mach_read_from_4( - src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - *dst_len = src_len; -#ifndef UNIV_INNOCHECKSUM - ib::warn() - << " Can't encrypt data of page," - << " page no:" << page_no - << " space id:" << space_id; -#else - fprintf(stderr, " Can't encrypt data of page," - " page no:" ULINTPF - " space id:" ULINTPF, - page_no, space_id); -#endif /* !UNIV_INNOCHECKSUM */ - return(src); - } - - len = static_cast(elen); - ut_ad(len == main_len); - - /* Copy remain bytes and page tailer. */ - memcpy(dst + FIL_PAGE_DATA + len, - src + FIL_PAGE_DATA + len, - src_len - FIL_PAGE_DATA - len); - - /* Encrypt the remain bytes. */ - if (remain_len != 0) { - remain_len = MY_AES_BLOCK_SIZE * 2; - - elen = my_aes_encrypt( - dst + FIL_PAGE_DATA + data_len - remain_len, - static_cast(remain_len), - remain_buf, - reinterpret_cast(m_key), - static_cast(m_klen), - my_aes_256_cbc, - reinterpret_cast(m_iv), - false); - - if (elen == MY_AES_BAD_DATA) { - ulint page_no =mach_read_from_4( - src + FIL_PAGE_OFFSET); - ulint space_id = mach_read_from_4( - src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); -#ifndef UNIV_INNOCHECKSUM - ib::warn() - << " Can't encrypt data of page," - << " page no:" << page_no - << " space id:" << space_id; -#else - fprintf(stderr, " Can't encrypt data of page," - " page no:" ULINTPF - " space id:" ULINTPF, - page_no, space_id); -#endif /* !UNIV_INNOCHECKSUM */ - *dst_len = src_len; - return(src); - } - - memcpy(dst + FIL_PAGE_DATA + data_len - remain_len, - remain_buf, remain_len); - } - - - break; - } - - default: - ut_error; - } - - /* Copy the header as is. */ - memmove(dst, src, FIL_PAGE_DATA); - ut_ad(memcmp(src, dst, FIL_PAGE_DATA) == 0); - - /* Add encryption control information. Required for decrypting. */ - if (page_type == FIL_PAGE_COMPRESSED) { - /* If the page is compressed, we don't need to save the - original type, since it is done in compression already. */ - mach_write_to_2(dst + FIL_PAGE_TYPE, - FIL_PAGE_COMPRESSED_AND_ENCRYPTED); - ut_ad(memcmp(src+FIL_PAGE_TYPE+2, - dst+FIL_PAGE_TYPE+2, - FIL_PAGE_DATA-FIL_PAGE_TYPE-2) == 0); - } else if (page_type == FIL_PAGE_RTREE) { - /* If the page is R-tree page, we need to save original - type. */ - mach_write_to_2(dst + FIL_PAGE_TYPE, FIL_PAGE_ENCRYPTED_RTREE); - } else{ - mach_write_to_2(dst + FIL_PAGE_TYPE, FIL_PAGE_ENCRYPTED); - mach_write_to_2(dst + FIL_PAGE_ORIGINAL_TYPE_V1, page_type); - } - -#ifdef UNIV_ENCRYPT_DEBUG -#ifndef UNIV_INNOCHECKSUM -#if 0 - byte* check_buf = static_cast(ut_malloc_nokey(src_len)); - byte* buf2 = static_cast(ut_malloc_nokey(src_len)); - - memcpy(check_buf, dst, src_len); - - dberr_t err = decrypt(type, check_buf, src_len, buf2, src_len); - if (err != DB_SUCCESS || memcmp(src + FIL_PAGE_DATA, - check_buf + FIL_PAGE_DATA, - src_len - FIL_PAGE_DATA) != 0) { - ut_print_buf(stderr, src, src_len); - ut_print_buf(stderr, check_buf, src_len); - ut_ad(0); - } - ut_free(buf2); - ut_free(check_buf); -#endif - fprintf(stderr, "Encrypted page:%lu.%lu\n", space_id, page_no); -#endif -#endif - *dst_len = src_len; - - - return(dst); -} - -/** Decrypt the page data contents. Page type must be FIL_PAGE_ENCRYPTED, -if not then the source contents are left unchanged and DB_SUCCESS is returned. -@param[in] type IORequest -@param[in,out] src Data read from disk, decrypted data will be - copied to this page -@param[in] src_len source data length -@param[in,out] dst Scratch area to use for decryption -@param[in] dst_len Size of the scratch area in bytes -@return DB_SUCCESS or error code */ -dberr_t -Encryption::decrypt( - const IORequest& type, - byte* src, - ulint src_len, - byte* dst, - ulint dst_len) -{ - ulint data_len; - ulint main_len; - ulint remain_len; - ulint original_type; - ulint page_type; - byte remain_buf[MY_AES_BLOCK_SIZE * 2]; - Block* block; - - /* Do nothing if it's not an encrypted table. */ - if (!is_encrypted_page(src)) { - return(DB_SUCCESS); - } - - /* For compressed page, we need to get the compressed size - for decryption */ - page_type = mach_read_from_2(src + FIL_PAGE_TYPE); - if (page_type == FIL_PAGE_COMPRESSED_AND_ENCRYPTED) { - src_len = static_cast( - mach_read_from_2(src + FIL_PAGE_COMPRESS_SIZE_V1)) - + FIL_PAGE_DATA; -#ifndef UNIV_INNOCHECKSUM - src_len = ut_calc_align(src_len, type.block_size()); -#endif - } -#ifdef UNIV_ENCRYPT_DEBUG - ulint space_id = - mach_read_from_4(src + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); - ulint page_no = mach_read_from_4(src + FIL_PAGE_OFFSET); - - fprintf(stderr, "Decrypting page:%lu.%lu len:%lu\n", - space_id, page_no, src_len); -#endif - - original_type = static_cast( - mach_read_from_2(src + FIL_PAGE_ORIGINAL_TYPE_V1)); - - byte* ptr = src + FIL_PAGE_DATA; - - /* The caller doesn't know what to expect */ - if (dst == NULL) { - - block = os_alloc_block(); -#ifdef UNIV_INNOCHECKSUM - dst = block; -#else - dst = block->m_ptr; -#endif /* UNIV_INNOCHECKSUM */ - - } else { - block = NULL; - } - - data_len = src_len - FIL_PAGE_DATA; - main_len = (data_len / MY_AES_BLOCK_SIZE) * MY_AES_BLOCK_SIZE; - remain_len = data_len - main_len; - - switch(m_type) { - case Encryption::AES: { - lint elen; - - /* First decrypt the last 2 blocks data of data, since - data is no block aligned. */ - if (remain_len != 0) { - ut_ad(m_klen == ENCRYPTION_KEY_LEN); - - remain_len = MY_AES_BLOCK_SIZE * 2; - - /* Copy the last 2 blocks. */ - memcpy(remain_buf, - ptr + data_len - remain_len, - remain_len); - - elen = my_aes_decrypt( - remain_buf, - static_cast(remain_len), - dst + data_len - remain_len, - reinterpret_cast(m_key), - static_cast(m_klen), - my_aes_256_cbc, - reinterpret_cast(m_iv), - false); - if (elen == MY_AES_BAD_DATA) { - if (block != NULL) { - os_free_block(block); - } - - return(DB_IO_DECRYPT_FAIL); - } - - /* Copy the other data bytes to temp area. */ - memcpy(dst, ptr, data_len - remain_len); - } else { - ut_ad(data_len == main_len); - - /* Copy the data bytes to temp area. */ - memcpy(dst, ptr, data_len); - } - - /* Then decrypt the main data */ - elen = my_aes_decrypt( - dst, - static_cast(main_len), - ptr, - reinterpret_cast(m_key), - static_cast(m_klen), - my_aes_256_cbc, - reinterpret_cast(m_iv), - false); - if (elen == MY_AES_BAD_DATA) { - - if (block != NULL) { - os_free_block(block); - } - - return(DB_IO_DECRYPT_FAIL); - } - - ut_ad(static_cast(elen) == main_len); - - /* Copy the remain bytes. */ - memcpy(ptr + main_len, dst + main_len, data_len - main_len); - - break; - } - - default: -#if !defined(UNIV_INNOCHECKSUM) - ib::error() - << "Encryption algorithm support missing: " - << Encryption::to_string(m_type); -#else - fprintf(stderr, "Encryption algorithm support missing: %s\n", - Encryption::to_string(m_type)); -#endif /* !UNIV_INNOCHECKSUM */ - - if (block != NULL) { - os_free_block(block); - } - - return(DB_UNSUPPORTED); - } - - /* Restore the original page type. If it's a compressed and - encrypted page, just reset it as compressed page type, since - we will do uncompress later. */ - - if (page_type == FIL_PAGE_ENCRYPTED) { - mach_write_to_2(src + FIL_PAGE_TYPE, original_type); - mach_write_to_2(src + FIL_PAGE_ORIGINAL_TYPE_V1, 0); - } else if (page_type == FIL_PAGE_ENCRYPTED_RTREE) { - mach_write_to_2(src + FIL_PAGE_TYPE, FIL_PAGE_RTREE); - } else { - ut_ad(page_type == FIL_PAGE_COMPRESSED_AND_ENCRYPTED); - mach_write_to_2(src + FIL_PAGE_TYPE, FIL_PAGE_COMPRESSED); - } - - if (block != NULL) { - os_free_block(block); - } - -#ifdef UNIV_ENCRYPT_DEBUG - fprintf(stderr, "Decrypted page:%lu.%lu\n", space_id, page_no); -#endif - - DBUG_EXECUTE_IF("ib_crash_during_decrypt_page", DBUG_SUICIDE();); - - return(DB_SUCCESS); -} -#endif /* MYSQL_ENCRYPTION */ - /** Normalizes a directory path for the current OS: On Windows, we convert '/' to '\', else we convert '\' to '/'. @param[in,out] str A null-terminated directory and file path */ diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 1054e4db1ef..88a4ce8b7d7 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -124,8 +124,7 @@ struct row_import { m_col_names(), m_n_indexes(), m_indexes(), - m_missing(true), - m_cfp_missing(true) { } + m_missing(true) {} ~row_import() UNIV_NOTHROW; @@ -220,9 +219,6 @@ struct row_import { bool m_missing; /*!< true if a .cfg file was found and was readable */ - - bool m_cfp_missing; /*!< true if a .cfp file was - found and was readable */ }; /** Use the page cursor to iterate over records in a block. */ @@ -2182,9 +2178,6 @@ row_import_cleanup( trx_commit_for_mysql(trx); - prebuilt->table->encryption_key = NULL; - prebuilt->table->encryption_iv = NULL; - row_mysql_unlock_data_dictionary(trx); trx_free_for_mysql(trx); @@ -3168,170 +3161,6 @@ row_import_read_cfg( return(err); } -#ifdef MYSQL_ENCRYPTION -/** Read the contents of the .cfp file. -@param[in] table table -@param[in] file file to read from -@param[in] thd session -@param[in] cfp contents of the .cfp file -@return DB_SUCCESS or error code. */ -static -dberr_t -row_import_read_encryption_data( - dict_table_t* table, - FILE* file, - THD* thd, - row_import& import) -{ - byte row[sizeof(ib_uint32_t)]; - ulint key_size; - byte transfer_key[ENCRYPTION_KEY_LEN]; - byte encryption_key[ENCRYPTION_KEY_LEN]; - byte encryption_iv[ENCRYPTION_KEY_LEN]; - lint elen; - - if (fread(&row, 1, sizeof(row), file) != sizeof(row)) { - ib_senderrf( - thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - errno, strerror(errno), - "while reading encrypton key size."); - - return(DB_IO_ERROR); - } - - key_size = mach_read_from_4(row); - if (key_size != ENCRYPTION_KEY_LEN) { - ib_senderrf( - thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - errno, strerror(errno), - "while parsing encryption key size."); - - return(DB_IO_ERROR); - } - - /* Read the transfer key. */ - if (fread(transfer_key, 1, ENCRYPTION_KEY_LEN, file) - != ENCRYPTION_KEY_LEN) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while reading tranfer key."); - - return(DB_IO_ERROR); - } - - /* Read the encrypted key. */ - if (fread(encryption_key, 1, ENCRYPTION_KEY_LEN, file) - != ENCRYPTION_KEY_LEN) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while reading encryption key."); - - return(DB_IO_ERROR); - } - - /* Read the encrypted iv. */ - if (fread(encryption_iv, 1, ENCRYPTION_KEY_LEN, file) - != ENCRYPTION_KEY_LEN) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while reading encryption iv."); - - return(DB_IO_ERROR); - } - - table->encryption_key = - static_cast(mem_heap_alloc(table->heap, - ENCRYPTION_KEY_LEN)); - - table->encryption_iv = - static_cast(mem_heap_alloc(table->heap, - ENCRYPTION_KEY_LEN)); - /* Decrypt tablespace key and iv. */ - elen = my_aes_decrypt( - encryption_key, - ENCRYPTION_KEY_LEN, - table->encryption_key, - transfer_key, - ENCRYPTION_KEY_LEN, - my_aes_256_ecb, NULL, false); - - if (elen == MY_AES_BAD_DATA) { - ib_senderrf( - thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - errno, strerror(errno), - "while decrypt encryption key."); - - return(DB_IO_ERROR); - } - - elen = my_aes_decrypt( - encryption_iv, - ENCRYPTION_KEY_LEN, - table->encryption_iv, - transfer_key, - ENCRYPTION_KEY_LEN, - my_aes_256_ecb, NULL, false); - - if (elen == MY_AES_BAD_DATA) { - ib_senderrf( - thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, - errno, strerror(errno), - "while decrypt encryption iv."); - - return(DB_IO_ERROR); - } - - return(DB_SUCCESS); -} - -/** Read the contents of the .cfp file. -@param[in] table table -@param[in] thd session -@param[in] cfp contents of the .cfp file -@return DB_SUCCESS or error code. */ -static -dberr_t -row_import_read_cfp( - dict_table_t* table, - THD* thd, - row_import& import) -{ - dberr_t err; - char name[OS_FILE_MAX_PATH]; - - /* Clear table encryption information. */ - table->encryption_key = NULL; - table->encryption_iv = NULL; - - srv_get_encryption_data_filename(table, name, sizeof(name)); - - FILE* file = fopen(name, "rb"); - - if (file == NULL) { - import.m_cfp_missing = true; - - /* If there's no cfp file, we assume it's not an - encrpyted table. return directly. */ - - import.m_cfp_missing = true; - - err = DB_SUCCESS; - } else { - - import.m_cfp_missing = false; - - err = row_import_read_encryption_data(table, file, - thd, import); - fclose(file); - } - - return(err); -} -#endif /* MYSQL_ENCRYPTION */ - /*****************************************************************//** Update the of a table's indexes from the values in the data dictionary. @@ -3699,42 +3528,7 @@ row_import_for_mysql( rw_lock_s_unlock_gen(dict_operation_lock, 0); } - /* Try to read encryption information. */ - if (err == DB_SUCCESS) { -#ifdef MYSQL_ENCRYPTION - err = row_import_read_cfp(table, trx->mysql_thd, cfg); - - /* If table is not set to encrypted, but the fsp flag - is not, then return error. */ - if (!dict_table_is_encrypted(table) - && space_flags != 0 - && FSP_FLAGS_GET_ENCRYPTION(space_flags)) { - - ib_errf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Table is not marked as encrypted, but" - " the tablespace is marked as encrypted"); - - err = DB_ERROR; - return(row_import_error(prebuilt, trx, err)); - } - - /* If table is set to encrypted, but can't find - cfp file, then return error. */ - if (cfg.m_cfp_missing== true - && ((space_flags != 0 - && FSP_FLAGS_GET_ENCRYPTION(space_flags)) - || dict_table_is_encrypted(table))) { - ib_errf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Table is in an encrypted tablespace, but" - " can't find the encryption meta-data file" - " in importing"); - err = DB_ERROR; - return(row_import_error(prebuilt, trx, err)); - } -#endif /* MYSQL_ENCRYPTION */ - } else { + if (err != DB_SUCCESS) { return(row_import_error(prebuilt, trx, err)); } @@ -3757,22 +3551,6 @@ row_import_for_mysql( DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure", err = DB_TOO_MANY_CONCURRENT_TRXS;); -#ifdef MYSQL_ENCRYPTION - if (err == DB_IO_NO_ENCRYPT_TABLESPACE) { - char table_name[MAX_FULL_NAME_LEN + 1]; - - innobase_format_name( - table_name, sizeof(table_name), - table->name.m_name); - - ib_errf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLE_SCHEMA_MISMATCH, - "Encryption attribute is no matched"); - - return(row_import_cleanup(prebuilt, trx, err)); - } -#endif /* MYSQL_ENCRYPTION */ - if (err != DB_SUCCESS) { char table_name[MAX_FULL_NAME_LEN + 1]; @@ -3828,12 +3606,6 @@ row_import_for_mysql( ulint fsp_flags = dict_tf_to_fsp_flags(table->flags, false); -#ifdef MYSQL_ENCRYPTION - if (table->encryption_key != NULL) { - fsp_flags |= FSP_FLAGS_MASK_ENCRYPTION; - } -#endif /* MYSQL_ENCRYPTION */ - err = fil_ibd_open( true, true, FIL_TYPE_IMPORT, table->space, fsp_flags, table->name.m_name, filepath, table); @@ -3853,17 +3625,6 @@ row_import_for_mysql( return(row_import_cleanup(prebuilt, trx, err)); } -#ifdef MYSQL_ENCRYPTION - /* For encrypted table, set encryption information. */ - if (dict_table_is_encrypted(table)) { - - err = fil_set_encryption(table->space, - Encryption::AES, - table->encryption_key, - table->encryption_iv); - } -#endif /* MYSQL_ENCRYPTION */ - row_mysql_unlock_data_dictionary(trx); ut_free(filepath); @@ -3961,37 +3722,6 @@ row_import_for_mysql( ib::info() << "Phase IV - Flush complete"; fil_space_set_imported(prebuilt->table->space); -#ifdef MYSQL_ENCRYPTION - if (dict_table_is_encrypted(table)) { - fil_space_t* space; - mtr_t mtr; - byte encrypt_info[ENCRYPTION_INFO_SIZE_V2]; - - mtr_start(&mtr); - - mtr.set_named_space(table->space); - space = mtr_x_lock_space(table->space, &mtr); - - memset(encrypt_info, 0, ENCRYPTION_INFO_SIZE_V2); - - if (!fsp_header_rotate_encryption(space, - encrypt_info, - &mtr)) { - mtr_commit(&mtr); - ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_FILE_NOT_FOUND, - filepath, err, ut_strerr(err)); - - ut_free(filepath); - row_mysql_unlock_data_dictionary(trx); - - return(row_import_cleanup(prebuilt, trx, err)); - } - - mtr_commit(&mtr); - } -#endif /* MYSQL_ENCRYPTION */ - /* The dictionary latches will be released in in row_import_cleanup() after the transaction commit, for both success and error. */ diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 269291bd517..0c3a4e6bdae 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -102,8 +102,6 @@ static ib_mutex_t row_drop_list_mutex; /** Flag: has row_mysql_drop_list been initialized? */ static ibool row_mysql_drop_list_inited = FALSE; -extern ib_mutex_t master_key_id_mutex; - /** Magic table names for invoking various monitor threads */ /* @{ */ static const char S_innodb_monitor[] = "innodb_monitor"; @@ -3275,33 +3273,6 @@ row_discard_tablespace( return(err); } - /* For encrypted table, before we discard the tablespace, - we need save the encryption information into table, otherwise, - this information will be lost in fil_discard_tablespace along - with fil_space_free(). */ - if (dict_table_is_encrypted(table)) { - ut_ad(table->encryption_key == NULL - && table->encryption_iv == NULL); - - table->encryption_key = - static_cast(mem_heap_alloc(table->heap, - ENCRYPTION_KEY_LEN)); - - table->encryption_iv = - static_cast(mem_heap_alloc(table->heap, - ENCRYPTION_KEY_LEN)); - - fil_space_t* space = fil_space_get(table->space); - ut_ad(FSP_FLAGS_GET_ENCRYPTION(space->flags)); - - memcpy(table->encryption_key, - space->encryption_key, - ENCRYPTION_KEY_LEN); - memcpy(table->encryption_iv, - space->encryption_iv, - ENCRYPTION_KEY_LEN); - } - /* Discard the physical file that is used for the tablespace. */ err = fil_discard_tablespace(table->space); @@ -3614,7 +3585,6 @@ This deletes the fil_space_t if found and the file on disk. @param[in] tablename Table name, same as the tablespace name @param[in] filepath File path of tablespace to delete @param[in] is_temp Is this a temporary table/tablespace -@param[in] is_encrypted Is this an encrypted table/tablespace @param[in] trx Transaction handle @return error code or DB_SUCCESS */ UNIV_INLINE @@ -3624,7 +3594,6 @@ row_drop_single_table_tablespace( const char* tablename, const char* filepath, bool is_temp, - bool is_encrypted, trx_t* trx) { dberr_t err = DB_SUCCESS; @@ -3632,7 +3601,7 @@ row_drop_single_table_tablespace( /* This might be a temporary single-table tablespace if the table is compressed and temporary. If so, don't spam the log when we delete one of these or if we can't find the tablespace. */ - bool print_msg = !is_temp && !is_encrypted; + bool print_msg = !is_temp; /* If the tablespace is not in the cache, just delete the file. */ if (!fil_space_for_table_exists_in_mem( @@ -4117,7 +4086,6 @@ row_drop_table_for_mysql( switch (err) { ulint space_id; bool is_temp; - bool is_encrypted; bool ibd_file_missing; bool is_discarded; bool shared_tablespace; @@ -4127,7 +4095,6 @@ row_drop_table_for_mysql( ibd_file_missing = table->ibd_file_missing; is_discarded = dict_table_is_discarded(table); is_temp = dict_table_is_temporary(table); - is_encrypted = dict_table_is_encrypted(table); shared_tablespace = DICT_TF_HAS_SHARED_SPACE(table->flags); /* If there is a temp path then the temp flag is set. @@ -4172,32 +4139,13 @@ row_drop_table_for_mysql( nor system or shared general tablespaces. */ if (is_discarded || ibd_file_missing || shared_tablespace || is_system_tablespace(space_id)) { - /* For encrypted table, if ibd file can not be decrypt, - we also set ibd_file_missing. We still need to try to - remove the ibd file for this. */ - if (is_discarded || !is_encrypted - || !ibd_file_missing) { - break; - } + break; } -#ifdef MYSQL_ENCRYPTION - if (is_encrypted) { - /* Require the mutex to block key rotation. */ - mutex_enter(&master_key_id_mutex); - } -#endif /* MYSQL_ENCRYPTION */ - /* We can now drop the single-table tablespace. */ err = row_drop_single_table_tablespace( space_id, tablename, filepath, - is_temp, is_encrypted, trx); - -#ifdef MYSQL_ENCRYPTION - if (is_encrypted) { - mutex_exit(&master_key_id_mutex); - } -#endif /* MYSQL_ENCRYPTION */ + is_temp, trx); break; case DB_OUT_OF_FILE_SPACE: diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index 08d119768a9..828b126309f 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -480,210 +480,6 @@ row_quiesce_write_cfg( return(err); } -#ifdef MYSQL_ENCRYPTION - -/** Write the transfer key to CFP file. -@param[in] table write the data for this table -@param[in] file file to write to -@param[in] thd session -@return DB_SUCCESS or error code. */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -row_quiesce_write_transfer_key( - const dict_table_t* table, - FILE* file, - THD* thd) -{ - byte key_size[sizeof(ib_uint32_t)]; - byte row[ENCRYPTION_KEY_LEN * 3]; - byte* ptr = row; - byte* transfer_key = ptr; - lint elen; - - ut_ad(table->encryption_key != NULL - && table->encryption_iv != NULL); - - /* Write the encryption key size. */ - mach_write_to_4(key_size, ENCRYPTION_KEY_LEN); - - if (fwrite(&key_size, 1, sizeof(key_size), file) - != sizeof(key_size)) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while writing key size."); - - return(DB_IO_ERROR); - } - - /* Generate and write the transfer key. */ - Encryption::random_value(transfer_key); - if (fwrite(transfer_key, 1, ENCRYPTION_KEY_LEN, file) - != ENCRYPTION_KEY_LEN) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while writing transfer key."); - - return(DB_IO_ERROR); - } - - ptr += ENCRYPTION_KEY_LEN; - - /* Encrypt tablespace key. */ - elen = my_aes_encrypt( - reinterpret_cast(table->encryption_key), - ENCRYPTION_KEY_LEN, - ptr, - reinterpret_cast(transfer_key), - ENCRYPTION_KEY_LEN, - my_aes_256_ecb, - NULL, false); - - if (elen == MY_AES_BAD_DATA) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while encrypt tablespace key."); - return(DB_ERROR); - } - - /* Write encrypted tablespace key */ - if (fwrite(ptr, 1, ENCRYPTION_KEY_LEN, file) - != ENCRYPTION_KEY_LEN) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while writing encrypted tablespace key."); - - return(DB_IO_ERROR); - } - ptr += ENCRYPTION_KEY_LEN; - - /* Encrypt tablespace iv. */ - elen = my_aes_encrypt( - reinterpret_cast(table->encryption_iv), - ENCRYPTION_KEY_LEN, - ptr, - reinterpret_cast(transfer_key), - ENCRYPTION_KEY_LEN, - my_aes_256_ecb, - NULL, false); - - if (elen == MY_AES_BAD_DATA) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while encrypt tablespace iv."); - return(DB_ERROR); - } - - /* Write encrypted tablespace iv */ - if (fwrite(ptr, 1, ENCRYPTION_KEY_LEN, file) - != ENCRYPTION_KEY_LEN) { - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), - "while writing encrypted tablespace iv."); - - return(DB_IO_ERROR); - } - - return(DB_SUCCESS); -} - -/** Write the encryption data after quiesce. -@param[in] table write the data for this table -@param[in] thd session -@return DB_SUCCESS or error code */ -static MY_ATTRIBUTE((nonnull, warn_unused_result)) -dberr_t -row_quiesce_write_cfp( - dict_table_t* table, - THD* thd) -{ - dberr_t err; - char name[OS_FILE_MAX_PATH]; - - /* If table is not encrypted, return. */ - if (!dict_table_is_encrypted(table)) { - return(DB_SUCCESS); - } - - /* Get the encryption key and iv from space */ - /* For encrypted table, before we discard the tablespace, - we need save the encryption information into table, otherwise, - this information will be lost in fil_discard_tablespace along - with fil_space_free(). */ - if (table->encryption_key == NULL) { - table->encryption_key = - static_cast(mem_heap_alloc(table->heap, - ENCRYPTION_KEY_LEN)); - - table->encryption_iv = - static_cast(mem_heap_alloc(table->heap, - ENCRYPTION_KEY_LEN)); - - fil_space_t* space = fil_space_get(table->space); - ut_ad(space != NULL && FSP_FLAGS_GET_ENCRYPTION(space->flags)); - - memcpy(table->encryption_key, - space->encryption_key, - ENCRYPTION_KEY_LEN); - memcpy(table->encryption_iv, - space->encryption_iv, - ENCRYPTION_KEY_LEN); - } - - srv_get_encryption_data_filename(table, name, sizeof(name)); - - ib::info() << "Writing table encryption data to '" << name << "'"; - - FILE* file = fopen(name, "w+b"); - - if (file == NULL) { - ib_errf(thd, IB_LOG_LEVEL_WARN, ER_CANT_CREATE_FILE, - name, errno, strerror(errno)); - - err = DB_IO_ERROR; - } else { - err = row_quiesce_write_transfer_key(table, file, thd); - - if (fflush(file) != 0) { - - char msg[BUFSIZ]; - - ut_snprintf(msg, sizeof(msg), "%s flush() failed", - name); - - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), msg); - - err = DB_IO_ERROR; - } - - if (fclose(file) != 0) { - char msg[BUFSIZ]; - - ut_snprintf(msg, sizeof(msg), "%s flose() failed", - name); - - ib_senderrf( - thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, - errno, strerror(errno), msg); - err = DB_IO_ERROR; - } - } - - /* Clean the encryption information */ - table->encryption_key = NULL; - table->encryption_iv = NULL; - - return(err); -} -#endif /* MYSQL_ENCRYPTION */ - /*********************************************************************//** Check whether a table has an FTS index defined on it. @return true if an FTS index exists on the table */ @@ -744,24 +540,9 @@ row_quiesce_table_start( } if (!trx_is_interrupted(trx)) { - extern ib_mutex_t master_key_id_mutex; - -#ifdef MYSQL_ENCRYPTION - if (dict_table_is_encrypted(table)) { - /* Require the mutex to block key rotation. */ - mutex_enter(&master_key_id_mutex); - } -#endif /* MYSQL_ENCRYPTION */ - buf_LRU_flush_or_remove_pages( table->space, BUF_REMOVE_FLUSH_WRITE, trx); -#ifdef MYSQL_ENCRYPTION - if (dict_table_is_encrypted(table)) { - mutex_exit(&master_key_id_mutex); - } -#endif /* MYSQL_ENCRYPTION */ - if (trx_is_interrupted(trx)) { ib::warn() << "Quiesce aborted!"; @@ -771,12 +552,6 @@ row_quiesce_table_start( ib::warn() << "There was an error writing to the" " meta data file"; -#ifdef MYSQL_ENCRYPTION - } else if (row_quiesce_write_cfp(table, trx->mysql_thd) - != DB_SUCCESS) { - ib::warn() << "There was an error writing to the" - " encryption info file"; -#endif /* MYSQL_ENCRYPTION */ } else { ib::info() << "Table " << table->name << " flushed to disk"; @@ -829,19 +604,6 @@ row_quiesce_table_complete( ib::info() << "Deleting the meta-data file '" << cfg_name << "'"; - if (dict_table_is_encrypted(table)) { - char cfp_name[OS_FILE_MAX_PATH]; - - srv_get_encryption_data_filename(table, - cfp_name, - sizeof(cfp_name)); - - os_file_delete_if_exists(innodb_data_file_key, cfp_name, NULL); - - ib::info() << "Deleting the meta-data file '" - << cfp_name << "'"; - } - if (trx_purge_state() != PURGE_STATE_DISABLED) { trx_purge_run(); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 56576c2f29e..fd00e95e494 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2289,17 +2289,6 @@ files_checked: dict_check_tablespaces_and_store_max_id(validate); } -#ifdef MYSQL_ENCRYPTION - /* Rotate the encryption key for recovery. It's because - server could crash in middle of key rotation. Some tablespace - didn't complete key rotation. Here, we will resume the - rotation. */ - if (!srv_read_only_mode - && srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { - fil_encryption_rotate(); - } -#endif /* MYSQL_ENCRYPTION */ - /* Fix-up truncate of table if server crashed while truncate was active. */ err = truncate_t::fixup_tables_in_non_system_tablespace(); @@ -2970,36 +2959,3 @@ srv_get_meta_data_filename( ut_free(path); } -/** Get the encryption-data filename from the table name for a -single-table tablespace. -@param[in] table table object -@param[out] filename filename -@param[in] max_len filename max length */ -void -srv_get_encryption_data_filename( - dict_table_t* table, - char* filename, - ulint max_len) -{ - ulint len; - char* path; - /* Make sure the data_dir_path is set. */ - dict_get_and_save_data_dir_path(table, false); - - if (DICT_TF_HAS_DATA_DIR(table->flags)) { - ut_a(table->data_dir_path); - - path = fil_make_filepath( - table->data_dir_path, table->name.m_name, CFP, true); - } else { - path = fil_make_filepath(NULL, table->name.m_name, CFP, false); - } - - ut_a(path); - len = ut_strlen(path); - ut_a(max_len >= len); - - strcpy(filename, path); - - ut_free(path); -} diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc index c9b37cbbb09..1d9e8933185 100644 --- a/storage/innobase/sync/sync0debug.cc +++ b/storage/innobase/sync/sync0debug.cc @@ -1544,8 +1544,6 @@ sync_latch_meta_init() LATCH_ADD(SYNC_DEBUG_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED); - LATCH_ADD(MASTER_KEY_ID_MUTEX, SYNC_NO_ORDER_CHECK, master_key_id_mutex_key); - /* JAN: TODO: Add PFS instrumentation */ LATCH_ADD(SCRUB_STAT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED); LATCH_ADD(DEFRAGMENT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED); diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index 9aba075caa6..099a56c5457 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -98,7 +98,6 @@ mysql_pfs_key_t sync_array_mutex_key; mysql_pfs_key_t thread_mutex_key; mysql_pfs_key_t zip_pad_mutex_key; mysql_pfs_key_t row_drop_list_mutex_key; -mysql_pfs_key_t master_key_id_mutex_key; #endif /* UNIV_PFS_MUTEX */ #ifdef UNIV_PFS_RWLOCK mysql_pfs_key_t btr_search_latch_key; diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 8dc6fb0bbe6..d296fb5afe2 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -759,10 +759,6 @@ ut_strerr( return("Punch hole not supported by the file system"); case DB_IO_NO_PUNCH_HOLE_TABLESPACE: return("Punch hole not supported by the tablespace"); - case DB_IO_NO_ENCRYPT_TABLESPACE: - return("Page encryption not supported by the tablespace"); - case DB_IO_DECRYPT_FAIL: - return("Page decryption failed after reading from disk"); case DB_IO_PARTIAL_FAILED: return("Partial IO failed"); case DB_FORCED_ABORT: From 1eabad5dbe1caa23b27dd954ba0d435c91516776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 16 Jan 2017 14:03:36 +0200 Subject: [PATCH 085/167] Remove MYSQL_COMPRESSION. The MariaDB 10.1 page_compression is incompatible with the Oracle implementation that was introduced in MySQL 5.7 later. Remove the Oracle implementation. Also remove the remaining traces of MYSQL_ENCRYPTION. This will also remove traces of PUNCH_HOLE until it is implemented better. The only effective call to os_file_punch_hole() was in fil_node_create_low() to test if the operation is supported for the file. In other words, it looks like page_compression is not working in MariaDB 10.2, because no code equivalent to the 10.1 os_file_trim() is enabled. --- storage/innobase/buf/buf0buf.cc | 53 +- storage/innobase/buf/buf0dblwr.cc | 14 +- storage/innobase/fil/fil0fil.cc | 212 +--- storage/innobase/fil/fil0pagecompress.cc | 26 +- storage/innobase/fsp/fsp0file.cc | 30 +- storage/innobase/fts/fts0fts.cc | 4 +- storage/innobase/handler/ha_innodb.cc | 316 +----- storage/innobase/handler/ha_innodb.h | 3 - storage/innobase/handler/handler0alter.cc | 36 +- storage/innobase/include/buf0buf.h | 1 - storage/innobase/include/buf0buf.ic | 3 - storage/innobase/include/db0err.h | 12 - storage/innobase/include/fil0fil.h | 56 +- storage/innobase/include/fil0fil.ic | 92 +- storage/innobase/include/ha_prototypes.h | 1 - storage/innobase/include/os0file.h | 305 +----- storage/innobase/include/os0file.ic | 2 +- storage/innobase/include/row0mysql.h | 3 - storage/innobase/include/srv0srv.h | 5 - storage/innobase/innodb.cmake | 19 +- storage/innobase/os/os0file.cc | 1217 +-------------------- storage/innobase/row/row0merge.cc | 5 - storage/innobase/row/row0mysql.cc | 38 - storage/innobase/row/row0trunc.cc | 6 - storage/innobase/srv/srv0srv.cc | 2 - storage/innobase/srv/srv0start.cc | 8 - storage/innobase/trx/trx0purge.cc | 6 - storage/innobase/ut/ut0ut.cc | 8 - 28 files changed, 107 insertions(+), 2376 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 2f4edfb5014..315c951a9fe 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -5943,7 +5943,6 @@ buf_page_io_complete( ulint read_page_no; ulint read_space_id; byte* frame = NULL; - bool compressed_page=false; ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL); @@ -5957,8 +5956,6 @@ buf_page_io_complete( ib::info() << "Page " << bpage->id - << " in tablespace " - << bpage->space << " encryption error key_version " << bpage->key_version; @@ -5974,12 +5971,9 @@ buf_page_io_complete( FALSE)) { buf_pool->n_pend_unzip--; - compressed_page = false; ib::info() << "Page " << bpage->id - << " in tablespace " - << bpage->space << " zip_decompress failure."; goto database_corrupted; @@ -6005,13 +5999,13 @@ buf_page_io_complete( } else if (read_space_id == 0 && read_page_no == 0) { /* This is likely an uninitialized page. */ - } else if ((bpage->id.space() != 0 + } else if ((bpage->id.space() != TRX_SYS_SPACE && bpage->id.space() != read_space_id) || bpage->id.page_no() != read_page_no) { /* We did not compare space_id to read_space_id - if bpage->space == 0, because the field on the - page may contain garbage in MySQL < 4.1.1, - which only supported bpage->space == 0. */ + in the system tablespace, because the field + was written as garbage before MySQL 4.1.1, + which did not support innodb_file_per_table. */ ib::error() << "Space id and page no stored in " "the page, read in are " @@ -6019,37 +6013,16 @@ buf_page_io_complete( << ", should be " << bpage->id; } -#ifdef MYSQL_COMPRESSION - compressed_page = Compression::is_compressed_page(frame); - - /* If the decompress failed then the most likely case is - that we are reading in a page for which this instance doesn't - support the compression algorithm. */ - if (compressed_page) { - - Compression::meta_t meta; - - Compression::deserialize_header(frame, &meta); - - ib::error() - << "Page " << bpage->id << " " - << "compressed with " - << Compression::to_string(meta) << " " - << "that is not supported by this instance"; - } -#endif /* MYSQL_COMPRESSION */ - /* From version 3.23.38 up we store the page checksum to the 4 first bytes of the page end lsn field */ - if (compressed_page - || buf_page_is_corrupted( + if (buf_page_is_corrupted( true, frame, bpage->size, fsp_is_checksum_disabled(bpage->id.space()))) { /* Not a real corruption if it was triggered by error injection */ DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", - if (bpage->space > TRX_SYS_SPACE + if (bpage->id.space() != TRX_SYS_SPACE && buf_mark_space_corrupt(bpage)) { ib::info() << "Simulated page corruption"; @@ -6076,7 +6049,7 @@ database_corrupted: /* Compressed and encrypted pages are basically gibberish avoid printing the contents. */ - if (corrupted && !compressed_page) { + if (corrupted) { ib::error() << "Database page corruption on disk" @@ -6124,11 +6097,11 @@ database_corrupted: } ib_push_warning((void *)NULL, DB_DECRYPTION_FAILED, - "Table in tablespace %lu encrypted." + "Table in tablespace %u encrypted." "However key management plugin or used key_id %u is not found or" " used encryption algorithm or method does not match." " Can't continue opening the table.", - (ulint)bpage->space, key_version); + bpage->id.space(), key_version); buf_page_print(frame, bpage->size, BUF_PAGE_PRINT_NO_CRASH); @@ -6152,9 +6125,6 @@ database_corrupted: /* If space is being truncated then avoid ibuf operation. During re-init we have already freed ibuf entries. */ if (uncompressed -#ifdef MYSQL_COMPRESSION - && !Compression::is_compressed_page(frame) -#endif /* MYSQL_COMPRESSION */ && !recv_no_ibuf_operations && !Tablespace::is_undo_tablespace(bpage->id.space()) && bpage->id.space() != SRV_TMP_SPACE_ID @@ -6164,11 +6134,11 @@ database_corrupted: if (bpage && bpage->encrypted) { fprintf(stderr, - "InnoDB: Warning: Table in tablespace %lu encrypted." + "InnoDB: Warning: Table in tablespace %u encrypted." "However key management plugin or used key_id %u is not found or" " used encryption algorithm or method does not match." " Can't continue opening the table.\n", - (ulint)bpage->space, bpage->key_version); + bpage->id.space(), bpage->key_version); } else { ibuf_merge_or_delete_for_page( (buf_block_t*) bpage, bpage->id, @@ -7604,7 +7574,6 @@ buf_page_decrypt_after_read( bpage->key_version = key_version; bpage->page_encrypted = page_compressed_encrypted; bpage->page_compressed = page_compressed; - bpage->space = bpage->id.space(); if (page_compressed) { /* the page we read is unencrypted */ diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 5f46576ad7e..f555875559d 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -380,8 +380,6 @@ buf_dblwr_init_or_load_pages( IORequest read_request(IORequest::READ); - read_request.disable_compression(); - err = os_file_read( read_request, file, read_buf, TRX_SYS_PAGE_NO * UNIV_PAGE_SIZE, @@ -496,11 +494,6 @@ buf_dblwr_init_or_load_pages( IORequest write_request(IORequest::WRITE); - /* Recovered data file pages are written out - as uncompressed. */ - - write_request.disable_compression(); - err = os_file_write( write_request, path, file, page, source_page_no * UNIV_PAGE_SIZE, @@ -704,20 +697,15 @@ buf_dblwr_process(void) } } - /* Recovered data file pages are written out - as uncompressed. */ - IORequest write_request(IORequest::WRITE); - write_request.disable_compression(); - /* Write the good page from the doublewrite buffer to the intended position. */ fil_io(write_request, true, page_id, page_size, 0, page_size.physical(), - const_cast(page), NULL, NULL); + const_cast(page), NULL, NULL); ib::info() << "Recovered page " diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a00b287dc3f..f8abe3c5f21 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -481,7 +481,6 @@ fil_space_is_flushed( @param[in] size file size in entire database blocks @param[in,out] space tablespace from fil_space_create() @param[in] is_raw whether this is a raw device or partition -@param[in] punch_hole true if supported for this node @param[in] atomic_write true if the file could use atomic write @param[in] max_pages maximum number of pages in file, ULINT_MAX means the file size is unlimited. @@ -494,7 +493,6 @@ fil_node_create_low( ulint size, fil_space_t* space, bool is_raw, - bool punch_hole, bool atomic_write, ulint max_pages = ULINT_MAX) { @@ -544,26 +542,6 @@ fil_node_create_low( node->block_size = stat_info.block_size; - /* In this debugging mode, we can overcome the limitation of some - OSes like Windows that support Punch Hole but have a hole size - effectively too large. By setting the block size to be half the - page size, we can bypass one of the checks that would normally - turn Page Compression off. This execution mode allows compression - to be tested even when full punch hole support is not available. */ - DBUG_EXECUTE_IF("ignore_punch_hole", - node->block_size = ut_min(stat_info.block_size, - static_cast(UNIV_PAGE_SIZE / 2)); - ); - - if (!IORequest::is_punch_hole_supported() - || !punch_hole - || node->block_size >= srv_page_size) { - - fil_no_punch_hole(node); - } else { - node->punch_hole = punch_hole; - } - node->atomic_write = atomic_write; UT_LIST_ADD_LAST(space->chain, node); @@ -595,8 +573,7 @@ fil_node_create( fil_node_t* node; node = fil_node_create_low( - name, size, space, is_raw, IORequest::is_punch_hole_supported(), - atomic_write, max_pages); + name, size, space, is_raw, atomic_write, max_pages); return(node == NULL ? NULL : node->name); } @@ -3868,23 +3845,6 @@ fil_ibd_create( return(DB_OUT_OF_FILE_SPACE); } - /* Note: We are actually punching a hole, previous contents will - be lost after this call, if it succeeds. In this case the file - should be full of NULs. */ - - bool punch_hole = os_is_sparse_file_supported(path, file); - - if (punch_hole) { - - dberr_t punch_err; - - punch_err = os_file_punch_hole(file, 0, size * UNIV_PAGE_SIZE); - - if (punch_err != DB_SUCCESS) { - punch_hole = false; - } - } - /* printf("Creating tablespace %s id %lu\n", path, space_id); */ /* We have to write the space id to the file immediately and flush the @@ -3920,9 +3880,6 @@ fil_ibd_create( err = os_file_write( request, path, file, page, 0, page_size.physical()); - - ut_ad(err != DB_IO_NO_PUNCH_HOLE); - } else { page_zip_des_t page_zip; page_zip_set_size(&page_zip, page_size.physical()); @@ -3940,10 +3897,6 @@ fil_ibd_create( err = os_file_write( request, path, file, page_zip.data, 0, page_size.physical()); - - ut_a(err != DB_IO_NO_PUNCH_HOLE); - - punch_hole = false; } ut_free(buf2); @@ -3993,8 +3946,7 @@ fil_ibd_create( ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, crypt_data, true); - if (!fil_node_create_low( - path, size, space, false, punch_hole, TRUE)) { + if (!fil_node_create_low(path, size, space, false, true)) { if (crypt_data) { free(crypt_data); @@ -4387,7 +4339,7 @@ skip_validate: df_remote.is_open() ? df_remote.filepath() : df_dict.is_open() ? df_dict.filepath() : df_default.filepath(), 0, space, false, - true, TRUE) == NULL) { + true) == NULL) { err = DB_ERROR; } } @@ -4750,8 +4702,7 @@ fil_ibd_load( the rounding formula for extents and pages is somewhat complex; we let fil_node_open() do that task. */ - if (!fil_node_create_low(file.filepath(), 0, space, - false, true, false)) { + if (!fil_node_create_low(file.filepath(), 0, space, false, false)) { ut_error; } @@ -5487,29 +5438,6 @@ fil_io( const char* name = node->name == NULL ? space->name : node->name; -#ifdef MYSQL_COMPRESSION - /* Don't compress the log, page 0 of all tablespaces, tables - compresssed with the old scheme and all pages from the system - tablespace. */ - - if (req_type.is_write() - && !req_type.is_log() - && !page_size.is_compressed() - && page_id.page_no() > 0 - && IORequest::is_punch_hole_supported() - && node->punch_hole) { - - ut_ad(!req_type.is_log()); - - req_type.set_punch_hole(); - - req_type.compression_algorithm(space->compression_type); - - } else { - req_type.clear_compressed(); - } -#endif /* MYSQL_COMPRESSION */ - req_type.block_size(node->block_size); /* Queue the aio request */ @@ -5520,20 +5448,6 @@ fil_io( && srv_read_only_mode, node, message, write_size); - if (err == DB_IO_NO_PUNCH_HOLE) { - - err = DB_SUCCESS; - - if (node->punch_hole) { - - ib::warn() - << "Punch hole failed for '" - << name << "'"; - } - - fil_no_punch_hole(node); - } - /* We an try to recover the page from the double write buffer if the decompression fails or the page is corrupt. */ @@ -6160,17 +6074,8 @@ fil_iterate( iter.filepath, iter.file, writeptr, offset, (ulint) n_bytes)) != DB_SUCCESS) { - /* This is not a hard error */ - if (err == DB_IO_NO_PUNCH_HOLE) { - - err = DB_SUCCESS; - write_type &= ~IORequest::PUNCH_HOLE; - - } else { - ib::error() << "os_file_write() failed"; - - return(err); - } + ib::error() << "os_file_write() failed"; + return(err); } } @@ -6797,111 +6702,6 @@ truncate_t::truncate( return(err); } -/** -Note that the file system where the file resides doesn't support PUNCH HOLE. -Called from AIO handlers when IO returns DB_IO_NO_PUNCH_HOLE -@param[in,out] node Node to set */ -void -fil_no_punch_hole(fil_node_t* node) -{ - node->punch_hole = false; -} - -#ifdef MYSQL_COMPRESSION - -/** Set the compression type for the tablespace of a table -@param[in] table The table that should be compressed -@param[in] algorithm Text representation of the algorithm -@return DB_SUCCESS or error code */ -dberr_t -fil_set_compression( - dict_table_t* table, - const char* algorithm) -{ - ut_ad(table != NULL); - - /* We don't support Page Compression for the system tablespace, - the temporary tablespace, or any general tablespace because - COMPRESSION is set by TABLE DDL, not TABLESPACE DDL. There is - no other technical reason. Also, do not use it for missing - tables or tables with compressed row_format. */ - if (table->ibd_file_missing - || !DICT_TF2_FLAG_IS_SET(table, DICT_TF2_USE_FILE_PER_TABLE) - || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY) - || page_size_t(table->flags).is_compressed()) { - - return(DB_IO_NO_PUNCH_HOLE_TABLESPACE); - } - - dberr_t err; - Compression compression; - - if (algorithm == NULL || strlen(algorithm) == 0) { - -#ifndef UNIV_DEBUG - compression.m_type = Compression::NONE; -#else - /* This is a Debug tool for setting compression on all - compressible tables not otherwise specified. */ - switch (srv_debug_compress) { - case Compression::LZ4: - case Compression::ZLIB: - case Compression::NONE: - - compression.m_type = - static_cast( - srv_debug_compress); - break; - - default: - compression.m_type = Compression::NONE; - } - -#endif /* UNIV_DEBUG */ - - err = DB_SUCCESS; - - } else { - - err = Compression::check(algorithm, &compression); - } - - fil_space_t* space = fil_space_get(table->space); - - if (space == NULL) { - return(DB_NOT_FOUND); - } - - space->compression_type = compression.m_type; - - if (space->compression_type != Compression::NONE) { - - const fil_node_t* node; - - node = UT_LIST_GET_FIRST(space->chain); - - if (!node->punch_hole) { - - return(DB_IO_NO_PUNCH_HOLE_FS); - } - } - - return(err); -} - -/** Get the compression algorithm for a tablespace. -@param[in] space_id Space ID to check -@return the compression algorithm */ -Compression::Type -fil_get_compression( - ulint space_id) -{ - fil_space_t* space = fil_space_get(space_id); - - return(space == NULL ? Compression::NONE : space->compression_type); -} -#endif /* MYSQL_COMPRESSION */ - /** Build the basic folder name from the path and length provided @param[in] path pathname (may also include the file basename) @param[in] len length of the path, in bytes */ diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index cd2c62e00c1..8ebe4513b3f 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (C) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (C) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -415,21 +415,23 @@ fil_decompress_page( ulint compression_alg = 0; byte *in_buf; ulint ptype; - ulint header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE; + ulint header_len; ut_ad(buf); ut_ad(len); ptype = mach_read_from_2(buf+FIL_PAGE_TYPE); - if (ptype == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { - header_len += FIL_PAGE_COMPRESSION_METHOD_SIZE; - } - - /* Do not try to uncompressed pages that are not compressed */ - if (ptype != FIL_PAGE_PAGE_COMPRESSED && - ptype != FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED && - ptype != FIL_PAGE_COMPRESSED) { + switch (ptype) { + case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: + header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE + + FIL_PAGE_COMPRESSION_METHOD_SIZE; + break; + case FIL_PAGE_PAGE_COMPRESSED: + header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE; + break; + default: + /* The page is not in our format. */ return; } @@ -443,9 +445,7 @@ fil_decompress_page( /* Before actual decompress, make sure that page type is correct */ - if (mach_read_from_4(buf+FIL_PAGE_SPACE_OR_CHKSUM) != BUF_NO_CHECKSUM_MAGIC || - (ptype != FIL_PAGE_PAGE_COMPRESSED && - ptype != FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED)) { + if (mach_read_from_4(buf+FIL_PAGE_SPACE_OR_CHKSUM) != BUF_NO_CHECKSUM_MAGIC) { ib::error() << "Corruption: We try to uncompress corrupted page:" << " CRC " << mach_read_from_4(buf+FIL_PAGE_SPACE_OR_CHKSUM) diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 3b89da2301b..600de5418bd 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -682,30 +682,7 @@ Datafile::find_space_id() err = os_file_read( request, m_handle, page, n_bytes, page_size); - if (err == DB_IO_DECOMPRESS_FAIL) { - - /* If the page was compressed on the fly then - try and decompress the page */ - - n_bytes = os_file_compressed_page_size(page); - - if (n_bytes != ULINT_UNDEFINED) { - - err = os_file_read( - request, - m_handle, page, page_size, - UNIV_PAGE_SIZE_MAX); - - if (err != DB_SUCCESS) { - - ib::info() - << "READ FAIL: " - << "page_no:" << j; - continue; - } - } - - } else if (err != DB_SUCCESS) { + if (err != DB_SUCCESS) { ib::info() << "READ FAIL: page_no:" << j; @@ -838,11 +815,6 @@ Datafile::restore_from_doublewrite( IORequest request(IORequest::WRITE); - /* Note: The pages are written out as uncompressed because we don't - have the compression algorithm information at this point. */ - - request.disable_compression(); - return(os_file_write( request, m_filepath, m_handle, page, 0, page_size.physical())); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index d74f8cfa5bf..55c34db2b59 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1838,7 +1838,7 @@ fts_create_one_common_table( FTS_CONFIG_TABLE_VALUE_COL_LEN); } - error = row_create_table_for_mysql(new_table, NULL, trx, false, + error = row_create_table_for_mysql(new_table, trx, false, FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); if (error == DB_SUCCESS) { @@ -2055,7 +2055,7 @@ fts_create_one_index_table( (DATA_MTYPE_MAX << 16) | DATA_UNSIGNED | DATA_NOT_NULL, FTS_INDEX_ILIST_LEN); - error = row_create_table_for_mysql(new_table, NULL, trx, false, + error = row_create_table_for_mysql(new_table, trx, false, FIL_SPACE_ENCRYPTION_DEFAULT, FIL_DEFAULT_ENCRYPTION_KEY); if (error == DB_SUCCESS) { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0fe23301c32..1e47da86f70 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -382,25 +382,6 @@ get_row_format( static ulong innodb_default_row_format = DEFAULT_ROW_FORMAT_DYNAMIC; -#ifdef UNIV_DEBUG -/** Values for --innodb-debug-compress names. */ -static const char* innodb_debug_compress_names[] = { - "none", - "zlib", - "lz4", - "lz4hc", - NullS -}; - -/** Enumeration of --innodb-debug-compress */ -static TYPELIB innodb_debug_compress_typelib = { - array_elements(innodb_debug_compress_names) - 1, - "innodb_debug_compress_typelib", - innodb_debug_compress_names, - NULL -}; -#endif /* UNIV_DEBUG */ - /** Possible values for system variable "innodb_stats_method". The values are defined the same as its corresponding MyISAM system variable "myisam_stats_method"(see "myisam_stats_method_names"), for better usability */ @@ -2828,64 +2809,6 @@ innobase_raw_format( return(ut_str_sql_format(buf_tmp, buf_tmp_used, buf, buf_size)); } -#ifdef MYSQL_COMPRESSION -/** Check if the string is "empty" or "none". -@param[in] algorithm Compression algorithm to check -@return true if no algorithm requested */ -bool -Compression::is_none(const char* algorithm) -{ - /* NULL is the same as NONE */ - if (algorithm == NULL - || *algorithm == 0 - || innobase_strcasecmp(algorithm, "none") == 0) { - return(true); - } - - return(false); -} - -/** Check for supported COMPRESS := (ZLIB | LZ4 | NONE) supported values -@param[in] name Name of the compression algorithm -@param[out] compression The compression algorithm -@return DB_SUCCESS or DB_UNSUPPORTED */ -dberr_t -Compression::check( - const char* algorithm, - Compression* compression) -{ - if (is_none(algorithm)) { - - compression->m_type = NONE; - - } else if (innobase_strcasecmp(algorithm, "zlib") == 0) { - - compression->m_type = ZLIB; - - } else if (innobase_strcasecmp(algorithm, "lz4") == 0) { - - compression->m_type = LZ4; - - } else { - return(DB_UNSUPPORTED); - } - - return(DB_SUCCESS); -} - -/** Check for supported COMPRESS := (ZLIB | LZ4 | NONE) supported values -@param[in] name Name of the compression algorithm -@param[out] compression The compression algorithm -@return DB_SUCCESS or DB_UNSUPPORTED */ -dberr_t -Compression::validate(const char* algorithm) -{ - Compression compression; - - return(check(algorithm, &compression)); -} -#endif /* MYSQL_COMPRESSION */ - /*********************************************************************//** Compute the next autoinc value. @@ -7042,34 +6965,6 @@ ha_innobase::open( } info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); - -#ifdef MYSQL_COMPRESSION - dberr_t err = fil_set_compression(m_prebuilt->table, - table->s->compress.str); - - switch (err) { - case DB_NOT_FOUND: - case DB_UNSUPPORTED: - /* We will do another check before the create - table and push the error to the client there. */ - break; - - case DB_IO_NO_PUNCH_HOLE_TABLESPACE: - /* We did the check in the 'if' above. */ - - case DB_IO_NO_PUNCH_HOLE_FS: - /* During open we can't check whether the FS supports - punch hole or not, at least on Linux. */ - break; - - default: - ut_error; - - case DB_SUCCESS: - break; - } -#endif - DBUG_RETURN(0); } @@ -12099,98 +11994,36 @@ err_col: on re-start we don't need to restore temp-table and so no entry is needed in SYSTEM tables. */ if (dict_table_is_temporary(table)) { -#ifdef MYSQL_COMPRESSION - if (m_create_info->compress.length > 0) { - push_warning_printf( - m_thd, - Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "InnoDB: Compression not supported for " - "temporary tables"); + /* Get a new table ID */ + dict_table_assign_new_id(table, m_trx); - err = DB_UNSUPPORTED; - - dict_mem_table_free(table); - } else { -#endif /* MYSQL_COMPRESSION */ - /* Get a new table ID */ - dict_table_assign_new_id(table, m_trx); - - /* Create temp tablespace if configured. */ - err = dict_build_tablespace_for_table(table, NULL); - - if (err == DB_SUCCESS) { - /* Temp-table are maintained in memory and so - can_be_evicted is FALSE. */ - mem_heap_t* temp_table_heap; - - temp_table_heap = mem_heap_create(256); - - dict_table_add_to_cache( - table, FALSE, temp_table_heap); - - DBUG_EXECUTE_IF("ib_ddl_crash_during_create2", - DBUG_SUICIDE();); - - mem_heap_free(temp_table_heap); - } -#ifdef MYSQL_COMPRESSION - } -#endif - - } else { - const char* algorithm = NULL; - -#if MYSQL_COMPRESSION - const char* algorithm = m_create_info->compress.str; - - if (!(m_flags2 & DICT_TF2_USE_FILE_PER_TABLE) - && m_create_info->compress.length > 0 - && !Compression::is_none(algorithm)) { - - push_warning_printf( - m_thd, - Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "InnoDB: Compression not supported for " - "shared tablespaces"); - - algorithm = NULL; - - err = DB_UNSUPPORTED; - dict_mem_table_free(table); - - } else if (Compression::validate(algorithm) != DB_SUCCESS - || m_form->s->row_type == ROW_TYPE_COMPRESSED - || m_create_info->key_block_size > 0) { - - algorithm = NULL; - } -#endif /* MYSQL_COMPRESSION */ + /* Create temp tablespace if configured. */ + err = dict_build_tablespace_for_table(table, NULL); + if (err == DB_SUCCESS) { + /* Temp-table are maintained in memory and so + can_be_evicted is FALSE. */ + mem_heap_t* temp_table_heap; + + temp_table_heap = mem_heap_create(256); + + dict_table_add_to_cache( + table, FALSE, temp_table_heap); + + DBUG_EXECUTE_IF("ib_ddl_crash_during_create2", + DBUG_SUICIDE();); + + mem_heap_free(temp_table_heap); + } + } else { if (err == DB_SUCCESS) { err = row_create_table_for_mysql( - table, algorithm, m_trx, false, + table, m_trx, false, (fil_encryption_t)options->encryption, options->encryption_key_id); } - if (err == DB_IO_NO_PUNCH_HOLE_FS) { - - ut_ad(!dict_table_in_shared_tablespace(table)); - - push_warning_printf( - m_thd, - Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "InnoDB: Punch hole not supported by the " - "file system or the tablespace page size " - "is not large enough. Compression disabled"); - - err = DB_SUCCESS; - } - DBUG_EXECUTE_IF("ib_crash_during_create_for_encryption", DBUG_SUICIDE();); } @@ -12665,77 +12498,6 @@ create_table_info_t::create_option_tablespace_is_valid() } #endif -#ifdef MYSQL_COMPRESSION -/** Validate the COPMRESSION option. -@return true if valid, false if not. */ -bool -create_table_info_t::create_option_compression_is_valid() -{ - dberr_t err; - Compression compression; - - if (m_create_info->compress.length == 0) { - return(true); - } - - err = Compression::check(m_create_info->compress.str, &compression); - - if (err == DB_UNSUPPORTED) { - push_warning_printf( - m_thd, - Sql_condition::WARN_LEVEL_WARN, - ER_UNSUPPORTED_EXTENSION, - "InnoDB: Unsupported compression algorithm '%s'", - m_create_info->compress.str); - return(false); - } - - /* Allow Compression=NONE on any tablespace or row format. */ - if (compression.m_type == Compression::NONE) { - return(true); - } - - static char intro[] = "InnoDB: Page Compression is not supported"; - - if (m_create_info->key_block_size != 0 - || m_create_info->row_type == ROW_TYPE_COMPRESSED) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - ER_UNSUPPORTED_EXTENSION, - "%s with row_format=compressed or" - " key_block_size > 0", intro); - return(false); - } - - if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "%s for temporary tables", intro); - return(false); - } - - if (tablespace_is_general_space(m_create_info)) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "%s for shared general tablespaces", intro); - return(false); - } - - /* The only non-file-per-table tablespace left is the system space. */ - if (!m_use_file_per_table) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "%s for the system tablespace", intro); - return(false); - } - - return(true); -} -#endif /* MYSQL_COMPRESSION */ - /** Validate the create options. Check that the options KEY_BLOCK_SIZE, ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE are compatible with each other and other settings. These CREATE OPTIONS are not validated @@ -12935,25 +12697,6 @@ create_table_info_t::create_options_are_invalid() } } -#ifdef MYSQL_COMPRESSION - /* Validate the page compression parameter. */ - if (!create_option_compression_is_valid()) { - return("COMPRESSION"); - } - - /* Check the encryption option. */ - if (ret == NULL && m_create_info->encrypt_type.length > 0) { - dberr_t err; - - err = Encryption::validate(m_create_info->encrypt_type.str); - - if (err == DB_UNSUPPORTED) { - my_error(ER_INVALID_ENCRYPTION_OPTION, MYF(0)); - ret = "ENCRYPTION"; - } - } -#endif - return(ret); } @@ -13269,17 +13012,6 @@ create_table_info_t::innobase_table_flags() m_flags = 0; m_flags2 = 0; -#ifdef MYSQL_COMPRESSION - /* Validate the page compression parameter. */ - if (!create_option_compression_is_valid()) { - /* No need to do anything. Warnings were issued. - The compresion setting will be ignored later. - If inodb_strict_mode=ON, this is called twice unless - there was a problem before. - If inodb_strict_mode=OFF, this is the only call. */ - } -#endif - /* Check if there are any FTS indexes defined on this table. */ for (uint i = 0; i < m_form->s->keys; i++) { const KEY* key = &m_form->key_info[i]; @@ -22573,11 +22305,6 @@ static MYSQL_SYSVAR_BOOL(disable_background_merge, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_RQCMDARG, "Disable change buffering merges by the master thread", NULL, NULL, FALSE); - -static MYSQL_SYSVAR_ENUM(compress_debug, srv_debug_compress, - PLUGIN_VAR_RQCMDARG, - "Compress all tables, without specifying the COMPRESS table attribute", - NULL, NULL, Compression::NONE, &innodb_debug_compress_typelib); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ static MYSQL_SYSVAR_ULONG(buf_dump_status_frequency, srv_buf_dump_status_frequency, @@ -23114,7 +22841,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(data_file_size_debug), MYSQL_SYSVAR(fil_make_page_dirty_debug), MYSQL_SYSVAR(saved_page_number_debug), - MYSQL_SYSVAR(compress_debug), MYSQL_SYSVAR(disable_resize_buffer_pool_debug), MYSQL_SYSVAR(page_cleaner_disabled_debug), MYSQL_SYSVAR(dict_stats_disabled_debug), diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index cef39e594b9..8d879207fab 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -795,9 +795,6 @@ public: /** Validate TABLESPACE option. */ bool create_option_tablespace_is_valid(); - /** Validate COMPRESSION option. */ - bool create_option_compression_is_valid(); - /** Prepare to create a table. */ int prepare_create_table(const char* name); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 004b6863a9f..6b6667b5e56 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4358,7 +4358,6 @@ prepare_inplace_alter_table_dict( dict_index_t* fts_index = NULL; ulint new_clustered = 0; dberr_t error; - const char* punch_hole_warning = NULL; ulint num_fts_index; dict_add_v_col_t* add_v = NULL; ha_innobase_inplace_ctx*ctx; @@ -4534,7 +4533,6 @@ prepare_inplace_alter_table_dict( ulint z = 0; ulint key_id = FIL_DEFAULT_ENCRYPTION_KEY; fil_encryption_t mode = FIL_SPACE_ENCRYPTION_DEFAULT; - const char* compression=NULL; crypt_data = fil_space_get_crypt_data(ctx->prebuilt->table->space); @@ -4732,39 +4730,11 @@ prepare_inplace_alter_table_dict( ctx->new_table->fts->doc_col = fts_doc_id_col; } -#ifdef MYSQL_COMPRESSION - compression = ha_alter_info->create_info->compress.str; - - if (Compression::validate(compression) != DB_SUCCESS) { - - compression = NULL; - } -#endif /* MYSQL_COMPRESSION */ - error = row_create_table_for_mysql( - ctx->new_table, compression, ctx->trx, false, mode, key_id); - - punch_hole_warning = - (error == DB_IO_NO_PUNCH_HOLE_FS) - ? "Punch hole is not supported by the file system" - : "Page Compression is not supported for this" - " tablespace"; + ctx->new_table, ctx->trx, false, mode, key_id); switch (error) { dict_table_t* temp_table; - case DB_IO_NO_PUNCH_HOLE_FS: - case DB_IO_NO_PUNCH_HOLE_TABLESPACE: - push_warning_printf( - ctx->prebuilt->trx->mysql_thd, - Sql_condition::WARN_LEVEL_WARN, - HA_ERR_UNSUPPORTED, - "%s. Compression disabled for '%s'", - punch_hole_warning, - ctx->new_table->name.m_name); - - error = DB_SUCCESS; - - case DB_SUCCESS: /* We need to bump up the table ref count and before we can use it we need to open the @@ -9078,10 +9048,6 @@ foreign_fail: } } - /* We don't support compression for the system tablespace nor - the temporary tablespace. Only because they are shared tablespaces. - There is no other technical reason. */ - innobase_parse_hint_from_comment( m_user_thd, m_prebuilt->table, altered_table->s); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 1d535c58e77..de23e998020 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1615,7 +1615,6 @@ public: if written again we check is TRIM operation needed. */ - ulint space; /*!< space id */ unsigned key_version; /*!< key version for this block */ bool page_encrypted; /*!< page is page encrypted */ bool page_compressed;/*!< page is page compressed */ diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index f2b1b151598..5e75c446bbd 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -734,9 +734,6 @@ buf_block_get_frame( case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_ZIP_DIRTY: case BUF_BLOCK_NOT_USED: - if (block->page.encrypted) { - goto ok; - } ut_error; break; case BUF_BLOCK_FILE_PAGE: diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index d4757d93509..ab505e04083 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -146,18 +146,6 @@ enum dberr_t { DB_IO_ERROR = 100, /*!< Generic IO error */ - DB_IO_DECOMPRESS_FAIL, /*!< Failure to decompress a page - after reading it from disk */ - - DB_IO_NO_PUNCH_HOLE, /*!< Punch hole not supported by - InnoDB */ - - DB_IO_NO_PUNCH_HOLE_FS, /*!< The file system doesn't support - punch hole */ - - DB_IO_NO_PUNCH_HOLE_TABLESPACE, /*!< The tablespace doesn't support - punch hole */ - DB_IO_PARTIAL_FAILED, /*!< Partial IO request failed */ DB_FORCED_ABORT, /*!< Transaction was forced to rollback diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 6410c86939b..0788f84d11a 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -166,9 +166,6 @@ struct fil_space_t { UT_LIST_NODE_T(fil_space_t) space_list; /*!< list of all spaces */ - /** Compression algorithm */ - Compression::Type compression_type; - /** MariaDB encryption data */ fil_space_crypt_t* crypt_data; @@ -234,9 +231,6 @@ struct fil_node_t { /** link to the fil_system->LRU list (keeping track of open files) */ UT_LIST_NODE_T(fil_node_t) LRU; - /** whether the file system of this file supports PUNCH HOLE */ - bool punch_hole; - /** block size to use for punching holes */ ulint block_size; @@ -438,23 +432,6 @@ extern fil_addr_t fil_addr_null; used to encrypt the page + 32-bit checksum or 64 bits of zero if no encryption */ -/** If page type is FIL_PAGE_COMPRESSED then the 8 bytes starting at -FIL_PAGE_FILE_FLUSH_LSN are broken down as follows: */ - -/** Control information version format (u8) */ -static const ulint FIL_PAGE_VERSION = FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION; - -/** Compression algorithm (u8) */ -static const ulint FIL_PAGE_ALGORITHM_V1 = FIL_PAGE_VERSION + 1; - -/** Original page type (u16) */ -static const ulint FIL_PAGE_ORIGINAL_TYPE_V1 = FIL_PAGE_ALGORITHM_V1 + 1; - -/** Original data size in bytes (u16)*/ -static const ulint FIL_PAGE_ORIGINAL_SIZE_V1 = FIL_PAGE_ORIGINAL_TYPE_V1 + 2; - -/** Size after compression (u16) */ -static const ulint FIL_PAGE_COMPRESS_SIZE_V1 = FIL_PAGE_ORIGINAL_SIZE_V1 + 2; /** This overloads FIL_PAGE_FILE_FLUSH_LSN for RTREE Split Sequence Number */ #define FIL_RTREE_SPLIT_SEQ_NUM FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION @@ -504,11 +481,12 @@ static const ulint FIL_PAGE_COMPRESS_SIZE_V1 = FIL_PAGE_ORIGINAL_SIZE_V1 + 2; #define FIL_PAGE_TYPE_UNKNOWN 13 /*!< In old tablespaces, garbage in FIL_PAGE_TYPE is replaced with this value when flushing pages. */ -#define FIL_PAGE_COMPRESSED 14 /*!< Compressed page */ -#define FIL_PAGE_ENCRYPTED 15 /*!< Encrypted page */ -#define FIL_PAGE_COMPRESSED_AND_ENCRYPTED 16 - /*!< Compressed and Encrypted page */ -#define FIL_PAGE_ENCRYPTED_RTREE 17 /*!< Encrypted R-tree page */ + +/* File page types introduced in MySQL 5.7, not supported in MariaDB */ +//#define FIL_PAGE_COMPRESSED 14 +//#define FIL_PAGE_ENCRYPTED 15 +//#define FIL_PAGE_COMPRESSED_AND_ENCRYPTED 16 +//#define FIL_PAGE_ENCRYPTED_RTREE 17 /** Used by i_s.cc to index into the text description. */ #define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_UNKNOWN @@ -1622,24 +1600,6 @@ fil_names_dirty_and_write( fil_space_t* space, mtr_t* mtr); -/** Set the compression type for the tablespace of a table -@param[in] table Table that should be compressesed -@param[in] algorithm Text representation of the algorithm -@return DB_SUCCESS or error code */ -dberr_t -fil_set_compression( - dict_table_t* table, - const char* algorithm) - MY_ATTRIBUTE((warn_unused_result)); - -/** Get the compression type for the tablespace -@param[in] space_id Space ID to check -@return the compression algorithm */ -Compression::Type -fil_get_compression( - ulint space_id) - MY_ATTRIBUTE((warn_unused_result)); - /** Write MLOG_FILE_NAME records if a persistent tablespace was modified for the first time since the latest fil_names_clear(). @param[in,out] space tablespace @@ -1705,10 +1665,6 @@ fil_names_clear( lsn_t lsn, bool do_write); -/** Note that the file system where the file resides doesn't support PUNCH HOLE -@param[in,out] node Node to set */ -void fil_no_punch_hole(fil_node_t* node); - #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH void test_make_filepath(); #endif /* UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH */ diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic index 8f8a4194c0d..01fa1093e5e 100644 --- a/storage/innobase/include/fil0fil.ic +++ b/storage/innobase/include/fil0fil.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2015, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -58,49 +58,41 @@ fil_get_page_type_name( { switch(page_type) { case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED: - return (const char*)"PAGE_COMPRESSED_ENRYPTED"; + return "PAGE_COMPRESSED_ENRYPTED"; case FIL_PAGE_PAGE_COMPRESSED: - return (const char*)"PAGE_COMPRESSED"; + return "PAGE_COMPRESSED"; case FIL_PAGE_INDEX: - return (const char*)"INDEX"; + return "INDEX"; case FIL_PAGE_RTREE: - return (const char*)"RTREE"; + return "RTREE"; case FIL_PAGE_UNDO_LOG: - return (const char*)"UNDO LOG"; + return "UNDO LOG"; case FIL_PAGE_INODE: - return (const char*)"INODE"; + return "INODE"; case FIL_PAGE_IBUF_FREE_LIST: - return (const char*)"IBUF_FREE_LIST"; + return "IBUF_FREE_LIST"; case FIL_PAGE_TYPE_ALLOCATED: - return (const char*)"ALLOCATED"; + return "ALLOCATED"; case FIL_PAGE_IBUF_BITMAP: - return (const char*)"IBUF_BITMAP"; + return "IBUF_BITMAP"; case FIL_PAGE_TYPE_SYS: - return (const char*)"SYS"; + return "SYS"; case FIL_PAGE_TYPE_TRX_SYS: - return (const char*)"TRX_SYS"; + return "TRX_SYS"; case FIL_PAGE_TYPE_FSP_HDR: - return (const char*)"FSP_HDR"; + return "FSP_HDR"; case FIL_PAGE_TYPE_XDES: - return (const char*)"XDES"; + return "XDES"; case FIL_PAGE_TYPE_BLOB: - return (const char*)"BLOB"; + return "BLOB"; case FIL_PAGE_TYPE_ZBLOB: - return (const char*)"ZBLOB"; + return "ZBLOB"; case FIL_PAGE_TYPE_ZBLOB2: - return (const char*)"ZBLOB2"; - case FIL_PAGE_COMPRESSED: - return (const char*)"ORACLE PAGE COMPRESSED"; - case FIL_PAGE_ENCRYPTED: - return (const char*)"ORACLE PAGE ENCRYPTED"; - case FIL_PAGE_COMPRESSED_AND_ENCRYPTED: - return (const char*)"ORACLE PAGE COMPRESSED AND ENCRYPTED"; - case FIL_PAGE_ENCRYPTED_RTREE: - return (const char*)"ORACLE RTREE ENCRYPTED"; + return "ZBLOB2"; case FIL_PAGE_TYPE_UNKNOWN: - return (const char*)"OLD UNKOWN PAGE TYPE"; + return "OLD UNKOWN PAGE TYPE"; default: - return (const char*)"PAGE TYPE CORRUPTED"; + return "PAGE TYPE CORRUPTED"; } } @@ -145,52 +137,22 @@ fil_page_type_validate( page_type == FIL_PAGE_TYPE_BLOB || page_type == FIL_PAGE_TYPE_ZBLOB || page_type == FIL_PAGE_TYPE_ZBLOB2 || - page_type == FIL_PAGE_COMPRESSED || - page_type == FIL_PAGE_TYPE_UNKNOWN || - page_type == FIL_PAGE_ENCRYPTED || - page_type == FIL_PAGE_COMPRESSED_AND_ENCRYPTED || - page_type == FIL_PAGE_ENCRYPTED_RTREE))) { + page_type == FIL_PAGE_TYPE_UNKNOWN))) { - uint key_version = mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); - bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED); - bool page_compressed_encrypted = (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED); ulint space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); ulint offset = mach_read_from_4(page + FIL_PAGE_OFFSET); - ib_uint64_t lsn = mach_read_from_8(page + FIL_PAGE_LSN); - ulint compressed_len = mach_read_from_2(page + FIL_PAGE_DATA); fil_system_enter(); fil_space_t* rspace = fil_space_get_by_id(space); fil_system_exit(); /* Dump out the page info */ - fprintf(stderr, "InnoDB: Space %lu offset %lu name %s page_type %lu page_type_name %s\n" - "InnoDB: key_version %u page_compressed %d page_compressed_encrypted %d lsn %llu compressed_len %lu\n", - space, offset, rspace->name, page_type, fil_get_page_type_name(page_type), - key_version, page_compressed, page_compressed_encrypted, (ulonglong)lsn, compressed_len); - fflush(stderr); - - ut_ad(page_type == FIL_PAGE_PAGE_COMPRESSED || - page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED || - page_type == FIL_PAGE_INDEX || - page_type == FIL_PAGE_RTREE || - page_type == FIL_PAGE_UNDO_LOG || - page_type == FIL_PAGE_INODE || - page_type == FIL_PAGE_IBUF_FREE_LIST || - page_type == FIL_PAGE_TYPE_ALLOCATED || - page_type == FIL_PAGE_IBUF_BITMAP || - page_type == FIL_PAGE_TYPE_SYS || - page_type == FIL_PAGE_TYPE_TRX_SYS || - page_type == FIL_PAGE_TYPE_FSP_HDR || - page_type == FIL_PAGE_TYPE_XDES || - page_type == FIL_PAGE_TYPE_BLOB || - page_type == FIL_PAGE_TYPE_ZBLOB || - page_type == FIL_PAGE_TYPE_ZBLOB2 || - page_type == FIL_PAGE_COMPRESSED || - page_type == FIL_PAGE_TYPE_UNKNOWN || - page_type == FIL_PAGE_ENCRYPTED || - page_type == FIL_PAGE_COMPRESSED_AND_ENCRYPTED || - page_type == FIL_PAGE_ENCRYPTED_RTREE); - + ib::fatal() << "Page " << space << ":" << offset + << " name " << (rspace ? rspace->name : "???") + << " page_type " << page_type + << " key_version " + << mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) + << " lsn " << mach_read_from_8(page + FIL_PAGE_LSN) + << " compressed_len " << mach_read_from_2(page + FIL_PAGE_DATA); return false; } diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index cf4702cb366..541fbe24d82 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -41,7 +41,6 @@ struct fts_string_t; // JAN: TODO missing features: #undef MYSQL_57_SELECT_COUNT_OPTIMIZATION -#undef MYSQL_COMPRESSION #undef MYSQL_FT_INIT_EXT #undef MYSQL_INNODB_API_CB #undef MYSQL_INNODB_PARTITIONING diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 474c6848b09..57ee015dfdd 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -169,130 +169,6 @@ static const ulint OS_FILE_OPERATION_NOT_SUPPORTED = 125; static const ulint OS_FILE_ERROR_MAX = 200; /* @} */ -/** Compression algorithm. */ -struct Compression { - - /** Algorithm types supported */ - enum Type { - /* Note: During recovery we don't have the compression type - because the .frm file has not been read yet. Therefore - we write the recovered pages out without compression. */ - - /** No compression */ - NONE = 0, - - /** Use ZLib */ - ZLIB = 1, - - /** Use LZ4 faster variant, usually lower compression. */ - LZ4 = 2 - }; - - /** Compressed page meta-data */ - struct meta_t { - - /** Version number */ - uint8_t m_version; - - /** Algorithm type */ - Type m_algorithm; - - /** Original page type */ - uint16_t m_original_type; - - /** Original page size, before compression */ - uint16_t m_original_size; - - /** Size after compression */ - uint16_t m_compressed_size; - }; - - /** Default constructor */ - Compression() : m_type(NONE) { }; - - /** Specific constructor - @param[in] type Algorithm type */ - explicit Compression(Type type) - : - m_type(type) - { -#ifdef UNIV_DEBUG - switch (m_type) { - case NONE: - case ZLIB: - case LZ4: - - default: - ut_error; - } -#endif /* UNIV_DEBUG */ - } - - /** Check the page header type field. - @param[in] page Page contents - @return true if it is a compressed page */ - static bool is_compressed_page(const byte* page) - MY_ATTRIBUTE((warn_unused_result)); - - /** Check wether the compression algorithm is supported. - @param[in] algorithm Compression algorithm to check - @param[out] type The type that algorithm maps to - @return DB_SUCCESS or error code */ - static dberr_t check(const char* algorithm, Compression* type) - MY_ATTRIBUTE((warn_unused_result)); - - /** Validate the algorithm string. - @param[in] algorithm Compression algorithm to check - @return DB_SUCCESS or error code */ - static dberr_t validate(const char* algorithm) - MY_ATTRIBUTE((warn_unused_result)); - - /** Convert to a "string". - @param[in] type The compression type - @return the string representation */ - static const char* to_string(Type type) - MY_ATTRIBUTE((warn_unused_result)); - - /** Convert the meta data to a std::string. - @param[in] meta Page Meta data - @return the string representation */ - static std::string to_string(const meta_t& meta) - MY_ATTRIBUTE((warn_unused_result)); - - /** Deserizlise the page header compression meta-data - @param[in] header Pointer to the page header - @param[out] control Deserialised data */ - static void deserialize_header( - const byte* page, - meta_t* control); - - /** Check if the string is "empty" or "none". - @param[in] algorithm Compression algorithm to check - @return true if no algorithm requested */ - static bool is_none(const char* algorithm) - MY_ATTRIBUTE((warn_unused_result)); - - /** Decompress the page data contents. Page type must be - FIL_PAGE_COMPRESSED, if not then the source contents are - left unchanged and DB_SUCCESS is returned. - @param[in] dblwr_recover true of double write recovery - in progress - @param[in,out] src Data read from disk, decompressed - data will be copied to this page - @param[in,out] dst Scratch area to use for decompression - @param[in] dst_len Size of the scratch area in bytes - @return DB_SUCCESS or error code */ - static dberr_t deserialize( - bool dblwr_recover, - byte* src, - byte* dst, - ulint dst_len) - MY_ATTRIBUTE((warn_unused_result)); - - /** Compression type */ - Type m_type; -}; - /** Types for AIO operations @{ */ /** No transformations during read/write, write as is. */ @@ -335,25 +211,13 @@ public: /** Ignore failed reads of non-existent pages */ IGNORE_MISSING = 128, - - /** Use punch hole if available, only makes sense if - compression algorithm != NONE. Ignored if not set */ - PUNCH_HOLE = 256, - - /** Force raw read, do not try to compress/decompress. - This can be used to force a read and write without any - compression e.g., for redo log, merge sort temporary files - and the truncate redo log. */ - NO_COMPRESSION = 512 - }; /** Default constructor */ IORequest() : m_block_size(UNIV_SECTOR_SIZE), - m_type(READ), - m_compression() + m_type(READ) { /* No op */ } @@ -364,16 +228,8 @@ public: explicit IORequest(ulint type) : m_block_size(UNIV_SECTOR_SIZE), - m_type(static_cast(type)), - m_compression() + m_type(static_cast(type)) { - if (is_log()) { - disable_compression(); - } - - if (!is_punch_hole_supported()) { - clear_punch_hole(); - } } /** Destructor */ @@ -435,28 +291,11 @@ public: return(ignore_missing(m_type)); } - /** @return true if punch hole should be used */ - bool punch_hole() const - MY_ATTRIBUTE((warn_unused_result)) - { - return((m_type & PUNCH_HOLE) == PUNCH_HOLE); - } - /** @return true if the read should be validated */ bool validate() const MY_ATTRIBUTE((warn_unused_result)) { - ut_a(is_read() ^ is_write()); - - return(!is_read() || !punch_hole()); - } - - /** Set the punch hole flag */ - void set_punch_hole() - { - if (is_punch_hole_supported()) { - m_type |= PUNCH_HOLE; - } + return(is_read() ^ is_write()); } /** Clear the do not wake flag */ @@ -465,12 +304,6 @@ public: m_type &= ~DO_NOT_WAKE; } - /** Clear the punch hole flag */ - void clear_punch_hole() - { - m_type &= ~PUNCH_HOLE; - } - /** @return the block size to use for IO */ ulint block_size() const MY_ATTRIBUTE((warn_unused_result)) @@ -485,14 +318,6 @@ public: m_block_size = static_cast(block_size); } - /** Clear all compression related flags */ - void clear_compressed() - { - clear_punch_hole(); - - m_compression.m_type = Compression::NONE; - } - /** Compare two requests @reutrn true if the are equal */ bool operator==(const IORequest& rhs) const @@ -500,47 +325,6 @@ public: return(m_type == rhs.m_type); } - /** Set compression algorithm - @param[in] compression The compression algorithm to use */ - void compression_algorithm(Compression::Type type) - { - if (type == Compression::NONE) { - return; - } - - set_punch_hole(); - - m_compression.m_type = type; - } - - /** Get the compression algorithm. - @return the compression algorithm */ - Compression compression_algorithm() const - MY_ATTRIBUTE((warn_unused_result)) - { - return(m_compression); - } - - /** @return true if the page should be compressed */ - bool is_compressed() const - MY_ATTRIBUTE((warn_unused_result)) - { - return(compression_algorithm().m_type != Compression::NONE); - } - - /** @return true if the page read should not be transformed. */ - bool is_compression_enabled() const - MY_ATTRIBUTE((warn_unused_result)) - { - return((m_type & NO_COMPRESSION) == 0); - } - - /** Disable transformations. */ - void disable_compression() - { - m_type |= NO_COMPRESSION; - } - /** Note that the IO is for double write recovery. */ void dblwr_recover() { @@ -554,33 +338,12 @@ public: return((m_type & DBLWR_RECOVER) == DBLWR_RECOVER); } - /** @return true if punch hole is supported */ - static bool is_punch_hole_supported() - { - - /* In this debugging mode, we act as if punch hole is supported, - and then skip any calls to actually punch a hole here. - In this way, Transparent Page Compression is still being tested. */ - DBUG_EXECUTE_IF("ignore_punch_hole", - return(true); - ); - -#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32) - return(true); -#else - return(false); -#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || _WIN32 */ - } - private: /* File system best block size */ uint32_t m_block_size; /** Request type bit flags */ uint16_t m_type; - - /** Compression algorithm */ - Compression m_compression; }; /* @} */ @@ -1659,71 +1422,11 @@ int innobase_mysql_tmpfile( const char* path); -/** If it is a compressed page return the compressed page data + footer size -@param[in] buf Buffer to check, must include header + 10 bytes -@return ULINT_UNDEFINED if the page is not a compressed page or length - of the compressed data (including footer) if it is a compressed page */ -ulint -os_file_compressed_page_size(const byte* buf); - -/** If it is a compressed page return the original page data + footer size -@param[in] buf Buffer to check, must include header + 10 bytes -@return ULINT_UNDEFINED if the page is not a compressed page or length - of the original data + footer if it is a compressed page */ -ulint -os_file_original_page_size(const byte* buf); - /** Set the file create umask @param[in] umask The umask to use for file creation. */ void os_file_set_umask(ulint umask); -/** Free storage space associated with a section of the file. -@param[in] fh Open file handle -@param[in] off Starting offset (SEEK_SET) -@param[in] len Size of the hole -@return DB_SUCCESS or error code */ -dberr_t -os_file_punch_hole( - os_file_t fh, - os_offset_t off, - os_offset_t len) - MY_ATTRIBUTE((warn_unused_result)); - -/** Check if the file system supports sparse files. - -Warning: On POSIX systems we try and punch a hole from offset 0 to -the system configured page size. This should only be called on an empty -file. - -Note: On Windows we use the name and on Unices we use the file handle. - -@param[in] name File name -@param[in] fh File handle for the file - if opened -@return true if the file system supports sparse files */ -bool -os_is_sparse_file_supported( - const char* path, - os_file_t fh) - MY_ATTRIBUTE((warn_unused_result)); - -/** Decompress the page data contents. Page type must be FIL_PAGE_COMPRESSED, if -not then the source contents are left unchanged and DB_SUCCESS is returned. -@param[in] dblwr_recover true of double write recovery in progress -@param[in,out] src Data read from disk, decompressed data will be - copied to this page -@param[in,out] dst Scratch area to use for decompression -@param[in] dst_len Size of the scratch area in bytes -@return DB_SUCCESS or error code */ - -dberr_t -os_file_decompress_page( - bool dblwr_recover, - byte* src, - byte* dst, - ulint dst_len) - MY_ATTRIBUTE((warn_unused_result)); - /** Normalizes a directory path for the current OS: On Windows, we convert '/' to '\', else we convert '\' to '/'. @param[in,out] str A null-terminated directory and file path */ diff --git a/storage/innobase/include/os0file.ic b/storage/innobase/include/os0file.ic index 74d0b2c83a8..3e78b87a177 100644 --- a/storage/innobase/include/os0file.ic +++ b/storage/innobase/include/os0file.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2010, 2015, 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 diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index f010e717103..67482db160a 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -373,9 +373,6 @@ row_create_table_for_mysql( dict_table_t* table, /*!< in, own: table definition (will be freed, or on DB_SUCCESS added to the data dictionary cache) */ - const char* compression, - /*!< in: compression algorithm to use, - can be NULL */ trx_t* trx, /*!< in/out: transaction */ bool commit, /*!< in: if true, commit the transaction */ fil_encryption_t mode, /*!< in: encryption mode */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 1e05c2c6e4a..227bcfb7781 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -731,11 +731,6 @@ enum srv_stats_method_name_enum { typedef enum srv_stats_method_name_enum srv_stats_method_name_t; -#ifdef UNIV_DEBUG -/** Force all user tables to use page compression. */ -extern ulong srv_debug_compress; -#endif /* UNIV_DEBUG */ - /** Types of threads existing in the system. */ enum srv_thread_type { SRV_NONE, /*!< None */ diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake index 15b0f7c9c9a..9cc6e434f38 100644 --- a/storage/innobase/innodb.cmake +++ b/storage/innobase/innodb.cmake @@ -1,4 +1,5 @@ # Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 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 @@ -135,24 +136,6 @@ IF(HAVE_NANOSLEEP) ADD_DEFINITIONS(-DHAVE_NANOSLEEP=1) ENDIF() -IF(NOT MSVC) - CHECK_C_SOURCE_RUNS( - " - #define _GNU_SOURCE - #include - #include - int main() - { - /* Ignore the return value for now. Check if the flags exist. - The return value is checked at runtime. */ - fallocate(0, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0, 0); - - return(0); - }" - HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE - ) -ENDIF() - IF(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) ADD_DEFINITIONS(-DHAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE=1) ENDIF() diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index e228a89b946..71a9a856571 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. +Copyright (c) 2013, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -63,11 +63,6 @@ Created 10/21/1995 Heikki Tuuri #include #endif /* LINUX_NATIVE_AIO */ -#ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE -# include -# include -#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE */ - #ifdef HAVE_LZ4 #include #endif @@ -87,11 +82,6 @@ bool innodb_calling_exit; #include #endif -#ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE -# include -# include -#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE */ - #ifdef HAVE_LZO #include "lzo/lzo1x.h" #endif @@ -109,30 +99,6 @@ static const ulint IO_LOG_SEGMENT = 1; /** Number of retries for partial I/O's */ static const ulint NUM_RETRIES_ON_PARTIAL_IO = 10; -/** Blocks for doing IO, used in the transparent compression -and encryption code. */ -struct Block { - /** Default constructor */ - Block() : m_ptr(), m_in_use() { } - - byte* m_ptr; - - byte pad[CACHE_LINE_SIZE - sizeof(ulint)]; - int32 m_in_use; -}; - -/** For storing the allocated blocks */ -typedef std::vector Blocks; - -/** Block collection */ -static Blocks* block_cache; - -/** Number of blocks to allocate for sync read/writes */ -static const size_t MAX_BLOCKS = 128; - -/** Block buffer size */ -#define BUFFER_BLOCK_SIZE ((ulint)(UNIV_PAGE_SIZE * 1.3)) - /* This specifies the file permissions InnoDB uses when it creates files in Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to my_umask */ @@ -320,18 +286,6 @@ struct Slot { /** Length of the block before it was compressed */ uint32 original_len; - /** Buffer block for compressed pages or encrypted pages */ - Block* buf_block; - - /** Unaligned buffer for compressed pages */ - byte* compressed_ptr; - - /** Compressed data page, aligned and derived from compressed_ptr */ - byte* compressed_page; - - /** true, if we shouldn't punch a hole after writing the page */ - bool skip_punch_hole; - ulint* write_size; }; @@ -839,140 +793,12 @@ os_aio_windows_handler( IORequest* type); #endif /* WIN_ASYNC_IO */ -#ifdef MYSQL_COMPRESSION -/** Allocate a page for sync IO -@return pointer to page */ -static -Block* -os_alloc_block() -{ - size_t pos; - Blocks& blocks = *block_cache; - size_t i = static_cast(my_timer_cycles()); - const size_t size = blocks.size(); - ulint retry = 0; - Block* block; - - DBUG_EXECUTE_IF("os_block_cache_busy", retry = MAX_BLOCKS * 3;); - - for (;;) { - - /* After go through the block cache for 3 times, - allocate a new temporary block. */ - if (retry == MAX_BLOCKS * 3) { - byte* ptr; - - ptr = static_cast( - ut_malloc_nokey(sizeof(*block) - + BUFFER_BLOCK_SIZE)); - - block = new (ptr) Block(); - block->m_ptr = static_cast( - ptr + sizeof(*block)); - block->m_in_use = 1; - - break; - } - - pos = i++ % size; - - if (my_atomic_fas32_explicit(&blocks[pos].m_in_use, 1, - MY_MEMORY_ORDER_ACQUIRE) == 0) { - block = &blocks[pos]; - break; - } - - os_thread_yield(); - - ++retry; - } - - ut_a(block->m_in_use != 0); - - return(block); -} - -/** Free a page after sync IO -@param[in,own] block The block to free/release */ -static -void -os_free_block(Block* block) -{ - ut_ad(block->m_in_use == 1); - - my_atomic_store32_explicit(&block->m_in_use, 0, MY_MEMORY_ORDER_RELEASE); - - /* When this block is not in the block cache, and it's - a temporary block, we need to free it directly. */ - if (std::less()(block, &block_cache->front()) - || std::greater()(block, &block_cache->back())) { - ut_free(block); - } -} -#endif /* MYSQL_COMPRESSION */ - /** Generic AIO Handler methods. Currently handles IO post processing. */ class AIOHandler { public: /** Do any post processing after a read/write @return DB_SUCCESS or error code. */ static dberr_t post_io_processing(Slot* slot); - -private: - /** Check whether the page was compressed. - @param[in] slot The slot that contains the IO request - @return true if it was a compressed page */ - static bool is_compressed_page(const Slot* slot) - { - const byte* src = slot->buf; - - ulint page_type = mach_read_from_2(src + FIL_PAGE_TYPE); - - return(page_type == FIL_PAGE_COMPRESSED); - } - - /** Get the compressed page size. - @param[in] slot The slot that contains the IO request - @return number of bytes to read for a successful decompress */ - static ulint compressed_page_size(const Slot* slot) - { - ut_ad(slot->type.is_read()); - ut_ad(is_compressed_page(slot)); - - ulint size; - const byte* src = slot->buf; - - size = mach_read_from_2(src + FIL_PAGE_COMPRESS_SIZE_V1); - - return(size + FIL_PAGE_DATA); - } - - /** Check if the page contents can be decompressed. - @param[in] slot The slot that contains the IO request - @return true if the data read has all the compressed data */ - static bool can_decompress(const Slot* slot) - { - ut_ad(slot->type.is_read()); - ut_ad(is_compressed_page(slot)); - - ulint version; - const byte* src = slot->buf; - - version = mach_read_from_1(src + FIL_PAGE_VERSION); - - ut_a(version == 1); - - /* Includes the page header size too */ - ulint size = compressed_page_size(slot); - - return(size <= (slot->ptr - slot->buf) + (ulint) slot->n_bytes); - } - - /** Check if we need to read some more data. - @param[in] slot The slot that contains the IO request - @param[in] n_bytes Total bytes read so far - @return DB_SUCCESS or error code */ - static dberr_t check_read(Slot* slot, ulint n_bytes); }; /** Helper class for doing synchronous file IO. Currently, the objective @@ -1038,152 +864,17 @@ private: os_offset_t m_offset; }; -/** If it is a compressed page return the compressed page data + footer size -@param[in] buf Buffer to check, must include header + 10 bytes -@return ULINT_UNDEFINED if the page is not a compressed page or length - of the compressed data (including footer) if it is a compressed page */ -ulint -os_file_compressed_page_size(const byte* buf) -{ - ulint type = mach_read_from_2(buf + FIL_PAGE_TYPE); - - if (type == FIL_PAGE_COMPRESSED) { - ulint version = mach_read_from_1(buf + FIL_PAGE_VERSION); - ut_a(version == 1); - return(mach_read_from_2(buf + FIL_PAGE_COMPRESS_SIZE_V1)); - } - - return(ULINT_UNDEFINED); -} - -/** If it is a compressed page return the original page data + footer size -@param[in] buf Buffer to check, must include header + 10 bytes -@return ULINT_UNDEFINED if the page is not a compressed page or length - of the original data + footer if it is a compressed page */ -ulint -os_file_original_page_size(const byte* buf) -{ - ulint type = mach_read_from_2(buf + FIL_PAGE_TYPE); - - if (type == FIL_PAGE_COMPRESSED) { - - ulint version = mach_read_from_1(buf + FIL_PAGE_VERSION); - ut_a(version == 1); - - return(mach_read_from_2(buf + FIL_PAGE_ORIGINAL_SIZE_V1)); - } - - return(ULINT_UNDEFINED); -} - -/** Check if we need to read some more data. -@param[in] slot The slot that contains the IO request -@param[in] n_bytes Total bytes read so far -@return DB_SUCCESS or error code */ -dberr_t -AIOHandler::check_read(Slot* slot, ulint n_bytes) -{ - dberr_t err=DB_SUCCESS; - - ut_ad(slot->type.is_read()); - ut_ad(slot->original_len > slot->len); - - if (is_compressed_page(slot)) { - - if (can_decompress(slot)) { - - ut_a(slot->offset > 0); - - slot->len = slot->original_len; -#ifdef _WIN32 - slot->n_bytes = static_cast(n_bytes); -#else - slot->n_bytes = static_cast(n_bytes); -#endif /* _WIN32 */ - } else { - /* Read the next block in */ - ut_ad(compressed_page_size(slot) >= n_bytes); - - err = DB_FAIL; - } - } else { - err = DB_FAIL; - } - -#ifdef MYSQL_COMPRESSION - if (slot->buf_block != NULL) { - os_free_block(slot->buf_block); - slot->buf_block = NULL; - } -#endif - return(err); -} - /** Do any post processing after a read/write @return DB_SUCCESS or error code. */ dberr_t AIOHandler::post_io_processing(Slot* slot) { - dberr_t err=DB_SUCCESS; - ut_ad(slot->is_reserved); /* Total bytes read so far */ ulint n_bytes = (slot->ptr - slot->buf) + slot->n_bytes; - /* Compressed writes can be smaller than the original length. - Therefore they can be processed without further IO. */ - if (n_bytes == slot->original_len - || (slot->type.is_write() - && slot->type.is_compressed() - && slot->len == static_cast(slot->n_bytes))) { - -#ifdef MYSQL_COMPRESSION - if (!slot->type.is_log() && is_compressed_page(slot)) { - - ut_a(slot->offset > 0); - - if (slot->type.is_read()) { - slot->len = slot->original_len; - } - - /* The punch hole has been done on collect() */ - - if (slot->type.is_read()) { - err = io_complete(slot); - } else { - err = DB_SUCCESS; - } - - ut_ad(err == DB_SUCCESS - || err == DB_UNSUPPORTED - || err == DB_CORRUPTION - || err == DB_IO_DECOMPRESS_FAIL); - } else { - - err = DB_SUCCESS; - } - - if (slot->buf_block != NULL) { - os_free_block(slot->buf_block); - slot->buf_block = NULL; - } -#endif /* MYSQL_COMPRESSION */ - } else if ((ulint) slot->n_bytes == (ulint) slot->len) { - - /* It *must* be a partial read. */ - ut_ad(slot->len < slot->original_len); - - /* Has to be a read request, if it is less than - the original length. */ - ut_ad(slot->type.is_read()); - err = check_read(slot, n_bytes); - - } else { - err = DB_FAIL; - } - - return(err); + return(n_bytes == slot->original_len ? DB_SUCCESS : DB_FAIL); } /** Count the number of free slots @@ -1219,155 +910,6 @@ AIO::pending_io_count() const return(reserved); } -#ifdef MYSQL_COMPRESSION -/** Compress a data page -#param[in] block_size File system block size -@param[in] src Source contents to compress -@param[in] src_len Length in bytes of the source -@param[out] dst Compressed page contents -@param[out] dst_len Length in bytes of dst contents -@return buffer data, dst_len will have the length of the data */ -static -byte* -os_file_compress_page( - Compression compression, - ulint block_size, - byte* src, - ulint src_len, - byte* dst, - ulint* dst_len) -{ - ulint len = 0; - ulint compression_level = page_zip_level; - ulint page_type = mach_read_from_2(src + FIL_PAGE_TYPE); - - /* The page size must be a multiple of the OS punch hole size. */ - ut_ad(!(src_len % block_size)); - - /* Shouldn't compress an already compressed page. */ - ut_ad(page_type != FIL_PAGE_COMPRESSED); - - /* The page must be at least twice as large as the file system - block size if we are to save any space. Ignore R-Tree pages for now, - they repurpose the same 8 bytes in the page header. No point in - compressing if the file system block size >= our page size. */ - - if (page_type == FIL_PAGE_RTREE - || block_size == ULINT_UNDEFINED - || compression.m_type == Compression::NONE - || src_len < block_size * 2) { - - *dst_len = src_len; - - return(src); - } - - /* Leave the header alone when compressing. */ - ut_ad(block_size >= FIL_PAGE_DATA * 2); - - ut_ad(src_len > FIL_PAGE_DATA + block_size); - - /* Must compress to <= N-1 FS blocks. */ - ulint out_len = src_len - (FIL_PAGE_DATA + block_size); - - /* This is the original data page size - the page header. */ - ulint content_len = src_len - FIL_PAGE_DATA; - - ut_ad(out_len >= block_size - FIL_PAGE_DATA); - ut_ad(out_len <= src_len - (block_size + FIL_PAGE_DATA)); - - /* Only compress the data + trailer, leave the header alone */ - - switch (compression.m_type) { - case Compression::NONE: - ut_error; - - case Compression::ZLIB: { - - uLongf zlen = static_cast(out_len); - - if (compress2( - dst + FIL_PAGE_DATA, - &zlen, - src + FIL_PAGE_DATA, - static_cast(content_len), - static_cast(compression_level)) != Z_OK) { - - *dst_len = src_len; - - return(src); - } - - len = static_cast(zlen); - - break; - } - -#ifdef HAVE_LZ4 - case Compression::LZ4: - - len = LZ4_compress_limitedOutput( - reinterpret_cast(src) + FIL_PAGE_DATA, - reinterpret_cast(dst) + FIL_PAGE_DATA, - static_cast(content_len), - static_cast(out_len)); - - ut_a(len <= src_len - FIL_PAGE_DATA); - - if (len == 0 || len >= out_len) { - - *dst_len = src_len; - - return(src); - } - - break; -#endif - - default: - *dst_len = src_len; - return(src); - } - - ut_a(len <= out_len); - - ut_ad(memcmp(src + FIL_PAGE_LSN + 4, - src + src_len - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4) - == 0); - - /* Copy the header as is. */ - memmove(dst, src, FIL_PAGE_DATA); - - /* Add compression control information. Required for decompressing. */ - mach_write_to_2(dst + FIL_PAGE_TYPE, FIL_PAGE_COMPRESSED); - - mach_write_to_1(dst + FIL_PAGE_VERSION, 1); - - mach_write_to_1(dst + FIL_PAGE_ALGORITHM_V1, compression.m_type); - - mach_write_to_2(dst + FIL_PAGE_ORIGINAL_TYPE_V1, page_type); - - mach_write_to_2(dst + FIL_PAGE_ORIGINAL_SIZE_V1, content_len); - - mach_write_to_2(dst + FIL_PAGE_COMPRESS_SIZE_V1, len); - - /* Round to the next full block size */ - - len += FIL_PAGE_DATA; - - *dst_len = ut_calc_align(len, block_size); - - ut_ad(*dst_len >= len && *dst_len <= out_len + FIL_PAGE_DATA); - - /* Clear out the unused portion of the page. */ - if (len % block_size) { - memset(dst + len, 0x0, block_size - (len % block_size)); - } - - return(dst); -} -#endif /* MYSQL_COMPRESSION */ - #ifdef UNIV_DEBUG /** Validates the consistency the aio system some of the time. @return true if ok or the check was skipped */ @@ -1882,87 +1424,6 @@ os_file_create_subdirs_if_needed( return(success ? DB_SUCCESS : DB_ERROR); } -#ifdef MYSQL_COMPRESSION -/** Allocate the buffer for IO on a transparently compressed table. -@param[in] type IO flags -@param[out] buf buffer to read or write -@param[in,out] n number of bytes to read/write, starting from - offset -@return pointer to allocated page, compressed data is written to the offset - that is aligned on UNIV_SECTOR_SIZE of Block.m_ptr */ -static -Block* -os_file_compress_page( - IORequest& type, - void*& buf, - ulint* n) -{ - ut_ad(!type.is_log()); - ut_ad(type.is_write()); - ut_ad(type.is_compressed()); - - ulint n_alloc = *n * 2; - - ut_a(n_alloc <= UNIV_PAGE_SIZE_MAX * 2); -#ifdef HAVE_LZ4 - ut_a(type.compression_algorithm().m_type != Compression::LZ4 - || static_cast(LZ4_COMPRESSBOUND(*n)) < n_alloc); -#endif - - Block* ptr = reinterpret_cast(ut_malloc_nokey(n_alloc)); - - if (ptr == NULL) { - return(NULL); - } - - ulint old_compressed_len; - ulint compressed_len = *n; - - old_compressed_len = mach_read_from_2( - reinterpret_cast(buf) - + FIL_PAGE_COMPRESS_SIZE_V1); - - if (old_compressed_len > 0) { - old_compressed_len = ut_calc_align( - old_compressed_len + FIL_PAGE_DATA, - type.block_size()); - } - - byte* compressed_page; - - compressed_page = static_cast( - ut_align(block->m_ptr, UNIV_SECTOR_SIZE)); - - byte* buf_ptr; - - buf_ptr = os_file_compress_page( - type.compression_algorithm(), - type.block_size(), - reinterpret_cast(buf), - *n, - compressed_page, - &compressed_len); - - if (buf_ptr != buf) { - /* Set new compressed size to uncompressed page. */ - memcpy(reinterpret_cast(buf) + FIL_PAGE_COMPRESS_SIZE_V1, - buf_ptr + FIL_PAGE_COMPRESS_SIZE_V1, 2); - - buf = buf_ptr; - *n = compressed_len; - - if (compressed_len >= old_compressed_len) { - - ut_ad(old_compressed_len <= UNIV_PAGE_SIZE); - - type.clear_punch_hole(); - } - } - - return(block); -} -#endif /* MYSQL_COMPRESSION */ - #ifndef _WIN32 /** Do the read/write @@ -1983,51 +1444,6 @@ SyncFileIO::execute(const IORequest& request) return(n_bytes); } -/** Free storage space associated with a section of the file. -@param[in] fh Open file handle -@param[in] off Starting offset (SEEK_SET) -@param[in] len Size of the hole -@return DB_SUCCESS or error code */ -static -dberr_t -os_file_punch_hole_posix( - os_file_t fh, - os_offset_t off, - os_offset_t len) -{ - -#ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE - const int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; - - int ret = fallocate(fh, mode, off, len); - - if (ret == 0) { - return(DB_SUCCESS); - } - - ut_a(ret == -1); - - if (errno == ENOTSUP) { - return(DB_IO_NO_PUNCH_HOLE); - } - - ib::warn() - << "fallocate(" << fh - <<", FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, " - << off << ", " << len << ") returned errno: " - << errno; - - return(DB_IO_ERROR); - -#elif defined(UNIV_SOLARIS) - - // Use F_FREESP - -#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE */ - - return(DB_IO_NO_PUNCH_HOLE); -} - #if defined(LINUX_NATIVE_AIO) /** Linux native AIO handler */ @@ -2318,20 +1734,7 @@ LinuxAIOHandler::collect() /* We have not overstepped to next segment. */ ut_a(slot->pos < end_pos); - /* We never compress/decompress the first page */ - - if (slot->offset > 0 - && !slot->skip_punch_hole - && slot->type.is_compression_enabled() - && !slot->type.is_log() - && slot->type.is_write() - && slot->type.is_compressed() - && slot->type.punch_hole()) { - - slot->err = AIOHandler::io_complete(slot); - } else { - slot->err = DB_SUCCESS; - } + slot->err = DB_SUCCESS; /* Mark this request as completed. The error handling will be done in the calling function. */ @@ -2497,16 +1900,7 @@ os_aio_linux_handler( void** m2, IORequest* request) { - LinuxAIOHandler handler(global_segment); - - dberr_t err = handler.poll(m1, m2, request); - - if (err == DB_IO_NO_PUNCH_HOLE) { - fil_no_punch_hole(*m1); - err = DB_SUCCESS; - } - - return(err); + return LinuxAIOHandler(global_segment).poll(m1, m2, request); } /** Dispatch an AIO request to the kernel. @@ -3959,66 +3353,6 @@ struct WinIoInit /* Ensures proper initialization and shutdown */ static WinIoInit win_io_init; -/** Check if the file system supports sparse files. -@param[in] name File name -@return true if the file system supports sparse files */ -static -bool -os_is_sparse_file_supported_win32(const char* filename) -{ - char volname[MAX_PATH]; - BOOL result = GetVolumePathName(filename, volname, MAX_PATH); - - if (!result) { - - ib::error() - << "os_is_sparse_file_supported: " - << "Failed to get the volume path name for: " - << filename - << "- OS error number " << GetLastError(); - - return(false); - } - - DWORD flags; - - GetVolumeInformation( - volname, NULL, MAX_PATH, NULL, NULL, - &flags, NULL, MAX_PATH); - - return(flags & FILE_SUPPORTS_SPARSE_FILES) ? true : false; -} - -/** Free storage space associated with a section of the file. -@param[in] fh Open file handle -@param[in] page_size Tablespace page size -@param[in] block_size File system block size -@param[in] off Starting offset (SEEK_SET) -@param[in] len Size of the hole -@return 0 on success or errno */ -static -dberr_t -os_file_punch_hole_win32( - os_file_t fh, - os_offset_t off, - os_offset_t len) -{ - FILE_ZERO_DATA_INFORMATION punch; - - punch.FileOffset.QuadPart = off; - punch.BeyondFinalZero.QuadPart = off + len; - - /* If lpOverlapped is NULL, lpBytesReturned cannot be NULL, - therefore we pass a dummy parameter. */ - DWORD temp; - - BOOL result = DeviceIoControl( - fh, FSCTL_SET_ZERO_DATA, &punch, sizeof(punch), - NULL, 0, &temp, NULL); - - return(!result ? DB_IO_NO_PUNCH_HOLE : DB_SUCCESS); -} - /** Check the existence and type of the given file. @param[in] path path name of file @param[out] exists true if the file exists @@ -5243,30 +4577,6 @@ AIO::simulated_put_read_threads_to_sleep() #endif /* !_WIN32*/ -#ifdef MYSQL_COMPRESSION -/** Validate the type, offset and number of bytes to read * -@param[in] type IO flags -@param[in] offset Offset from start of the file -@param[in] n Number of bytes to read from offset */ -static -void -os_file_check_args(const IORequest& type, os_offset_t offset, ulint n) -{ - ut_ad(type.validate()); - - ut_ad(n > 0); - - /* If off_t is > 4 bytes in size, then we assume we can pass a - 64-bit address */ - off_t offs = static_cast(offset); - - if (sizeof(off_t) <= 4 && offset != (os_offset_t) offs) { - - ib::error() << "file write at offset > 4 GB."; - } -} -#endif /* MYSQL_COMPRESSION */ - /** Does a syncronous read or write depending upon the type specified In case of partial reads/writes the function tries NUM_RETRIES_ON_PARTIAL_IO times to read/write the complete data. @@ -5289,27 +4599,8 @@ os_file_io( { ulint original_n = n; IORequest type = in_type; - byte* compressed_page=NULL; ssize_t bytes_returned = 0; -#ifdef MYSQL_COMPRESSION - Block* block=NULL; - if (type.is_compressed()) { - - /* We don't compress the first page of any file. */ - ut_ad(offset > 0); - - block = os_file_compress_page(type, buf, &n); - - compressed_page = static_cast( - ut_align(block->m_ptr, UNIV_SECTOR_SIZE)); - - } else { - block = NULL; - compressed_page = NULL; - } -#endif /* MYSQL_COMPRESSION */ - SyncFileIO sync_file_io(file, buf, n, offset); for (ulint i = 0; i < NUM_RETRIES_ON_PARTIAL_IO; ++i) { @@ -5325,11 +4616,6 @@ os_file_io( bytes_returned += n_bytes; *err = DB_SUCCESS; -#ifdef MYSQL_COMPRESSION - if (block != NULL) { - os_free_block(block); - } -#endif return(original_n); } @@ -5357,12 +4643,6 @@ os_file_io( sync_file_io.advance(n_bytes); } -#ifdef MYSQL_COMPRESSION - if (block != NULL) { - os_free_block(block); - } -#endif - *err = DB_IO_ERROR; if (!type.is_partial_io_warning_disabled()) { @@ -5388,7 +4668,7 @@ ssize_t os_file_pwrite( IORequest& type, os_file_t file, - const byte* buf, + const void* buf, ulint n, os_offset_t offset, dberr_t* err) @@ -5400,7 +4680,8 @@ os_file_pwrite( (void) my_atomic_addlint(&os_n_pending_writes, 1); MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_WRITES); - ssize_t n_bytes = os_file_io(type, file, (void*) buf, n, offset, err); + ssize_t n_bytes = os_file_io(type, file, const_cast(buf), + n, offset, err); (void) my_atomic_addlint(&os_n_pending_writes, -1); MONITOR_ATOMIC_DEC(MONITOR_OS_PENDING_WRITES); @@ -5415,21 +4696,21 @@ os_file_pwrite( @param[in] offset file offset from the start where to read @param[in] n number of bytes to read, starting from offset @return DB_SUCCESS if request was successful, false if fail */ -static MY_ATTRIBUTE((warn_unused_result)) dberr_t -os_file_write_page( +os_file_write_func( IORequest& type, const char* name, os_file_t file, - const byte* buf, + const void* buf, os_offset_t offset, ulint n) { dberr_t err; + ut_ad(type.is_write()); ut_ad(type.validate()); ut_ad(n > 0); - + ssize_t n_bytes = os_file_pwrite(type, file, buf, n, offset, &err); if ((ulint) n_bytes != n && !os_has_said_disk_full) { @@ -5533,23 +4814,7 @@ os_file_read_page( return(err); } else if ((ulint) n_bytes == n) { - -#ifdef MYSQL_COMPRESSION - /** The read will succeed but decompress can fail - for various reasons. */ - - if (type.is_compression_enabled() - && !Compression::is_compressed_page( - static_cast(buf))) { - - return(DB_SUCCESS); - - } else { - return(err); - } -#else return(DB_SUCCESS); -#endif /* MYSQL_COMPRESSION */ } ib::error() << "Tried to read " << n @@ -5930,37 +5195,6 @@ os_file_read_no_error_handling_func( return(os_file_read_page(type, file, buf, offset, n, o, false)); } -/** NOTE! Use the corresponding macro os_file_write(), not directly -Requests a synchronous write operation. -@param[in] type IO flags -@param[in] file handle to an open file -@param[out] buf buffer from which to write -@param[in] offset file offset from the start where to read -@param[in] n number of bytes to read, starting from offset -@return DB_SUCCESS if request was successful, false if fail */ -dberr_t -os_file_write_func( - IORequest& type, - const char* name, - os_file_t file, - const void* buf, - os_offset_t offset, - ulint n) -{ - ut_ad(type.validate()); - ut_ad(type.is_write()); - - /* We never compress the first page. - Note: This assumes we always do block IO. */ - if (offset == 0) { - type.clear_compressed(); - } - - const byte* ptr = reinterpret_cast(buf); - - return(os_file_write_page(type, name, file, ptr, offset, n)); -} - /** Check the existence and type of the given file. @param[in] path path name of file @param[out] exists true if the file exists @@ -5979,65 +5213,6 @@ os_file_status( #endif /* _WIN32 */ } -/** Free storage space associated with a section of the file. -@param[in] fh Open file handle -@param[in] off Starting offset (SEEK_SET) -@param[in] len Size of the hole -@return DB_SUCCESS or error code */ -dberr_t -os_file_punch_hole( - os_file_t fh, - os_offset_t off, - os_offset_t len) -{ - /* In this debugging mode, we act as if punch hole is supported, - and then skip any calls to actually punch a hole here. - In this way, Transparent Page Compression is still being tested. */ - DBUG_EXECUTE_IF("ignore_punch_hole", - return(DB_SUCCESS); - ); - -#ifdef _WIN32 - return(os_file_punch_hole_win32(fh, off, len)); -#else - return(os_file_punch_hole_posix(fh, off, len)); -#endif /* _WIN32 */ -} - -/** Check if the file system supports sparse files. - -Warning: On POSIX systems we try and punch a hole from offset 0 to -the system configured page size. This should only be called on an empty -file. - -Note: On Windows we use the name and on Unices we use the file handle. - -@param[in] name File name -@param[in] fh File handle for the file - if opened -@return true if the file system supports sparse files */ -bool -os_is_sparse_file_supported(const char* path, os_file_t fh) -{ - /* In this debugging mode, we act as if punch hole is supported, - then we skip any calls to actually punch a hole. In this way, - Transparent Page Compression is still being tested. */ - DBUG_EXECUTE_IF("ignore_punch_hole", - return(true); - ); - -#ifdef _WIN32 - return(os_is_sparse_file_supported_win32(path)); -#else - dberr_t err; - - /* We don't know the FS block size, use the sector size. The FS - will do the magic. */ - err = os_file_punch_hole(fh, 0, UNIV_PAGE_SIZE); - - return(err == DB_SUCCESS); -#endif /* _WIN32 */ -} - /** This function returns information about the specified file @param[in] path pathname of the file @param[out] stat_info information of a file in a directory @@ -6192,16 +5367,6 @@ AIO::init_slots() memset(&slot.control, 0x0, sizeof(slot.control)); #endif /* WIN_ASYNC_IO */ - - slot.compressed_ptr = reinterpret_cast( - ut_zalloc_nokey(UNIV_PAGE_SIZE_MAX * 2)); - - if (slot.compressed_ptr == NULL) { - return(DB_OUT_OF_MEMORY); - } - - slot.compressed_page = static_cast( - ut_align(slot.compressed_ptr, UNIV_PAGE_SIZE)); } return(DB_SUCCESS); @@ -6328,16 +5493,6 @@ AIO::~AIO() } #endif /* LINUX_NATIVE_AIO */ - for (ulint i = 0; i < m_slots.size(); ++i) { - Slot& slot = m_slots[i]; - - if (slot.compressed_ptr != NULL) { - ut_free(slot.compressed_ptr); - slot.compressed_ptr = NULL; - slot.compressed_page = NULL; - } - } - m_slots.clear(); } @@ -6499,27 +5654,6 @@ os_aio_init( /* Maximum number of pending aio operations allowed per segment */ ulint limit = 8 * OS_AIO_N_PENDING_IOS_PER_THREAD; - - ut_a(block_cache == NULL); - - block_cache = UT_NEW_NOKEY(Blocks(MAX_BLOCKS)); - - for (Blocks::iterator it = block_cache->begin(); - it != block_cache->end(); - ++it) { - - ut_a(it->m_in_use == 0); - ut_a(it->m_ptr == NULL); - - /* Allocate double of max page size memory, since - compress could generate more bytes than orgininal - data. */ - it->m_ptr = static_cast( - ut_malloc_nokey(BUFFER_BLOCK_SIZE)); - - ut_a(it->m_ptr != NULL); - } - return(AIO::start(limit, n_readers, n_writers, n_slots_sync)); } @@ -6536,18 +5670,6 @@ os_aio_free() ut_free(os_aio_segment_wait_events); os_aio_segment_wait_events = 0; os_aio_n_segments = 0; - - for (Blocks::iterator it = block_cache->begin(); - it != block_cache->end(); - ++it) { - - ut_a(it->m_in_use == 0); - ut_free(it->m_ptr); - } - - UT_DELETE(block_cache); - - block_cache = NULL; } /** Wakes up all async i/o threads so that they know to exit themselves in @@ -6753,40 +5875,8 @@ AIO::reserve_slot( slot->is_log = type.is_log(); slot->original_len = static_cast(len); slot->io_already_done = false; - slot->buf_block = NULL; slot->buf = static_cast(buf); -#ifdef MYSQL_COMPRESSION - if (srv_use_native_aio - && offset > 0 - && type.is_write() - && type.is_compressed()) { - ulint compressed_len = len; - - ut_ad(!type.is_log()); - - release(); - - void* src_buf = slot->buf; - - slot->buf_block = os_file_compress_page( - type, - src_buf, - &compressed_len); - - slot->buf = static_cast(src_buf); - slot->ptr = slot->buf; -#ifdef _WIN32 - slot->len = static_cast(compressed_len); -#else - slot->len = static_cast(compressed_len); -#endif /* _WIN32 */ - slot->skip_punch_hole = type.punch_hole(); - - acquire(); - } -#endif /* MYSQL_COMPRESSION */ - #ifdef WIN_ASYNC_IO { OVERLAPPED* control; @@ -7506,7 +6596,7 @@ private: slot->offset, slot->len); - ut_a(err == DB_SUCCESS || err == DB_IO_NO_PUNCH_HOLE); + ut_a(err == DB_SUCCESS); } /** @return true if the slots are adjacent and can be merged */ @@ -8134,292 +7224,9 @@ os_file_set_umask(ulint umask) } #else - #include "univ.i" -#include "db0err.h" -#include "mach0data.h" -#include "fil0fil.h" -#include "os0file.h" - -#ifdef HAVE_LZ4 -#include -#endif - -#include -#ifndef UNIV_INNOCHECKSUM -#include -#include -#include -#include -#endif - -typedef byte Block; - -#ifdef MYSQL_COMPRESSION -/** Allocate a page for sync IO -@return pointer to page */ -static -Block* -os_alloc_block() -{ - return(reinterpret_cast(malloc(UNIV_PAGE_SIZE_MAX * 2))); -} - -/** Free a page after sync IO -@param[in,own] block The block to free/release */ -static -void -os_free_block(Block* block) -{ - ut_free(block); -} -#endif #endif /* !UNIV_INNOCHECKSUM */ -#ifdef MYSQL_COMPRESSION - -/** -@param[in] type The compression type -@return the string representation */ -const char* -Compression::to_string(Type type) -{ - switch(type) { - case NONE: - return("None"); - case ZLIB: - return("Zlib"); - case LZ4: - return("LZ4"); - } - - ut_ad(0); - - return(""); -} - -/** -@param[in] meta Page Meta data -@return the string representation */ -std::string Compression::to_string(const Compression::meta_t& meta) -{ - std::ostringstream stream; - - stream << "version: " << int(meta.m_version) << " " - << "algorithm: " << meta.m_algorithm << " " - << "(" << to_string(meta.m_algorithm) << ") " - << "orginal_type: " << meta.m_original_type << " " - << "original_size: " << meta.m_original_size << " " - << "compressed_size: " << meta.m_compressed_size; - - return(stream.str()); -} - -/** @return true if it is a compressed page */ -bool -Compression::is_compressed_page(const byte* page) -{ - return(mach_read_from_2(page + FIL_PAGE_TYPE) == FIL_PAGE_COMPRESSED); -} - -/** Deserizlise the page header compression meta-data -@param[in] page Pointer to the page header -@param[out] control Deserialised data */ -void -Compression::deserialize_header( - const byte* page, - Compression::meta_t* control) -{ - ut_ad(is_compressed_page(page)); - - control->m_version = static_cast( - mach_read_from_1(page + FIL_PAGE_VERSION)); - - control->m_original_type = static_cast( - mach_read_from_2(page + FIL_PAGE_ORIGINAL_TYPE_V1)); - - control->m_compressed_size = static_cast( - mach_read_from_2(page + FIL_PAGE_COMPRESS_SIZE_V1)); - - control->m_original_size = static_cast( - mach_read_from_2(page + FIL_PAGE_ORIGINAL_SIZE_V1)); - - control->m_algorithm = static_cast( - mach_read_from_1(page + FIL_PAGE_ALGORITHM_V1)); -} - -/** Decompress the page data contents. Page type must be FIL_PAGE_COMPRESSED, if -not then the source contents are left unchanged and DB_SUCCESS is returned. -@param[in] dblwr_recover true of double write recovery in progress -@param[in,out] src Data read from disk, decompressed data will be - copied to this page -@param[in,out] dst Scratch area to use for decompression -@param[in] dst_len Size of the scratch area in bytes -@return DB_SUCCESS or error code */ -dberr_t -Compression::deserialize( - bool dblwr_recover, - byte* src, - byte* dst, - ulint dst_len) -{ - if (!is_compressed_page(src)) { - /* There is nothing we can do. */ - return(DB_SUCCESS); - } - - meta_t header; - - deserialize_header(src, &header); - - byte* ptr = src + FIL_PAGE_DATA; - - ut_ad(header.m_version == 1); - - if (header.m_version != 1 - || header.m_original_size < UNIV_PAGE_SIZE_MIN - (FIL_PAGE_DATA + 8) - || header.m_original_size > UNIV_PAGE_SIZE_MAX - FIL_PAGE_DATA - || dst_len < header.m_original_size + FIL_PAGE_DATA) { - - /* The last check could potentially return DB_OVERFLOW, - the caller should be able to retry with a larger buffer. */ - - return(DB_CORRUPTION); - } - - Block* block; - - /* The caller doesn't know what to expect */ - if (dst == NULL) { - - block = os_alloc_block(); - -#ifdef UNIV_INNOCHECKSUM - dst = block; -#else - dst = block->m_ptr; -#endif /* UNIV_INNOCHECKSUM */ - - } else { - block = NULL; - } - - int ret; - Compression compression; - ulint len = header.m_original_size; - - compression.m_type = static_cast(header.m_algorithm); - - switch(compression.m_type) { - case Compression::ZLIB: { - - uLongf zlen = header.m_original_size; - - if (uncompress(dst, &zlen, ptr, header.m_compressed_size) - != Z_OK) { - - if (block != NULL) { - os_free_block(block); - } - - return(DB_IO_DECOMPRESS_FAIL); - } - - len = static_cast(zlen); - - break; - } -#ifdef HAVE_LZ4 - case Compression::LZ4: { - int ret; - - if (dblwr_recover) { - - ret = LZ4_decompress_safe( - reinterpret_cast(ptr), - reinterpret_cast(dst), - header.m_compressed_size, - header.m_original_size); - - } else { - - /* This can potentially read beyond the input - buffer if the data is malformed. According to - the LZ4 documentation it is a little faster - than the above function. When recovering from - the double write buffer we can afford to us the - slower function above. */ - - ret = LZ4_decompress_fast( - reinterpret_cast(ptr), - reinterpret_cast(dst), - header.m_original_size); - } - - if (ret < 0) { - - if (block != NULL) { - os_free_block(block); - } - - return(DB_IO_DECOMPRESS_FAIL); - } - - break; - } -#endif - default: -#if !defined(UNIV_INNOCHECKSUM) - ib::error() - << "Compression algorithm support missing: " - << Compression::to_string(compression.m_type); -#else - fprintf(stderr, "Compression algorithm support missing: %s\n", - Compression::to_string(compression.m_type)); -#endif /* !UNIV_INNOCHECKSUM */ - - if (block != NULL) { - os_free_block(block); - } - - return(DB_UNSUPPORTED); - } - /* Leave the header alone */ - memmove(src + FIL_PAGE_DATA, dst, len); - - mach_write_to_2(src + FIL_PAGE_TYPE, header.m_original_type); - - ut_ad(dblwr_recover - || memcmp(src + FIL_PAGE_LSN + 4, - src + (header.m_original_size + FIL_PAGE_DATA) - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4) == 0); - - if (block != NULL) { - os_free_block(block); - } - - return(DB_SUCCESS); -} - -/** Decompress the page data contents. Page type must be FIL_PAGE_COMPRESSED, if -not then the source contents are left unchanged and DB_SUCCESS is returned. -@param[in] dblwr_recover true of double write recovery in progress -@param[in,out] src Data read from disk, decompressed data will be - copied to this page -@param[in,out] dst Scratch area to use for decompression -@param[in] dst_len Size of the scratch area in bytes -@return DB_SUCCESS or error code */ -dberr_t -os_file_decompress_page( - bool dblwr_recover, - byte* src, - byte* dst, - ulint dst_len) -{ - return(Compression::deserialize(dblwr_recover, src, dst, dst_len)); -} -#endif /* MYSQL_COMPRESSION */ - /** Normalizes a directory path for the current OS: On Windows, we convert '/' to '\', else we convert '\' to '/'. @param[in,out] str A null-terminated directory and file path */ diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index a5cd0064ddd..fbcb6149add 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1182,9 +1182,6 @@ row_merge_read( IORequest request; - /* Merge sort pages are never compressed. */ - request.disable_compression(); - dberr_t err = os_file_read_no_error_handling( request, OS_FILE_FROM_FD(fd), buf, ofs, srv_sort_buf_size, NULL); @@ -1239,8 +1236,6 @@ row_merge_write( mach_write_to_4((byte *)out_buf, 0); } - request.disable_compression(); - dberr_t err = os_file_write( request, "(merge)", OS_FILE_FROM_FD(fd), out_buf, ofs, buf_len); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 0c3a4e6bdae..21bcd381c87 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2420,9 +2420,6 @@ row_create_table_for_mysql( dict_table_t* table, /*!< in, own: table definition (will be freed, or on DB_SUCCESS added to the data dictionary cache) */ - const char* compression, - /*!< in: compression algorithm to use, - can be NULL */ trx_t* trx, /*!< in/out: transaction */ bool commit, /*!< in: if true, commit the transaction */ fil_encryption_t mode, /*!< in: encryption mode */ @@ -2510,46 +2507,11 @@ err_exit: /* We must delete the link file. */ RemoteDatafile::delete_link_file(table->name.m_name); - - } else if (compression != NULL && compression[0] != '\0') { -#ifdef MYSQL_COMPRESSION - ut_ad(!dict_table_in_shared_tablespace(table)); - - ut_ad(Compression::validate(compression) == DB_SUCCESS); - - err = fil_set_compression(table, compression); - - switch (err) { - case DB_SUCCESS: - break; - case DB_NOT_FOUND: - case DB_UNSUPPORTED: - case DB_IO_NO_PUNCH_HOLE_FS: - /* Return these errors */ - break; - case DB_IO_NO_PUNCH_HOLE_TABLESPACE: - /* Page Compression will not be used. */ - err = DB_SUCCESS; - break; - default: - ut_error; - } - - /* We can check for file system punch hole support - only after creating the tablespace. On Windows - we can query that information but not on Linux. */ - ut_ad(err == DB_SUCCESS - || err == DB_IO_NO_PUNCH_HOLE_FS); -#endif /* MYSQL_COMPRESSION */ - - /* In non-strict mode we ignore dodgy compression - settings. */ } } switch (err) { case DB_SUCCESS: - case DB_IO_NO_PUNCH_HOLE_FS: break; case DB_OUT_OF_FILE_SPACE: trx->error_state = DB_SUCCESS; diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index 1c118dabc61..2d5ba6781d4 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -395,8 +395,6 @@ public: IORequest request(IORequest::WRITE); - request.disable_compression(); - io_err = os_file_write( request, m_log_file_name, handle, log_buf, 0, sz); @@ -488,8 +486,6 @@ public: IORequest request(IORequest::WRITE); - request.disable_compression(); - err = os_file_write( request, m_log_file_name, handle, buffer, 0, sizeof(buffer)); @@ -671,8 +667,6 @@ TruncateLogParser::parse( IORequest request(IORequest::READ); - request.disable_compression(); - /* Align the memory for file i/o if we might have O_DIRECT set*/ byte* log_buf = static_cast(ut_align(buf, UNIV_PAGE_SIZE)); diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 002477bc4e0..2fa7a02e85e 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -195,8 +195,6 @@ UNIV_INTERN long srv_mtflush_threads = MTFLUSH_DEFAULT_WORKER; UNIV_INTERN my_bool srv_use_mtflush = FALSE; #ifdef UNIV_DEBUG -/** Force all user tables to use page compression. */ -ulong srv_debug_compress; /** Used by SET GLOBAL innodb_master_thread_disabled_debug = X. */ my_bool srv_master_thread_disabled_debug; /** Event used to inform that master thread is disabled. */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index fd00e95e494..dfed856b051 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1454,14 +1454,6 @@ innobase_start_or_create_for_mysql(void) } #endif /* HAVE_LZO1X */ -#ifdef UNIV_LINUX -# ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE - ib::info() << "PUNCH HOLE support available"; -# else - ib::info() << "PUNCH HOLE support not available"; -# endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE */ -#endif /* UNIV_LINUX */ - if (sizeof(ulint) != sizeof(void*)) { ib::error() << "Size of InnoDB's ulint is " << sizeof(ulint) << ", but size of void* is " << sizeof(void*) diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index acde762a0b7..0763e0fa057 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -703,8 +703,6 @@ namespace undo { IORequest request(IORequest::WRITE); - request.disable_compression(); - err = os_file_write( request, log_file_name, handle, log_buf, 0, sz); @@ -768,8 +766,6 @@ namespace undo { IORequest request(IORequest::WRITE); - request.disable_compression(); - err = os_file_write( request, log_file_name, handle, log_buf, 0, sz); @@ -837,8 +833,6 @@ namespace undo { IORequest request(IORequest::READ); - request.disable_compression(); - dberr_t err; err = os_file_read(request, handle, log_buf, 0, sz); diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index d296fb5afe2..9eb11c913c5 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -749,16 +749,8 @@ ut_strerr( return("Table is corrupted"); case DB_FTS_TOO_MANY_WORDS_IN_PHRASE: return("Too many words in a FTS phrase or proximity search"); - case DB_IO_DECOMPRESS_FAIL: - return("Page decompress failed after reading from disk"); case DB_DECRYPTION_FAILED: return("Table is encrypted but decrypt failed."); - case DB_IO_NO_PUNCH_HOLE: - return("No punch hole support"); - case DB_IO_NO_PUNCH_HOLE_FS: - return("Punch hole not supported by the file system"); - case DB_IO_NO_PUNCH_HOLE_TABLESPACE: - return("Punch hole not supported by the tablespace"); case DB_IO_PARTIAL_FAILED: return("Partial IO failed"); case DB_FORCED_ABORT: From 494e4b99a4a6c2f933c7e663cbb6ad5b17e8f84a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 16 Jan 2017 16:02:42 +0200 Subject: [PATCH 086/167] Remove MYSQL_TABLESPACES. MySQL 5.7 introduced partial support for user-created shared tablespaces (for example, import and export are not supported). MariaDB Server does not support tablespaces at this point of time. Let us remove most InnoDB code and data structures that is related to shared tablespaces. --- .../innodb/r/innodb-alter-discard.result | 2 +- .../suite/innodb/t/innodb-alter-discard.test | 2 +- storage/innobase/btr/btr0btr.cc | 2 +- storage/innobase/dict/dict0crea.cc | 79 +- storage/innobase/dict/dict0dict.cc | 8 - storage/innobase/dict/dict0load.cc | 351 +------- storage/innobase/dict/dict0mem.cc | 4 - storage/innobase/fil/fil0fil.cc | 284 +----- storage/innobase/fsp/fsp0file.cc | 72 +- storage/innobase/fsp/fsp0fsp.cc | 30 +- storage/innobase/fsp/fsp0space.cc | 3 +- storage/innobase/fts/fts0fts.cc | 7 - storage/innobase/handler/ha_innodb.cc | 821 ++---------------- storage/innobase/handler/ha_innodb.h | 69 +- storage/innobase/handler/ha_innopart.cc | 66 +- storage/innobase/handler/handler0alter.cc | 39 +- storage/innobase/handler/i_s.cc | 10 +- storage/innobase/include/db0err.h | 2 - storage/innobase/include/dict0crea.h | 7 - storage/innobase/include/dict0dict.h | 19 +- storage/innobase/include/dict0dict.ic | 69 +- storage/innobase/include/dict0load.h | 10 +- storage/innobase/include/dict0mem.h | 23 +- storage/innobase/include/fil0fil.h | 94 -- storage/innobase/include/fsp0file.h | 12 +- storage/innobase/include/fsp0fsp.h | 16 +- storage/innobase/include/fsp0fsp.ic | 45 +- storage/innobase/include/fsp0space.h | 26 +- storage/innobase/include/fsp0types.h | 19 - storage/innobase/include/ha_prototypes.h | 1 - storage/innobase/row/row0mysql.cc | 8 +- storage/innobase/row/row0quiesce.cc | 9 - storage/innobase/row/row0trunc.cc | 118 +-- storage/innobase/srv/srv0srv.cc | 9 +- storage/innobase/srv/srv0start.cc | 2 +- storage/innobase/ut/ut0ut.cc | 3 - 36 files changed, 184 insertions(+), 2157 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-alter-discard.result b/mysql-test/suite/innodb/r/innodb-alter-discard.result index b05b905bc34..4f773185f3e 100644 --- a/mysql-test/suite/innodb/r/innodb-alter-discard.result +++ b/mysql-test/suite/innodb/r/innodb-alter-discard.result @@ -5,7 +5,7 @@ call mtr.add_suppression("InnoDB: Operating system error number .* in a file ope call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified."); call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself, InnoDB does not create them."); call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: './test/t.ibd' OS error: .*"); -call mtr.add_suppression("InnoDB: Ignoring tablespace `test/t` because it could not be opened."); +call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`t` because it could not be opened."); call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .*"); call mtr.add_suppression("InnoDB: Error: trying to open a table, but could not$"); call mtr.add_suppression("MySQL is trying to open a table handle but the \.ibd file for$"); diff --git a/mysql-test/suite/innodb/t/innodb-alter-discard.test b/mysql-test/suite/innodb/t/innodb-alter-discard.test index 19ba7c3a3ca..51faf0d9068 100644 --- a/mysql-test/suite/innodb/t/innodb-alter-discard.test +++ b/mysql-test/suite/innodb/t/innodb-alter-discard.test @@ -29,7 +29,7 @@ call mtr.add_suppression("InnoDB: Operating system error number .* in a file ope call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified."); call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself, InnoDB does not create them."); call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: './test/t.ibd' OS error: .*"); -call mtr.add_suppression("InnoDB: Ignoring tablespace `test/t` because it could not be opened."); +call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`t` because it could not be opened."); call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .*"); call mtr.add_suppression("InnoDB: Error: trying to open a table, but could not$"); call mtr.add_suppression("MySQL is trying to open a table handle but the \.ibd file for$"); diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index d1d9dfe64fe..f150a98e6ef 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -338,7 +338,7 @@ btr_root_adjust_on_import( ulint flags = dict_tf_to_fsp_flags( table->flags, false); ulint fsp_flags = fil_space_get_flags(table->space); - err = fsp_flags_are_equal(flags, fsp_flags) + err = flags == fsp_flags ? DB_SUCCESS : DB_CORRUPTION; } } else { diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 58b1e5b46b1..44624f6b654 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -377,75 +377,6 @@ dict_build_table_def_step( return(err); } -/** Build a tablespace to store various objects. -@param[in,out] tablespace Tablespace object describing what to build. -@return DB_SUCCESS or error code. */ -dberr_t -dict_build_tablespace( - Tablespace* tablespace) -{ - dberr_t err = DB_SUCCESS; - mtr_t mtr; - ulint space = 0; - - ut_ad(mutex_own(&dict_sys->mutex)); - ut_ad(tablespace); - - DBUG_EXECUTE_IF("out_of_tablespace_disk", - return(DB_OUT_OF_FILE_SPACE);); - /* Get a new space id. */ - dict_hdr_get_new_id(NULL, NULL, &space, NULL, false); - if (space == ULINT_UNDEFINED) { - return(DB_ERROR); - } - tablespace->set_space_id(space); - - Datafile* datafile = tablespace->first_datafile(); - - /* We create a new generic empty tablespace. - We initially let it be 4 pages: - - page 0 is the fsp header and an extent descriptor page, - - page 1 is an ibuf bitmap page, - - page 2 is the first inode page, - - page 3 will contain the root of the clustered index of the - first table we create here. */ - - err = fil_ibd_create( - space, - tablespace->name(), - datafile->filepath(), - tablespace->flags(), - FIL_IBD_FILE_INITIAL_SIZE, - tablespace->encryption_mode(), - tablespace->key_id()); - - if (err != DB_SUCCESS) { - return(err); - } - - /* Update SYS_TABLESPACES and SYS_DATAFILES */ - err = dict_replace_tablespace_and_filepath( - tablespace->space_id(), tablespace->name(), - datafile->filepath(), tablespace->flags()); - if (err != DB_SUCCESS) { - os_file_delete(innodb_data_file_key, datafile->filepath()); - return(err); - } - - mtr_start(&mtr); - mtr.set_named_space(space); - - /* Once we allow temporary general tablespaces, we must do this; - mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); */ - ut_a(!FSP_FLAGS_GET_TEMPORARY(tablespace->flags())); - - fsp_header_init(space, FIL_IBD_FILE_INITIAL_SIZE, &mtr); - - mtr_commit(&mtr); - - return(err); -} - /** Builds a tablespace to contain a table, using file-per-table=1. @param[in,out] table Table to build in its own tablespace. @param[in] node Table create node @@ -554,15 +485,7 @@ dict_build_tablespace_for_table( return(DB_ERROR); } } else { - /* We do not need to build a tablespace for this table. It - is already built. Just find the correct tablespace ID. */ - - if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { - ut_ad(table->tablespace != NULL); - - ut_ad(table->space == fil_space_get_id_by_name( - table->tablespace())); - } else if (dict_table_is_temporary(table)) { + if (dict_table_is_temporary(table)) { /* Use the shared temporary tablespace. Note: The temp tablespace supports all non-Compressed row formats whereas the system tablespace only diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 122ab2c54f0..58d5870bf95 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -7268,22 +7268,14 @@ dict_tf_to_fsp_flags( DICT_TF_HAS_ATOMIC_BLOBS(table_flags); page_size_t page_size = dict_tf_get_page_size(table_flags); bool has_data_dir = DICT_TF_HAS_DATA_DIR(table_flags); - bool is_shared = DICT_TF_HAS_SHARED_SPACE(table_flags); bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(table_flags); ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(table_flags); ut_ad(!page_size.is_compressed() || has_atomic_blobs); - /* General tablespaces that are not compressed do not get the - flags for dynamic row format (POST_ANTELOPE & ATOMIC_BLOBS) */ - if (is_shared && !page_size.is_compressed()) { - has_atomic_blobs = false; - } - ulint fsp_flags = fsp_flags_init(page_size, has_atomic_blobs, has_data_dir, - is_shared, is_temp, 0, 0, diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index ffa7f48beae..a3da3a755d6 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2016, 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 @@ -811,102 +811,6 @@ dict_get_first_path( return(filepath); } -/** Gets the space name from SYS_TABLESPACES for a given space ID. -@param[in] space_id Tablespace ID -@param[in] callers_heap A heap to allocate from, may be NULL -@return Tablespace name (caller is responsible to free it) -@retval NULL if no dictionary entry was found. */ -static -char* -dict_space_get_name( - ulint space_id, - mem_heap_t* callers_heap) -{ - mtr_t mtr; - dict_table_t* sys_tablespaces; - dict_index_t* sys_index; - dtuple_t* tuple; - dfield_t* dfield; - byte* buf; - btr_pcur_t pcur; - const rec_t* rec; - const byte* field; - ulint len; - char* space_name = NULL; - mem_heap_t* heap = mem_heap_create(1024); - - ut_ad(mutex_own(&dict_sys->mutex)); - - sys_tablespaces = dict_table_get_low("SYS_TABLESPACES"); - if (sys_tablespaces == NULL) { - ut_a(!srv_sys_tablespaces_open); - return(NULL); - } - - sys_index = UT_LIST_GET_FIRST(sys_tablespaces->indexes); - - ut_ad(!dict_table_is_comp(sys_tablespaces)); - ut_ad(name_of_col_is(sys_tablespaces, sys_index, - DICT_FLD__SYS_TABLESPACES__SPACE, "SPACE")); - ut_ad(name_of_col_is(sys_tablespaces, sys_index, - DICT_FLD__SYS_TABLESPACES__NAME, "NAME")); - - tuple = dtuple_create(heap, 1); - dfield = dtuple_get_nth_field(tuple, DICT_FLD__SYS_TABLESPACES__SPACE); - - buf = static_cast(mem_heap_alloc(heap, 4)); - mach_write_to_4(buf, space_id); - - dfield_set_data(dfield, buf, 4); - dict_index_copy_types(tuple, sys_index, 1); - - mtr_start(&mtr); - - btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, - BTR_SEARCH_LEAF, &pcur, &mtr); - - rec = btr_pcur_get_rec(&pcur); - - /* Get the tablespace name from this SYS_TABLESPACES record. */ - if (btr_pcur_is_on_user_rec(&pcur)) { - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_TABLESPACES__SPACE, &len); - ut_a(len == 4); - - if (space_id == mach_read_from_4(field)) { - /* A record for this space ID was found. */ - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_TABLESPACES__NAME, &len); - - ut_ad(len > 0); - ut_ad(len < OS_FILE_MAX_PATH); - - if (len > 0 && len != UNIV_SQL_NULL) { - /* Found a tablespace name. */ - if (callers_heap == NULL) { - space_name = mem_strdupl( - reinterpret_cast< - const char*>(field), - len); - } else { - space_name = mem_heap_strdupl( - callers_heap, - reinterpret_cast< - const char*>(field), - len); - } - ut_ad(space_name); - } - } - } - - btr_pcur_close(&pcur); - mtr_commit(&mtr); - mem_heap_free(heap); - - return(space_name); -} - /** Update the record for space_id in SYS_TABLESPACES to this filepath. @param[in] space_id Tablespace ID @param[in] filepath Tablespace filepath @@ -1144,106 +1048,6 @@ dict_sys_tablespaces_rec_read( return(true); } -/** Load and check each general tablespace mentioned in the SYS_TABLESPACES. -Ignore system and file-per-table tablespaces. -If it is valid, add it to the file_system list. -@param[in] validate true when the previous shutdown was not clean -@return the highest space ID found. */ -UNIV_INLINE -ulint -dict_check_sys_tablespaces( - bool validate) -{ - ulint max_space_id = 0; - btr_pcur_t pcur; - const rec_t* rec; - mtr_t mtr; - - DBUG_ENTER("dict_check_sys_tablespaces"); - - ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); - ut_ad(mutex_own(&dict_sys->mutex)); - - /* Before traversing it, let's make sure we have - SYS_TABLESPACES and SYS_DATAFILES loaded. */ - dict_table_get_low("SYS_TABLESPACES"); - dict_table_get_low("SYS_DATAFILES"); - - mtr_start(&mtr); - - for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES); - rec != NULL; - rec = dict_getnext_system(&pcur, &mtr)) - { - char space_name[NAME_LEN]; - ulint space_id = 0; - ulint fsp_flags; - - if (!dict_sys_tablespaces_rec_read(rec, &space_id, - space_name, &fsp_flags)) { - continue; - } - - /* Ignore system and file-per-table tablespaces. */ - if (is_system_tablespace(space_id) - || !fsp_is_shared_tablespace(fsp_flags)) { - continue; - } - - /* Ignore tablespaces that already are in the tablespace - cache. */ - if (fil_space_for_table_exists_in_mem( - space_id, space_name, false, true, NULL, 0, NULL)) { - /* Recovery can open a datafile that does not - match SYS_DATAFILES. If they don't match, update - SYS_DATAFILES. */ - char *dict_path = dict_get_first_path(space_id); - char *fil_path = fil_space_get_first_path(space_id); - if (dict_path && fil_path - && strcmp(dict_path, fil_path)) { - dict_update_filepath(space_id, fil_path); - } - ut_free(dict_path); - ut_free(fil_path); - continue; - } - - /* Set the expected filepath from the data dictionary. - If the file is found elsewhere (from an ISL or the default - location) or this path is the same file but looks different, - fil_ibd_open() will update the dictionary with what is - opened. */ - char* filepath = dict_get_first_path(space_id); - - validate = true; /* Encryption */ - - /* Check that the .ibd file exists. */ - dberr_t err = fil_ibd_open( - validate, - !srv_read_only_mode && srv_log_file_size != 0, - FIL_TYPE_TABLESPACE, - space_id, - fsp_flags, - space_name, - filepath, - NULL); - - if (err != DB_SUCCESS) { - ib::warn() << "Ignoring tablespace " - << id_name_t(space_name) - << " because it could not be opened."; - } - - max_space_id = ut_max(max_space_id, space_id); - - ut_free(filepath); - } - - mtr_commit(&mtr); - - DBUG_RETURN(max_space_id); -} - /** Read and return 5 integer fields from a SYS_TABLES record. @param[in] rec A record of SYS_TABLES @param[in] name Table Name, the same as SYS_TABLES.NAME @@ -1363,7 +1167,6 @@ dict_check_sys_tables( rec = dict_getnext_system(&pcur, &mtr)) { const byte* field; ulint len; - char* space_name; table_name_t table_name; table_id_t table_id; ulint space_id; @@ -1395,39 +1198,24 @@ dict_check_sys_tables( } if (flags2 & DICT_TF2_DISCARDED) { - ib::info() << "Ignoring tablespace " << table_name + ib::info() << "Ignoring tablespace for " << table_name << " because the DISCARD flag is set ."; ut_free(table_name.m_name); continue; } /* If the table is not a predefined tablespace then it must - be in a file-per-table or shared tablespace. + be in a file-per-table tablespace. Note that flags2 is not available for REDUNDANT tables, so don't check those. */ - ut_ad(DICT_TF_HAS_SHARED_SPACE(flags) - || !DICT_TF_GET_COMPACT(flags) + ut_ad(!DICT_TF_GET_COMPACT(flags) || flags2 & DICT_TF2_USE_FILE_PER_TABLE); - /* Look up the tablespace name in the data dictionary if this - is a shared tablespace. For file-per-table, the table_name - and the tablespace_name are the same. - Some hidden tables like FTS AUX tables may not be found in - the dictionary since they can always be found in the default - location. If so, then dict_space_get_name() will return NULL, - the space name must be the table_name, and the filepath can be - discovered in the default location.*/ - char* shared_space_name = dict_space_get_name(space_id, NULL); - space_name = shared_space_name == NULL - ? table_name.m_name - : shared_space_name; - /* Now that we have the proper name for this tablespace, - whether it is a shared tablespace or a single table - tablespace, look to see if it is already in the tablespace - cache. */ + look to see if it is already in the tablespace cache. */ if (fil_space_for_table_exists_in_mem( - space_id, space_name, false, true, NULL, 0, NULL)) { + space_id, table_name.m_name, + false, true, NULL, 0, NULL)) { /* Recovery can open a datafile that does not match SYS_DATAFILES. If they don't match, update SYS_DATAFILES. */ @@ -1440,7 +1228,6 @@ dict_check_sys_tables( ut_free(dict_path); ut_free(fil_path); ut_free(table_name.m_name); - ut_free(shared_space_name); continue; } @@ -1462,20 +1249,19 @@ dict_check_sys_tables( FIL_TYPE_TABLESPACE, space_id, fsp_flags, - space_name, + table_name.m_name, filepath, NULL); if (err != DB_SUCCESS) { - ib::warn() << "Ignoring tablespace " - << id_name_t(space_name) + ib::warn() << "Ignoring tablespace for " + << table_name << " because it could not be opened."; } max_space_id = ut_max(max_space_id, space_id); ut_free(table_name.m_name); - ut_free(shared_space_name); ut_free(filepath); } @@ -1485,7 +1271,6 @@ dict_check_sys_tables( } /** Check each tablespace found in the data dictionary. -Look at each general tablespace found in SYS_TABLESPACES. Then look at each table defined in SYS_TABLES that has a space_id > 0 to find all the file-per-table tablespaces. @@ -1518,16 +1303,10 @@ dict_check_tablespaces_and_store_max_id( fil_set_max_space_id_if_bigger(max_space_id); - /* Open all general tablespaces found in SYS_TABLESPACES. */ - ulint max1 = dict_check_sys_tablespaces(validate); - /* Open all tablespaces referenced in SYS_TABLES. This will update SYS_TABLESPACES and SYS_DATAFILES if it finds any file-per-table tablespaces not already there. */ - ulint max2 = dict_check_sys_tables(validate); - - /* Store the max space_id found */ - max_space_id = ut_max(max1, max2); + max_space_id = dict_check_sys_tables(validate); fil_set_max_space_id_if_bigger(max_space_id); mutex_exit(&dict_sys->mutex); @@ -2767,72 +2546,6 @@ dict_get_and_save_data_dir_path( } } -/** Make sure the tablespace name is saved in dict_table_t if the table -uses a general tablespace. -Try to read it from the fil_system_t first, then from SYS_TABLESPACES. -@param[in] table Table object -@param[in] dict_mutex_own) true if dict_sys->mutex is owned already */ -void -dict_get_and_save_space_name( - dict_table_t* table, - bool dict_mutex_own) -{ - /* Do this only for general tablespaces. */ - if (!DICT_TF_HAS_SHARED_SPACE(table->flags)) { - return; - } - - bool use_cache = true; - if (table->tablespace != NULL) { - - if (srv_sys_tablespaces_open - && dict_table_has_temp_general_tablespace_name( - table->tablespace)) { - /* We previous saved the temporary name, - get the real one now. */ - use_cache = false; - } else { - /* Keep and use this name */ - return; - } - } - - if (use_cache) { - fil_space_t* space = fil_space_acquire_silent(table->space); - - if (space != NULL) { - /* Use this name unless it is a temporary general - tablespace name and we can now replace it. */ - if (!srv_sys_tablespaces_open - || !dict_table_has_temp_general_tablespace_name( - space->name)) { - - /* Use this tablespace name */ - table->tablespace = mem_heap_strdup( - table->heap, space->name); - - fil_space_release(space); - return; - } - fil_space_release(space); - } - } - - /* Read it from the dictionary. */ - if (srv_sys_tablespaces_open) { - if (!dict_mutex_own) { - dict_mutex_enter_for_mysql(); - } - - table->tablespace = dict_space_get_name( - table->space, table->heap); - - if (!dict_mutex_own) { - dict_mutex_exit_for_mysql(); - } - } -} - /** Loads a table definition and also all its index definitions, and also the cluster definition if the table is a member in a cluster. Also loads all foreign key constraints where the foreign key is in the table or where @@ -2915,37 +2628,12 @@ dict_load_tablespace( return; } - /* A file-per-table table name is also the tablespace name. - A general tablespace name is not the same as the table name. - Use the general tablespace name if it can be read from the - dictionary, if not use 'innodb_general_##. */ - char* shared_space_name = NULL; - char* space_name; - if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { - if (srv_sys_tablespaces_open) { - shared_space_name = - dict_space_get_name(table->space, NULL); - - } else { - /* Make the temporary tablespace name. */ - shared_space_name = static_cast( - ut_malloc_nokey( - strlen(general_space_name) + 20)); - - sprintf(shared_space_name, "%s_" ULINTPF, - general_space_name, - static_cast(table->space)); - } - space_name = shared_space_name; - } else { - space_name = table->name.m_name; - } + char* space_name = table->name.m_name; /* The tablespace may already be open. */ if (fil_space_for_table_exists_in_mem( table->space, space_name, false, true, heap, table->id, table)) { - ut_free(shared_space_name); return; } @@ -2970,20 +2658,6 @@ dict_load_tablespace( table->data_dir_path, table->name.m_name, IBD, true); } - - } else if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { - /* Set table->tablespace from either - fil_system or SYS_TABLESPACES */ - dict_get_and_save_space_name(table, true); - - /* Set the filepath from either - fil_system or SYS_DATAFILES. */ - filepath = dict_get_first_path(table->space); - if (filepath == NULL) { - ib::warn() << "Could not find the filepath" - " for table " << table->name << - ", space ID " << table->space; - } } /* Try to open the tablespace. We set the 2nd param (fix_dict) to @@ -2998,7 +2672,6 @@ dict_load_tablespace( table->ibd_file_missing = TRUE; } - ut_free(shared_space_name); ut_free(filepath); } diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index f4726ecd329..9463c5103ca 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -163,10 +163,6 @@ dict_mem_table_create( table->fts = NULL; } - if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { - dict_get_and_save_space_name(table, true); - } - new(&table->foreign_set) dict_foreign_set(); new(&table->referenced_set) dict_foreign_set(); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index f8abe3c5f21..331fc34e603 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -128,15 +128,10 @@ out of the LRU-list and keep a count of pending operations. When an operation completes, we decrement the count and return the file node to the LRU-list if the count drops to zero. */ -/** This tablespace name is used internally during recovery to open a -general tablespace before the data dictionary are recovered and available. */ -const char general_space_name[] = "innodb_general"; - /** Reference to the server data directory. Usually it is the current working directory ".", but in the MySQL Embedded Server Library it is an absolute path. */ const char* fil_path_to_mysql_datadir; -Folder folder_mysql_datadir; /** Common InnoDB file extentions */ const char* dot_ext[] = { "", ".ibd", ".isl", ".cfg" }; @@ -3106,13 +3101,7 @@ fil_delete_tablespace( /* Delete the link file pointing to the ibd file we are deleting. */ if (FSP_FLAGS_HAS_DATA_DIR(space->flags)) { - RemoteDatafile::delete_link_file(space->name); - - } else if (FSP_FLAGS_GET_SHARED(space->flags)) { - - RemoteDatafile::delete_link_file(base_name(path)); - } mutex_enter(&fil_system->mutex); @@ -3725,7 +3714,6 @@ func_exit: /** Create a new General or Single-Table tablespace @param[in] space_id Tablespace ID @param[in] name Tablespace name in dbname/tablename format. -For general tablespaces, the 'dbname/' part may be missing. @param[in] path Path and filename of the datafile to create. @param[in] flags Tablespace flags @param[in] size Initial size of the tablespace file in @@ -3750,7 +3738,6 @@ fil_ibd_create( bool success; bool is_temp = FSP_FLAGS_GET_TEMPORARY(flags); bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags); - bool has_shared_space = FSP_FLAGS_GET_SHARED(flags); fil_space_t* space = NULL; fil_space_crypt_t *crypt_data = NULL; @@ -3762,11 +3749,9 @@ fil_ibd_create( /* Create the subdirectories in the path, if they are not there already. */ - if (!has_shared_space) { - err = os_file_create_subdirs_if_needed(path); - if (err != DB_SUCCESS) { - return(err); - } + err = os_file_create_subdirs_if_needed(path); + if (err != DB_SUCCESS) { + return(err); } file = os_file_create( @@ -3923,11 +3908,10 @@ fil_ibd_create( return(DB_ERROR); } - if (has_data_dir || has_shared_space) { + if (has_data_dir) { /* Make the ISL file if the IBD file is not in the default location. */ - err = RemoteDatafile::create_link_file(name, path, - has_shared_space); + err = RemoteDatafile::create_link_file(name, path); if (err != DB_SUCCESS) { os_file_close(file); os_file_delete(innodb_data_file_key, path); @@ -3974,7 +3958,7 @@ fil_ibd_create( These labels reflect the order in which variables are assigned or actions are done. */ error_exit_1: - if (err != DB_SUCCESS && (has_data_dir || has_shared_space)) { + if (err != DB_SUCCESS && has_data_dir) { RemoteDatafile::delete_link_file(name); } @@ -4030,7 +4014,6 @@ fil_ibd_open( bool dict_filepath_same_as_default = false; bool link_file_found = false; bool link_file_is_bad = false; - bool is_shared = FSP_FLAGS_GET_SHARED(flags); Datafile df_default; /* default location */ Datafile df_dict; /* dictionary location */ RemoteDatafile df_remote; /* remote location */ @@ -4056,25 +4039,8 @@ fil_ibd_open( /* Discover the correct file by looking in three possible locations while avoiding unecessary effort. */ - if (is_shared) { - /* Shared tablespaces will have a path_in since the filename - is not generated from the tablespace name. Use the basename - from this path_in with the default datadir as a filepath to - the default location */ - ut_a(path_in); - const char* sep = strrchr(path_in, OS_PATH_SEPARATOR); - const char* basename = (sep == NULL) ? path_in : &sep[1]; - df_default.make_filepath(NULL, basename, IBD); - - /* Always validate shared tablespaces. */ - validate = true; - - /* Set the ISL filepath in the default location. */ - df_remote.set_link_filepath(path_in); - } else { - /* We will always look for an ibd in the default location. */ - df_default.make_filepath(NULL, space_name, IBD); - } + /* We will always look for an ibd in the default location. */ + df_default.make_filepath(NULL, space_name, IBD); /* Look for a filepath embedded in an ISL where the default file would be. */ @@ -4284,8 +4250,7 @@ fil_ibd_open( RemoteDatafile::delete_link_file(space_name); } - } else if (!is_shared - && (!link_file_found || link_file_is_bad)) { + } else if (!link_file_found || link_file_is_bad) { ut_ad(df_dict.is_open()); /* Fix the link file if we got our filepath from the dictionary but a link file did not @@ -4315,9 +4280,7 @@ fil_ibd_open( path_in is not suppled for file-per-table, we must assume that it matched the ISL. */ if ((path_in != NULL && !dict_filepath_same_as_default) - || (path_in == NULL - && (DICT_TF_HAS_DATA_DIR(flags) - || DICT_TF_HAS_SHARED_SPACE(flags))) + || (path_in == NULL && DICT_TF_HAS_DATA_DIR(flags)) || df_remote.filepath() != NULL) { dict_replace_tablespace_and_filepath( id, space_name, df_default.filepath(), flags); @@ -4449,24 +4412,12 @@ fil_ibd_discover( ulint space_id, Datafile& df) { - Datafile df_def_gen; /* default general datafile */ Datafile df_def_per; /* default file-per-table datafile */ - RemoteDatafile df_rem_gen; /* remote general datafile*/ RemoteDatafile df_rem_per; /* remote file-per-table datafile */ - /* Look for the datafile in the default location. If it is - a general tablespace, it will be in the datadir. */ + /* Look for the datafile in the default location. */ const char* filename = df.filepath(); const char* basename = base_name(filename); - df_def_gen.init(basename, 0); - df_def_gen.make_filepath(NULL, basename, IBD); - if (df_def_gen.open_read_only(false) == DB_SUCCESS - && df_def_gen.validate_for_recovery() == DB_SUCCESS - && df_def_gen.space_id() == space_id) { - df.set_filepath(df_def_gen.filepath()); - df.open_read_only(false); - return(true); - } /* If this datafile is file-per-table it will have a schema dir. */ ulint sep_found = 0; @@ -4487,44 +4438,9 @@ fil_ibd_discover( df.open_read_only(false); return(true); } - } - /* Did not find a general or file-per-table datafile in the - default location. Look for a remote general tablespace. */ - df_rem_gen.set_name(basename); - if (df_rem_gen.open_link_file() == DB_SUCCESS) { + /* Look for a remote file-per-table tablespace. */ - /* An ISL file was found with contents. */ - if (df_rem_gen.open_read_only(false) != DB_SUCCESS - || df_rem_gen.validate_for_recovery() != DB_SUCCESS) { - - /* Assume that this ISL file is intended to be used. - Do not continue looking for another if this file - cannot be opened or is not a valid IBD file. */ - ib::error() << "ISL file '" - << df_rem_gen.link_filepath() - << "' was found but the linked file '" - << df_rem_gen.filepath() - << "' could not be opened or is not correct."; - return(false); - } - - /* Use this file if it has the space_id from the MLOG - record. */ - if (df_rem_gen.space_id() == space_id) { - df.set_filepath(df_rem_gen.filepath()); - df.open_read_only(false); - return(true); - } - - /* Since old MLOG records can use the same basename in - multiple CREATE/DROP sequences, this ISL file could be - pointing to a later version of this basename.ibd file - which has a different space_id. Keep looking. */ - } - - /* Look for a remote file-per-table tablespace. */ - if (sep_found == 2) { df_rem_per.set_name(db); if (df_rem_per.open_link_file() == DB_SUCCESS) { @@ -4616,14 +4532,9 @@ fil_ibd_load( return(FIL_LOAD_OK); } - /* If the filepath in the redo log is a default location in or - under the datadir, then just try to open it there. */ Datafile file; file.set_filepath(filename); - Folder folder(filename, dirname_length(filename)); - if (folder_mysql_datadir >= folder) { - file.open_read_only(false); - } + file.open_read_only(false); if (!file.is_open()) { /* The file has been moved or it is a remote datafile. */ @@ -4804,37 +4715,7 @@ fil_space_for_table_exists_in_mem( table->crypt_data = space->crypt_data; } - if (space != NULL - && FSP_FLAGS_GET_SHARED(space->flags) - && adjust_space - && srv_sys_tablespaces_open - && 0 == strncmp(space->name, general_space_name, - strlen(general_space_name))) { - /* This name was assigned during recovery in fil_ibd_load(). - This general tablespace was opened from an MLOG_FILE_NAME log - entry where the tablespace name does not exist. Replace the - temporary name with this name and return this space. */ - HASH_DELETE(fil_space_t, name_hash, fil_system->name_hash, - ut_fold_string(space->name), space); - ut_free(space->name); - space->name = mem_strdup(name); - HASH_INSERT(fil_space_t, name_hash, fil_system->name_hash, - ut_fold_string(space->name), space); - - mutex_exit(&fil_system->mutex); - - return(true); - } - if (space != NULL) { - if (FSP_FLAGS_GET_SHARED(space->flags) - && !srv_sys_tablespaces_open) { - - /* No need to check the name */ - mutex_exit(&fil_system->mutex); - return(true); - } - /* If this space has the expected name, use it. */ fnamespace = fil_space_get_by_name(name); if (space == fnamespace) { @@ -6359,12 +6240,10 @@ fil_mtr_rename_log( dberr_t err; bool old_is_file_per_table = - !is_system_tablespace(old_table->space) - && !DICT_TF_HAS_SHARED_SPACE(old_table->flags); + !is_system_tablespace(old_table->space); bool new_is_file_per_table = - !is_system_tablespace(new_table->space) - && !DICT_TF_HAS_SHARED_SPACE(new_table->flags); + !is_system_tablespace(new_table->space); /* If neither table is file-per-table, there will be no renaming of files. */ @@ -6702,139 +6581,6 @@ truncate_t::truncate( return(err); } -/** Build the basic folder name from the path and length provided -@param[in] path pathname (may also include the file basename) -@param[in] len length of the path, in bytes */ -void -Folder::make_path(const char* path, size_t len) -{ - if (is_absolute_path(path)) { - m_folder = mem_strdupl(path, len); - m_folder_len = len; - } - else { - size_t n = 2 + len + strlen(fil_path_to_mysql_datadir); - m_folder = static_cast(ut_malloc_nokey(n)); - m_folder_len = 0; - - if (path != fil_path_to_mysql_datadir) { - /* Put the mysqld datadir into m_folder first. */ - ut_ad(fil_path_to_mysql_datadir[0] != '\0'); - m_folder_len = strlen(fil_path_to_mysql_datadir); - memcpy(m_folder, fil_path_to_mysql_datadir, - m_folder_len); - if (m_folder[m_folder_len - 1] != OS_PATH_SEPARATOR) { - m_folder[m_folder_len++] = OS_PATH_SEPARATOR; - } - } - - /* Append the path. */ - memcpy(m_folder + m_folder_len, path, len); - m_folder_len += len; - m_folder[m_folder_len] = '\0'; - } - - os_normalize_path(m_folder); -} - -/** Resolve a relative path in m_folder to an absolute path -in m_abs_path setting m_abs_len. */ -void -Folder::make_abs_path() -{ - my_realpath(m_abs_path, m_folder, MYF(0)); - m_abs_len = strlen(m_abs_path); - - ut_ad(m_abs_len + 1 < sizeof(m_abs_path)); - - /* Folder::related_to() needs a trailing separator. */ - if (m_abs_path[m_abs_len - 1] != OS_PATH_SEPARATOR) { - m_abs_path[m_abs_len] = OS_PATH_SEPARATOR; - m_abs_path[++m_abs_len] = '\0'; - } -} - -/** Constructor -@param[in] path pathname (may also include the file basename) -@param[in] len length of the path, in bytes */ -Folder::Folder(const char* path, size_t len) -{ - make_path(path, len); - make_abs_path(); -} - -/** Assignment operator -@param[in] folder folder string provided */ -class Folder& -Folder::operator=(const char* path) -{ - ut_free(m_folder); - make_path(path, strlen(path)); - make_abs_path(); - - return(*this); -} - -/** Determine if two folders are equal -@param[in] other folder to compare to -@return whether the folders are equal */ -bool Folder::operator==(const Folder& other) const -{ - return(m_abs_len == other.m_abs_len - && !memcmp(m_abs_path, other.m_abs_path, m_abs_len)); -} - -/** Determine if the left folder is the same or an ancestor of -(contains) the right folder. -@param[in] other folder to compare to -@return whether this is the same or an ancestor of the other folder. */ -bool Folder::operator>=(const Folder& other) const -{ - return(m_abs_len <= other.m_abs_len - && (!memcmp(other.m_abs_path, m_abs_path, m_abs_len))); -} - -/** Determine if the left folder is an ancestor of (contains) -the right folder. -@param[in] other folder to compare to -@return whether this is an ancestor of the other folder */ -bool Folder::operator>(const Folder& other) const -{ - return(m_abs_len < other.m_abs_len - && (!memcmp(other.m_abs_path, m_abs_path, m_abs_len))); -} - -/** Determine if the directory referenced by m_folder exists. -@return whether the directory exists */ -bool -Folder::exists() -{ - bool exists; - os_file_type_t type; - -#ifdef _WIN32 - /* Temporarily strip the trailing_separator since it will cause - _stat64() to fail on Windows unless the path is the root of some - drive; like "c:\". _stat64() will fail if it is "c:". */ - size_t len = strlen(m_abs_path); - if (m_abs_path[m_abs_len - 1] == OS_PATH_SEPARATOR - && m_abs_path[m_abs_len - 2] != ':') { - m_abs_path[m_abs_len - 1] = '\0'; - } -#endif /* WIN32 */ - - bool ret = os_file_status(m_abs_path, &exists, &type); - -#ifdef _WIN32 - /* Put the separator back on. */ - if (m_abs_path[m_abs_len - 1] == '\0') { - m_abs_path[m_abs_len - 1] = OS_PATH_SEPARATOR; - } -#endif /* WIN32 */ - - return(ret && exists && type == OS_FILE_TYPE_DIR); -} - /* Unit Tests */ #ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH #define MF fil_make_filepath diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 600de5418bd..00b5c37cec4 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -268,9 +268,8 @@ Datafile::same_as( } /** Allocate and set the datafile or tablespace name in m_name. -If a name is provided, use it; else if the datafile is file-per-table, -extract a file-per-table tablespace name from m_filepath; else it is a -general tablespace, so just call it that for now. The value of m_name +If a name is provided, use it; else extract a file-per-table +tablespace name from m_filepath. The value of m_name will be freed in the destructor. @param[in] name tablespace name if known, NULL if not */ void @@ -280,14 +279,8 @@ Datafile::set_name(const char* name) if (name != NULL) { m_name = mem_strdup(name); - } else if (fsp_is_file_per_table(m_space_id, m_flags)) { - m_name = fil_path_to_space_name(m_filepath); } else { - /* Give this general tablespace a temporary name. */ - m_name = static_cast( - ut_malloc_nokey(strlen(general_space_name) + 20)); - - sprintf(m_name, "%s_" ULINTPF, general_space_name, m_space_id); + m_name = fil_path_to_space_name(m_filepath); } } @@ -408,9 +401,8 @@ Datafile::validate_to_dd( If the datafile is a file-per-table tablespace then also match the row format and zip page size. */ if (m_space_id == space_id - && (m_flags & FSP_FLAGS_MASK_SHARED - || (m_flags & ~FSP_FLAGS_MASK_DATA_DIR) - == (flags & ~FSP_FLAGS_MASK_DATA_DIR))) { + && ((m_flags & ~FSP_FLAGS_MASK_DATA_DIR) + == (flags & ~FSP_FLAGS_MASK_DATA_DIR))) { /* Datafile matches the tablespace expected. */ return(DB_SUCCESS); } @@ -900,19 +892,7 @@ the path provided without its suffix, plus DOT_ISL. void RemoteDatafile::set_link_filepath(const char* path) { - if (m_link_filepath != NULL) { - return; - } - - if (path != NULL && FSP_FLAGS_GET_SHARED(flags())) { - /* Make the link_filepath based on the basename. */ - ut_ad(strcmp(&path[strlen(path) - strlen(DOT_IBD)], - DOT_IBD) == 0); - - m_link_filepath = fil_make_filepath(NULL, base_name(path), - ISL, false); - } else { - /* Make the link_filepath based on the m_name. */ + if (m_link_filepath == NULL) { m_link_filepath = fil_make_filepath(NULL, name(), ISL, false); } } @@ -922,14 +902,11 @@ under the 'datadir' of MySQL. The datadir is the directory of a running mysqld program. We can refer to it by simply using the path ".". @param[in] name tablespace name @param[in] filepath remote filepath of tablespace datafile -@param[in] is_shared true for general tablespace, - false for file-per-table @return DB_SUCCESS or error code */ dberr_t RemoteDatafile::create_link_file( const char* name, - const char* filepath, - bool is_shared) + const char* filepath) { bool success; dberr_t err = DB_SUCCESS; @@ -939,31 +916,8 @@ RemoteDatafile::create_link_file( ut_ad(!srv_read_only_mode); ut_ad(0 == strcmp(&filepath[strlen(filepath) - 4], DOT_IBD)); - if (is_shared) { - /* The default location for a shared tablespace is the - datadir. We previously made sure that this filepath is - not under the datadir. If it is in the datadir there - is no need for a link file. */ + link_filepath = fil_make_filepath(NULL, name, ISL, false); - size_t len = dirname_length(filepath); - if (len == 0) { - /* File is in the datadir. */ - return(DB_SUCCESS); - } - - Folder folder(filepath, len); - - if (folder_mysql_datadir == folder) { - /* File is in the datadir. */ - return(DB_SUCCESS); - } - - /* Use the file basename to build the ISL filepath. */ - link_filepath = fil_make_filepath(NULL, base_name(filepath), - ISL, false); - } else { - link_filepath = fil_make_filepath(NULL, name, ISL, false); - } if (link_filepath == NULL) { return(DB_ERROR); } @@ -1070,8 +1024,6 @@ RemoteDatafile::delete_link_file( It is always created under the datadir of MySQL. For file-per-table tablespaces, the isl file is expected to be in a 'database' directory and called 'tablename.isl'. -For general tablespaces, there will be no 'database' directory. -The 'basename.isl' will be in the datadir. The caller must free the memory returned if it is not null. @param[in] link_filepath filepath of the ISL file @return Filepath of the IBD file read from the ISL file */ @@ -1079,16 +1031,12 @@ char* RemoteDatafile::read_link_file( const char* link_filepath) { - char* filepath = NULL; - FILE* file = NULL; - - file = fopen(link_filepath, "r+b"); + FILE* file = fopen(link_filepath, "r+b"); if (file == NULL) { return(NULL); } - filepath = static_cast( - ut_malloc_nokey(OS_FILE_MAX_PATH)); + char* filepath = static_cast(ut_malloc_nokey(OS_FILE_MAX_PATH)); os_file_read_string(file, filepath, OS_FILE_MAX_PATH); fclose(file); diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 2dd96bdbd04..8739326b022 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -197,7 +197,6 @@ fsp_flags_to_dict_tf( ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags); bool atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(fsp_flags); bool data_dir = FSP_FLAGS_HAS_DATA_DIR(fsp_flags); - bool shared_space = FSP_FLAGS_GET_SHARED(fsp_flags); bool page_compressed = FSP_FLAGS_GET_PAGE_COMPRESSION(fsp_flags); ulint comp_level = FSP_FLAGS_GET_PAGE_COMPRESSION_LEVEL(fsp_flags); @@ -206,7 +205,7 @@ fsp_flags_to_dict_tf( any code is created where that is needed. */ ulint flags = dict_tf_init(post_antelope | compact, zip_ssize, - atomic_blobs, data_dir, shared_space, + atomic_blobs, data_dir, page_compressed, comp_level, 0); return(flags); @@ -228,7 +227,6 @@ fsp_flags_is_valid( bool atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags); ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags); bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags); - bool is_shared = FSP_FLAGS_GET_SHARED(flags); bool is_temp = FSP_FLAGS_GET_TEMPORARY(flags); ulint unused = FSP_FLAGS_GET_UNUSED(flags); bool page_compression = FSP_FLAGS_GET_PAGE_COMPRESSION(flags); @@ -279,7 +277,7 @@ fsp_flags_is_valid( /* Only single-table tablespaces use the DATA DIRECTORY clause. It is not compatible with the TABLESPACE clause. Nor is it compatible with the TEMPORARY clause. */ - if (has_data_dir && (is_shared || is_temp)) { + if (has_data_dir && is_temp) { GOTO_ERROR; return(false); } @@ -311,7 +309,6 @@ err_exit: << " page_ssize: " << page_ssize << " " << UNIV_PAGE_SSIZE_MIN << ":" << UNIV_PAGE_SSIZE_MAX << " has_data_dir: " << has_data_dir - << " is_shared: " << is_shared << " is_temp: " << is_temp << " page_compressed: " << page_compression << " page_compression_level: " << page_compression_level; @@ -328,19 +325,6 @@ fsp_is_checksum_disabled( return(fsp_is_system_temporary(space_id)); } -/** Check if tablespace is file-per-table. -@param[in] space_id tablespace ID -@param[in] fsp_flags tablespace flags -@return true if tablespace is file-per-table. */ -bool -fsp_is_file_per_table( - ulint space_id, - ulint fsp_flags) -{ - return(!is_system_tablespace(space_id) - && !fsp_is_shared_tablespace(fsp_flags)); -} - #ifdef UNIV_DEBUG /** Skip some of the sanity checks that are time consuming even in debug mode and can affect frequent verification runs that are done to ensure stability of @@ -1099,8 +1083,8 @@ fsp_try_extend_data_file( to reset the flag to false as dealing with this error requires server restart. */ if (!srv_sys_space.get_tablespace_full_status()) { - ib::error() << "Tablespace " << srv_sys_space.name() - << " " << OUT_OF_SPACE_MSG + ib::error() << "The InnoDB system tablespace " + << OUT_OF_SPACE_MSG << " innodb_data_file_path."; srv_sys_space.set_tablespace_full_status(true); } @@ -1113,8 +1097,8 @@ fsp_try_extend_data_file( to reset the flag to false as dealing with this error requires server restart. */ if (!srv_tmp_space.get_tablespace_full_status()) { - ib::error() << "Tablespace " << srv_tmp_space.name() - << " " << OUT_OF_SPACE_MSG + ib::error() << "The InnoDB temporary tablespace " + << OUT_OF_SPACE_MSG << " innodb_temp_data_file_path."; srv_tmp_space.set_tablespace_full_status(true); } @@ -1174,7 +1158,7 @@ fsp_try_extend_data_file( } /** Calculate the number of pages to extend a datafile. -We extend single-table and general tablespaces first one extent at a time, +We extend single-table tablespaces first one extent at a time, but 4 at a time for bigger tablespaces. It is not enough to extend always by one extent, because we need to add at least one extent to FSP_FREE. A single extent descriptor page will track many extents. And the extent diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc index b72590e48e8..ed557fb8334 100644 --- a/storage/innobase/fsp/fsp0space.cc +++ b/storage/innobase/fsp/fsp0space.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -18,7 +19,7 @@ this program; if not, write to the Free Software Foundation, Inc., /**************************************************//** @file fsp/fsp0space.cc -General shared tablespace implementation. +Shared tablespace implementation. Created 2012-11-16 by Sunny Bains as srv/srv0space.cc *******************************************************/ diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 55c34db2b59..f05ad4421f6 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1780,13 +1780,6 @@ fts_create_in_mem_aux_table( aux_table_name, table->space, n_cols, 0, table->flags, fts_get_table_flags2_for_aux_tables(table->flags2)); - if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { - ut_ad(table->space == fil_space_get_id_by_name( - table->tablespace())); - new_table->tablespace = mem_heap_strdup( - new_table->heap, table->tablespace); - } - if (DICT_TF_HAS_DATA_DIR(table->flags)) { ut_ad(table->data_dir_path != NULL); new_table->data_dir_path = mem_heap_strdup( diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1e47da86f70..56b1f968244 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -474,20 +474,6 @@ static const char* innobase_change_buffering_values[IBUF_USE_COUNT] = { "all" /* IBUF_USE_ALL */ }; - -/* This tablespace name is reserved by InnoDB in order to explicitly -create a file_per_table tablespace for the table. */ -const char reserved_file_per_table_space_name[] = "innodb_file_per_table"; - -/* This tablespace name is reserved by InnoDB for the system tablespace -which uses space_id 0 and stores extra types of system pages like UNDO -and doublewrite. */ -const char reserved_system_space_name[] = "innodb_system"; - -/* This tablespace name is reserved by InnoDB for the predefined temporary -tablespace. */ -const char reserved_temporary_space_name[] = "innodb_temporary"; - /* Call back function array defined by MySQL and used to retrieve FTS results. */ const struct _ft_vft ft_vft_result = {NULL, @@ -1478,20 +1464,6 @@ innobase_rollback_by_xid( XID* xid); /*!< in: X/Open XA transaction identification */ -#ifdef MYSQL_TABLESPACES -/** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces. -@param[in] hton Handlerton of InnoDB -@param[in] thd Connection -@param[in] alter_info Describies the command and how to do it. -@return MySQL error code*/ -static -int -innobase_alter_tablespace( - handlerton* hton, - THD* thd, - st_alter_tablespace* alter_info); -#endif /* MYSQL_TABLESPACES */ - /** Remove all tables in the named database inside InnoDB. @param[in] hton handlerton from InnoDB @param[in] path Database path; Inside InnoDB the name of the last @@ -2335,8 +2307,6 @@ convert_error_code_to_mysql( return(HA_ERR_TABLE_CORRUPT); case DB_FTS_TOO_MANY_WORDS_IN_PHRASE: return(HA_ERR_FTS_TOO_MANY_WORDS_IN_PHRASE); - case DB_WRONG_FILE_NAME: - return(HA_ERR_GENERIC); // when can this happen? case DB_COMPUTE_VALUE_FAILED: return(HA_ERR_GENERIC); // impossible } @@ -3535,7 +3505,7 @@ innobase_invalidate_query_cache( TRUE); } -/** Quote a standard SQL identifier like tablespace, index or column name. +/** Quote a standard SQL identifier like index or column name. @param[in] file output stream @param[in] trx InnoDB transaction, or NULL @param[in] id identifier to quote */ @@ -3924,9 +3894,6 @@ innobase_init( innobase_hton->commit_checkpoint_request=innobase_checkpoint_request; innobase_hton->create = innobase_create_handler; -#ifdef MYSQL_TABLESPACES - innobase_hton->alter_tablespace = innobase_alter_tablespace; -#endif innobase_hton->drop_database = innobase_drop_database; innobase_hton->panic = innobase_end; innobase_hton->partition_flags= innobase_partition_flags; @@ -4095,7 +4062,6 @@ innobase_init( ut_a(default_path); fil_path_to_mysql_datadir = default_path; - folder_mysql_datadir = fil_path_to_mysql_datadir; /* Set InnoDB initialization parameters according to the values read from MySQL .cnf file */ @@ -4132,10 +4098,10 @@ innobase_init( /* Create the filespace flags. */ fsp_flags = fsp_flags_init( - univ_page_size, false, false, false, false, false, 0, 0); + univ_page_size, false, false, false, false, 0, 0); srv_sys_space.set_flags(fsp_flags); - srv_sys_space.set_name(reserved_system_space_name); + srv_sys_space.set_name("innodb_system"); srv_sys_space.set_path(srv_data_home); /* Supports raw devices */ @@ -4153,12 +4119,12 @@ innobase_init( /* We set the temporary tablspace id later, after recovery. The temp tablespace doesn't support raw devices. Set the name and path. */ - srv_tmp_space.set_name(reserved_temporary_space_name); + srv_tmp_space.set_name("innodb_temporary"); srv_tmp_space.set_path(srv_data_home); /* Create the filespace flags with the temp flag set. */ fsp_flags = fsp_flags_init( - univ_page_size, false, false, false, true, false, 0, 0); + univ_page_size, false, false, true, false, 0, 0); srv_tmp_space.set_flags(fsp_flags); if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) { @@ -11773,11 +11739,6 @@ create_table_info_t::create_table_def() /* For single-table tablespaces, we pass 0 as the space id, and then determine the actual space id when the tablespace is created. */ - if (DICT_TF_HAS_SHARED_SPACE(m_flags)) { - ut_ad(m_tablespace != NULL && m_tablespace[0] != '\0'); - - space_id = fil_space_get_id_by_name(m_tablespace); - } /* Adjust the number of columns for the FTS hidden field */ actual_n_cols = n_cols; @@ -11809,13 +11770,6 @@ create_table_info_t::create_table_def() table->data_dir_path = NULL; } - if (DICT_TF_HAS_SHARED_SPACE(m_flags)) { - ut_ad(strlen(m_tablespace)); - table->tablespace = mem_heap_strdup(table->heap, m_tablespace); - } else { - table->tablespace = NULL; - } - heap = mem_heap_create(1000); for (i = 0; i < n_cols; i++) { @@ -12278,7 +12232,7 @@ create_table_info_t::create_option_data_directory_is_valid() && m_create_info->data_file_name[0] != '\0'); /* Use DATA DIRECTORY only with file-per-table. */ - if (!m_use_shared_space && !m_allow_file_per_table) { + if (!m_allow_file_per_table) { push_warning( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -12303,201 +12257,6 @@ create_table_info_t::create_option_data_directory_is_valid() return(is_valid); } - -#ifdef MYSQL_TABLESPACES -#define IDENT_NAME_OK 0 -static int check_tablespace_name(const char *name) -{ - CHARSET_INFO *cs= system_charset_info; - return cs->cset->numchars(cs, name, name + strlen(name)) > NAME_CHAR_LEN; -} - - -/** Validate the tablespace name provided for a tablespace DDL -@param[in] name A proposed tablespace name -@param[in] for_table Caller is putting a table here -@return MySQL handler error code like HA_... */ -static -int -validate_tablespace_name( - const char* name, - bool for_table) -{ - int err = 0; - - /* This prefix is reserved by InnoDB for use in internal tablespace names. */ - const char reserved_space_name_prefix[] = "innodb_"; - - if (check_tablespace_name(name) != IDENT_NAME_OK) { - err = HA_WRONG_CREATE_OPTION; - } - - /* The tablespace name cannot start with `innodb_`. */ - if (strlen(name) >= sizeof(reserved_space_name_prefix) - 1 - && 0 == memcmp(name, reserved_space_name_prefix, - sizeof(reserved_space_name_prefix) - 1)) { - - /* Use a different message for reserved names */ - if (0 == strcmp(name, reserved_file_per_table_space_name) - || 0 == strcmp(name, reserved_system_space_name) - || 0 == strcmp(name, reserved_temporary_space_name)) { - /* Allow these names if the caller is putting a - table into one of these by CREATE/ALTER TABLE */ - if (!for_table) { - my_printf_error( - ER_WRONG_TABLESPACE_NAME, - "InnoDB: `%s` is a reserved" - " tablespace name.", - MYF(0), name); - err = HA_WRONG_CREATE_OPTION; - } - } else { - my_printf_error(ER_WRONG_TABLESPACE_NAME, - "InnoDB: A general tablespace" - " name cannot start with `%s`.", - MYF(0), reserved_space_name_prefix); - err = HA_WRONG_CREATE_OPTION; - } - } - - /* The tablespace name cannot contain a '/'. */ - if (memchr(name, '/', strlen(name)) != NULL) { - my_printf_error(ER_WRONG_TABLESPACE_NAME, - "InnoDB: A general tablespace name cannot" - " contain '/'.", MYF(0)); - err = HA_WRONG_CREATE_OPTION; - } - - return(err); -} - -/** Validate TABLESPACE option. -@return true if valid, false if not. */ -bool -create_table_info_t::create_option_tablespace_is_valid() -{ - if (!m_use_shared_space) { - return(true); - } - - if (0 != validate_tablespace_name(m_create_info->tablespace, true)) { - return(false); - } - - /* Look up the tablespace name in the fil_system. */ - ulint space_id = fil_space_get_id_by_name( - m_create_info->tablespace); - - if (space_id == ULINT_UNDEFINED) { - my_printf_error(ER_TABLESPACE_MISSING, - "InnoDB: A general tablespace named" - " `%s` cannot be found.", MYF(0), - m_create_info->tablespace); - return(false); - } - - /* Cannot add a second table to a file-per-table tablespace. */ - ulint fsp_flags = fil_space_get_flags(space_id); - if (fsp_is_file_per_table(space_id, fsp_flags)) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Tablespace `%s` is file-per-table so no" - " other table can be added to it.", MYF(0), - m_create_info->tablespace); - return(false); - } - - /* If TABLESPACE=innodb_file_per_table this function is not called - since tablespace_is_shared_space() will return false. Any other - tablespace is incompatible with the DATA DIRECTORY phrase. - On any ALTER TABLE that contains a DATA DIRECTORY, MySQL will issue - a warning like " option ignored." The check below is - needed for CREATE TABLE only. ALTER TABLE may be moving remote - file-per-table table to a general tablespace, in which case the - create_info->data_file_name is not null. */ - bool is_create_table = (thd_sql_command(m_thd) == SQLCOM_CREATE_TABLE); - if (is_create_table - && m_create_info->data_file_name != NULL - && m_create_info->data_file_name[0] != '\0') { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: DATA DIRECTORY cannot be used" - " with a TABLESPACE assignment.", MYF(0)); - return(false); - } - - /* Temp tables only belong in temp tablespaces. */ - if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { - if (!FSP_FLAGS_GET_TEMPORARY(fsp_flags)) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Tablespace `%s` cannot contain" - " TEMPORARY tables.", MYF(0), - m_create_info->tablespace); - return(false); - } - - /* Restrict Compressed Temporary General tablespaces. */ - if (m_create_info->key_block_size - || m_create_info->row_type == ROW_TYPE_COMPRESSED) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Temporary tablespace `%s` cannot" - " contain COMPRESSED tables.", MYF(0), - m_create_info->tablespace); - return(false); - } - } else if (FSP_FLAGS_GET_TEMPORARY(fsp_flags)) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Tablespace `%s` can only contain" - " TEMPORARY tables.", MYF(0), - m_create_info->tablespace); - return(false); - } - - /* Make sure the physical page size of the table matches the - file block size of the tablespace. */ - ulint block_size_needed; - bool table_is_compressed; - if (m_create_info->key_block_size) { - block_size_needed = m_create_info->key_block_size * 1024; - table_is_compressed = true; - } else if (m_create_info->row_type == ROW_TYPE_COMPRESSED) { - block_size_needed = ut_min( - UNIV_PAGE_SIZE / 2, - static_cast(UNIV_ZIP_SIZE_MAX)); - table_is_compressed = true; - } else { - block_size_needed = UNIV_PAGE_SIZE; - table_is_compressed = false; - } - - const page_size_t page_size(fsp_flags); - - /* The compression code needs some work in order for a general - tablespace to contain both compressed and non-compressed tables - together in the same tablespace. The problem seems to be that - each page is either compressed or not based on the fsp flags, - which is shared by all tables in that general tablespace. */ - if (table_is_compressed && page_size.physical() == UNIV_PAGE_SIZE) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Tablespace `%s` cannot contain a" - " COMPRESSED table", MYF(0), - m_create_info->tablespace); - return(false); - } - - if (block_size_needed != page_size.physical()) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Tablespace `%s` uses block size " ULINTPF - " and cannot contain a table with physical" - " page size " ULINTPF, MYF(0), - m_create_info->tablespace, - page_size.physical(), - block_size_needed); - return(false); - } - - return(true); -} -#endif - /** Validate the create options. Check that the options KEY_BLOCK_SIZE, ROW_FORMAT, DATA DIRECTORY, TEMPORARY & TABLESPACE are compatible with each other and other settings. These CREATE OPTIONS are not validated @@ -12516,20 +12275,8 @@ create_table_info_t::create_options_are_invalid() ut_ad(m_thd != NULL); ut_ad(m_create_info != NULL); -#ifdef MYSQL_TABLESPACES - /* The TABLESPACE designation on a CREATE TABLE is not subject to - non-strict-mode. If it is incorrect or is incompatible with other - options, then we will return an error. Make sure the tablespace exists - and is compatible with this table */ - if (!create_option_tablespace_is_valid()) { - return("TABLESPACE"); - } -#endif - - /* If innodb_strict_mode is not set don't do any more validation. - Also, if this table is being put into a shared general tablespace - we ALWAYS act like strict mode is ON. */ - if (!m_use_shared_space && !(THDVAR(m_thd, strict_mode))) { + /* If innodb_strict_mode is not set don't do any more validation. */ + if (!THDVAR(m_thd, strict_mode)) { return(NULL); } @@ -12560,11 +12307,6 @@ create_table_info_t::create_options_are_invalid() ret = "KEY_BLOCK_SIZE"; } - /* The following checks do not appy to shared tablespaces */ - if (m_use_shared_space) { - break; - } - /* Valid KEY_BLOCK_SIZE, check its dependencies. */ if (!m_allow_file_per_table) { push_warning( @@ -12599,47 +12341,43 @@ create_table_info_t::create_options_are_invalid() other incompatibilities. */ switch (row_format) { case ROW_TYPE_COMPRESSED: - if (!m_use_shared_space) { - if (!m_allow_file_per_table) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ROW_FORMAT=%s requires" - " innodb_file_per_table.", - get_row_format_name(row_format)); - ret = "ROW_FORMAT"; - } - if (srv_file_format < UNIV_FORMAT_B) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ROW_FORMAT=%s requires" - " innodb_file_format > Antelope.", - get_row_format_name(row_format)); - ret = "ROW_FORMAT"; - } + if (!m_allow_file_per_table) { + push_warning_printf( + m_thd, Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s requires" + " innodb_file_per_table.", + get_row_format_name(row_format)); + ret = "ROW_FORMAT"; + } + if (srv_file_format < UNIV_FORMAT_B) { + push_warning_printf( + m_thd, Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s requires" + " innodb_file_format > Antelope.", + get_row_format_name(row_format)); + ret = "ROW_FORMAT"; } break; case ROW_TYPE_DYNAMIC: - if (!m_use_shared_space) { - if (!m_allow_file_per_table) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ROW_FORMAT=%s requires" - " innodb_file_per_table.", - get_row_format_name(row_format)); - ret = "ROW_FORMAT"; - } - if (srv_file_format < UNIV_FORMAT_B) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ROW_FORMAT=%s requires" - " innodb_file_format > Antelope.", - get_row_format_name(row_format)); - ret = "ROW_FORMAT"; - } + if (!m_allow_file_per_table) { + push_warning_printf( + m_thd, Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s requires" + " innodb_file_per_table.", + get_row_format_name(row_format)); + ret = "ROW_FORMAT"; + } + if (srv_file_format < UNIV_FORMAT_B) { + push_warning_printf( + m_thd, Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s requires" + " innodb_file_format > Antelope.", + get_row_format_name(row_format)); + ret = "ROW_FORMAT"; } /* FALLTRHOUGH */ case ROW_TYPE_COMPACT: @@ -12863,18 +12601,6 @@ ha_innobase::update_create_info( if (m_prebuilt->table->data_dir_path) { create_info->data_file_name = m_prebuilt->table->data_dir_path; } - - /* Update the TABLESPACE name from the Data Dictionary. */ - dict_get_and_save_space_name(m_prebuilt->table, false); - - /* Put this tablespace name into the create_info structure so that - SHOW CREATE TABLE will display TABLESPACE=name. This also affects - an ALTER TABLE which must know the current TABLESPACE so that the - table will stay there. */ - if (m_prebuilt->table->tablespace != NULL - && create_info->tablespace == NULL) { - create_info->tablespace = m_prebuilt->table->tablespace; - } } /*****************************************************************//** @@ -12929,14 +12655,12 @@ create_table_info_t::parse_table_name( m_temp_path[0] = '\0'; m_remote_path[0] = '\0'; - m_tablespace[0] = '\0'; /* A full path is provided by the server for TEMPORARY tables not targeted for a tablespace or when DATA DIRECTORY is given. So these two are not compatible. Likewise, DATA DIRECTORY is not compatible with a TABLESPACE assignment. */ - if ((m_create_info->options & HA_LEX_CREATE_TMP_TABLE) - && !m_use_shared_space) { + if ((m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) { strncpy(m_temp_path, name, FN_REFLEN - 1); } @@ -12967,21 +12691,11 @@ create_table_info_t::parse_table_name( "INDEX DIRECTORY"); } - /* The TABLESPACE designation has already been validated by - create_option_tablespace_is_valid() irregardless of strict-mode. - So it only needs to be copied now. */ - if (m_use_shared_space) { - strncpy(m_tablespace, m_create_info->tablespace, - NAME_LEN - 1); - } - DBUG_RETURN(0); } /** Determine InnoDB table flags. If strict_mode=OFF, this will adjust the flags to what should be assumed. -However, if an existing general tablespace is being targeted, we will NOT -assume anything or adjust these flags. @retval true if successful, false if error */ bool create_table_info_t::innobase_table_flags() @@ -13075,7 +12789,7 @@ index_bad: } /* Make sure compressed row format is allowed. */ - if (!m_allow_file_per_table && !m_use_shared_space) { + if (!m_allow_file_per_table) { push_warning( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -13084,8 +12798,7 @@ index_bad: zip_allowed = false; } - if (file_format_allowed < UNIV_FORMAT_B - && !m_use_shared_space) { + if (file_format_allowed < UNIV_FORMAT_B) { push_warning( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -13148,16 +12861,14 @@ index_bad: case ROW_TYPE_COMPRESSED: /* ROW_FORMAT=COMPRESSED requires file_per_table and file_format=Barracuda unless there is a target tablespace. */ - if (!m_allow_file_per_table - && !m_use_shared_space) { + if (!m_allow_file_per_table) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: ROW_FORMAT=COMPRESSED requires" " innodb_file_per_table."); - } else if (file_format_allowed == UNIV_FORMAT_A - && !m_use_shared_space) { + } else if (file_format_allowed == UNIV_FORMAT_A) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -13215,14 +12926,13 @@ index_bad: /* Set the table flags */ dict_tf_set(&m_flags, innodb_row_format, zip_ssize, - m_use_data_dir, m_use_shared_space, + m_use_data_dir, options->page_compressed, options->page_compression_level == 0 ? default_compression_level : options->page_compression_level, 0); if (m_use_file_per_table) { - ut_ad(!m_use_shared_space); m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE; } @@ -13408,18 +13118,12 @@ void create_table_info_t::set_tablespace_type( bool table_being_altered_is_file_per_table) { - /* Note whether this table will be created using a shared, - general or system tablespace. */ - m_use_shared_space = tablespace_is_shared_space(m_create_info); - /** Allow file_per_table for this table either because: 1) the setting innodb_file_per_table=on, - 2) the table being altered is currently file_per_table - 3) explicitly requested by tablespace=innodb_file_per_table. */ + 2) the table being altered is currently file_per_table */ m_allow_file_per_table = m_innodb_file_per_table - || table_being_altered_is_file_per_table - || tablespace_is_file_per_table(m_create_info); + || table_being_altered_is_file_per_table; /* All noncompresed temporary tables will be put into the system temporary tablespace. */ @@ -13429,12 +13133,10 @@ create_table_info_t::set_tablespace_type( || m_create_info->key_block_size > 0); /* Ignore the current innodb-file-per-table setting if we are - creating a temporary, non-compressed table or if the - TABLESPACE= phrase is using an existing shared tablespace. */ + creating a temporary, non-compressed table. */ m_use_file_per_table = m_allow_file_per_table - && !is_noncompressed_temporary - && !m_use_shared_space; + && !is_noncompressed_temporary; /* DATA DIRECTORY must have m_use_file_per_table but cannot be used with TEMPORARY tables. */ @@ -13443,7 +13145,6 @@ create_table_info_t::set_tablespace_type( && !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE) && (m_create_info->data_file_name != NULL) && (m_create_info->data_file_name[0] != '\0'); - ut_ad(!(m_use_shared_space && m_use_data_dir)); } /** Initialize the create_table_info_t object. @@ -13871,7 +13572,6 @@ ha_innobase::create( char norm_name[FN_REFLEN]; /* {database}/{tablename} */ char temp_path[FN_REFLEN]; /* Absolute path of temp frm */ char remote_path[FN_REFLEN]; /* Absolute path of table */ - char tablespace[NAME_LEN]; /* Tablespace name identifier */ trx_t* trx; DBUG_ENTER("ha_innobase::create"); @@ -13880,8 +13580,7 @@ ha_innobase::create( create_info, norm_name, temp_path, - remote_path, - tablespace); + remote_path); /* Initialize the object. */ if ((error = info.initialize())) { @@ -13974,16 +13673,6 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE); } - if (DICT_TF_HAS_SHARED_SPACE(dict_table->flags)) { - my_printf_error(ER_NOT_ALLOWED_COMMAND, - "InnoDB: Cannot %s table `%s` because it is in" - " a general tablespace. It must be file-per-table.", - MYF(0), discard ? "discard" : "import", - dict_table->name.m_name); - - DBUG_RETURN(HA_ERR_NOT_ALLOWED_COMMAND); - } - TrxInInnoDB trx_in_innodb(m_prebuilt->trx); if (trx_in_innodb.is_aborted()) { @@ -14316,410 +14005,6 @@ ha_innobase::delete_table( DBUG_RETURN(convert_error_code_to_mysql(err, 0, NULL)); } -#ifdef MYSQL_TABLESPACES -/** Validate the parameters in st_alter_tablespace -before using them in InnoDB tablespace functions. -@param[in] thd Connection -@param[in] alter_info How to do the command. -@return MySQL handler error code like HA_... */ -static -int -validate_create_tablespace_info( - THD* thd, - st_alter_tablespace* alter_info) -{ - ulint space_id; - - /* The parser ensures that these fields are provided. */ - ut_a(alter_info->tablespace_name); - ut_a(alter_info->data_file_name); - - if (high_level_read_only) { - return(HA_ERR_INNODB_READ_ONLY); - } - - /* From this point forward, push a warning for each problem found - instead of returning immediately*/ - int error = validate_tablespace_name( - alter_info->tablespace_name, false); - - /* Make sure the tablespace is not already open. */ - space_id = fil_space_get_id_by_name(alter_info->tablespace_name); - if (space_id != ULINT_UNDEFINED) { - my_printf_error(ER_TABLESPACE_EXISTS, - "InnoDB: A tablespace named `%s`" - " already exists.", MYF(0), - alter_info->tablespace_name); - error = HA_ERR_TABLESPACE_EXISTS; - } - if (alter_info->file_block_size) { - /* Check for a bad file block size. */ - if (!ut_is_2pow(alter_info->file_block_size) - || alter_info->file_block_size < UNIV_ZIP_SIZE_MIN - || alter_info->file_block_size > UNIV_PAGE_SIZE_MAX) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB does not support" - " FILE_BLOCK_SIZE=%llu", MYF(0), - alter_info->file_block_size); - error = HA_WRONG_CREATE_OPTION; - - /* Don't allow a file block size larger than UNIV_PAGE_SIZE. */ - } else if (alter_info->file_block_size > UNIV_PAGE_SIZE) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Cannot create a tablespace" - " with FILE_BLOCK_SIZE=%llu because" - " INNODB_PAGE_SIZE=%lu.", MYF(0), - alter_info->file_block_size, - UNIV_PAGE_SIZE); - error = HA_WRONG_CREATE_OPTION; - - /* Don't allow a compressed tablespace when page size > 16k. */ - } else if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF - && alter_info->file_block_size != UNIV_PAGE_SIZE) { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: Cannot create a COMPRESSED" - " tablespace when innodb_page_size >" - " 16k.", MYF(0)); - error = HA_WRONG_CREATE_OPTION; - } - } - - /* Validate the ADD DATAFILE name. */ - char* filepath = mem_strdup(alter_info->data_file_name); - os_normalize_path(filepath); - - /* It must end with '.ibd' and contain a basename of at least - 1 character before the.ibd extension. */ - ulint dirname_len = dirname_length(filepath); - const char* basename = filepath + dirname_len; - ulint basename_len = strlen(basename); - if (basename_len < 5) { - my_error(ER_WRONG_FILE_NAME, MYF(0), - alter_info->data_file_name); - ut_free(filepath); - return(HA_WRONG_CREATE_OPTION); - } - - if (memcmp(&basename[basename_len - 4], DOT_IBD, 5)) { - my_error(ER_WRONG_FILE_NAME, MYF(0), - alter_info->data_file_name); - my_printf_error(ER_WRONG_FILE_NAME, - "An IBD filepath must end with `.ibd`.", - MYF(0)); - ut_free(filepath); - return(HA_WRONG_CREATE_OPTION); - } - - /* Do not allow an invalid colon in the file name. */ - const char* colon = strchr(filepath, ':'); - if (colon != NULL) { -#ifdef _WIN32 - /* Do not allow names like "C:name.ibd" because it - specifies the "C:" drive but allows a relative location. - It should be like "c:\". If a single colon is used it must - be the second byte the the third byte must be a separator. */ - if (colon != &filepath[1] - || (colon[1] != OS_PATH_SEPARATOR) - || NULL != strchr(&colon[1], ':')) { -#endif /* _WIN32 */ - my_error(ER_WRONG_FILE_NAME, MYF(0), - alter_info->data_file_name); - my_printf_error(ER_WRONG_FILE_NAME, - "Invalid use of ':'.", MYF(0)); - ut_free(filepath); - return(HA_WRONG_CREATE_OPTION); -#ifdef _WIN32 - } -#endif /* _WIN32 */ - } - -#ifndef _WIN32 - /* On Non-Windows platforms, '\\' is a valid file name character. - But for InnoDB datafiles, we always assume it is a directory - separator and convert these to '/' */ - if (strchr(alter_info->data_file_name, '\\') != NULL) { - ib::warn() << "Converting backslash to forward slash in" - " ADD DATAFILE " << alter_info->data_file_name; - } -#endif /* _WIN32 */ - - /* The directory path must be pre-existing. */ - Folder folder(filepath, dirname_len); - ut_free(filepath); - if (!folder.exists()) { - my_error(ER_WRONG_FILE_NAME, MYF(0), - alter_info->data_file_name); - my_printf_error(ER_WRONG_FILE_NAME, - "The directory does not exist.", MYF(0)); - return(HA_WRONG_CREATE_OPTION); - } - - /* CREATE TABLESPACE...ADD DATAFILE can be inside but not under - the datadir.*/ - if (folder_mysql_datadir > folder) { - my_error(ER_WRONG_FILE_NAME, MYF(0), - alter_info->data_file_name); - my_printf_error(ER_WRONG_FILE_NAME, - "CREATE TABLESPACE data file" - " cannot be under the datadir.", MYF(0)); - error = HA_WRONG_CREATE_OPTION; - } - - return(error); -} - -/** CREATE a tablespace. -@param[in] hton Handlerton of InnoDB -@param[in] thd Connection -@param[in] alter_info How to do the command -@return MySQL error code*/ -static -int -innobase_create_tablespace( - handlerton* hton, - THD* thd, - st_alter_tablespace* alter_info) -{ - trx_t* trx; - int error=0; - Tablespace tablespace; - - DBUG_ENTER("innobase_create_tablespace"); - DBUG_ASSERT(hton == innodb_hton_ptr); - - /* Be sure the input parameters are valid before continuing. */ - error = validate_create_tablespace_info(thd, alter_info); - if (error) { - DBUG_RETURN(error); - } - - /* Create the tablespace object. */ - tablespace.set_name(alter_info->tablespace_name); - - dberr_t err = tablespace.add_datafile(alter_info->data_file_name); - if (err != DB_SUCCESS) { - DBUG_RETURN(convert_error_code_to_mysql(err, 0, NULL)); - } - - /* Get the transaction associated with the current thd and make - sure it will not block this DDL. */ - trx_t* parent_trx = check_trx_exists(thd); - - /* In case MySQL calls this in the middle of a SELECT - query, release possible adaptive hash latch to avoid - deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); - - /* Allocate a new transaction for this DDL */ - trx = innobase_trx_allocate(thd); - ++trx->will_lock; - - trx_start_if_not_started(trx, true); - row_mysql_lock_data_dictionary(trx); - - /* In FSP_FLAGS, a zip_ssize of zero means that the tablespace - holds non-compresssed tables. A non-zero zip_ssize means that - the general tablespace can ONLY contain compressed tables. */ - ulint zip_size = static_cast(alter_info->file_block_size); - ut_ad(zip_size <= UNIV_PAGE_SIZE_MAX); - if (zip_size == 0) { - zip_size = UNIV_PAGE_SIZE; - } - - bool zipped = (zip_size != UNIV_PAGE_SIZE); - page_size_t page_size(zip_size, UNIV_PAGE_SIZE, zipped); - bool atomic_blobs = page_size.is_compressed(); - - /* Create the filespace flags */ - ulint fsp_flags = fsp_flags_init( - page_size, /* page sizes and a flag if compressed */ - atomic_blobs, /* needed only for compressed tables */ - false, /* This is not a file-per-table tablespace */ - true, /* This is a general shared tablespace */ - false, /* Temporary General Tablespaces not allowed */ - false, /* Page compression is not used. */ - 0, /* Page compression level 0 */ - 0); - - tablespace.set_flags(fsp_flags); - - err = dict_build_tablespace(&tablespace); - if (err != DB_SUCCESS) { - error = convert_error_code_to_mysql(err, 0, NULL); - trx_rollback_for_mysql(trx); - goto cleanup; - } - - innobase_commit_low(trx); - -cleanup: - row_mysql_unlock_data_dictionary(trx); - trx_free_for_mysql(trx); - - DBUG_RETURN(error); -} - -/** DROP a tablespace. -@param[in] hton Handlerton of InnoDB -@param[in] thd Connection -@param[in] alter_info How to do the command -@return MySQL error code*/ -static -int -innobase_drop_tablespace( - handlerton* hton, - THD* thd, - st_alter_tablespace* alter_info) -{ - trx_t* trx; - dberr_t err; - int error = 0; - ulint space_id; - - DBUG_ENTER("innobase_drop_tablespace"); - DBUG_ASSERT(hton == innodb_hton_ptr); - - if (srv_read_only_mode) { - DBUG_RETURN(HA_ERR_INNODB_READ_ONLY); - } - - error = validate_tablespace_name(alter_info->tablespace_name, false); - if (error != 0) { - DBUG_RETURN(error); - } - - /* Be sure that this tablespace is known and valid. */ - space_id = fil_space_get_id_by_name(alter_info->tablespace_name); - if (space_id == ULINT_UNDEFINED) { - - space_id = dict_space_get_id(alter_info->tablespace_name); - if (space_id == ULINT_UNDEFINED) { - DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); - // DBUG_RETURN(HA_ERR_TABLESPACE_MISSING); - } - - /* The datafile is not open but the tablespace is in - sys_tablespaces, so we can try to drop the metadata. */ - } - - /* The tablespace can only be dropped if it is empty. */ - if (!dict_space_is_empty(space_id)) { - DBUG_RETURN(HA_ERR_TABLE_READONLY); - //DBUG_RETURN(HA_ERR_TABLESPACE_IS_NOT_EMPTY); - } - - /* Get the transaction associated with the current thd and make sure - it will not block this DDL. */ - trx_t* parent_trx = check_trx_exists(thd); - - /* In case MySQL calls this in the middle of a SELECT - query, release possible adaptive hash latch to avoid - deadlocks of threads */ - trx_search_latch_release_if_reserved(parent_trx); - - /* Allocate a new transaction for this DDL */ - trx = innobase_trx_allocate(thd); - ++trx->will_lock; - - trx_start_if_not_started(trx, true); - row_mysql_lock_data_dictionary(trx); - - /* Update SYS_TABLESPACES and SYS_DATAFILES */ - err = dict_delete_tablespace_and_datafiles(space_id, trx); - if (err != DB_SUCCESS) { - ib::error() << "Unable to delete the dictionary entries" - " for tablespace `" << alter_info->tablespace_name - << "`, Space ID " << space_id; - goto have_error; - } - - /* Delete the physical files, fil_space_t & fil_node_t entries. */ - err = fil_delete_tablespace(space_id, BUF_REMOVE_FLUSH_NO_WRITE); - switch (err) { - case DB_TABLESPACE_NOT_FOUND: - /* OK if the physical file is mising. - We deleted the metadata. */ - case DB_SUCCESS: - innobase_commit_low(trx); - break; - default: - ib::error() << "Unable to delete the tablespace `" - << alter_info->tablespace_name - << "`, Space ID " << space_id; -have_error: - error = convert_error_code_to_mysql(err, 0, NULL); - trx_rollback_for_mysql(trx); - } - - row_mysql_unlock_data_dictionary(trx); - trx_free_for_mysql(trx); - - DBUG_RETURN(error); -} - -/** This API handles CREATE, ALTER & DROP commands for InnoDB tablespaces. -@param[in] hton Handlerton of InnoDB -@param[in] thd Connection -@param[in] alter_info How to do the command -@return MySQL error code*/ -static -int -innobase_alter_tablespace( - handlerton* hton, - THD* thd, - st_alter_tablespace* alter_info) -{ - int error; /* return zero for success */ - DBUG_ENTER("innobase_alter_tablespace"); - - switch (alter_info->ts_cmd_type) { - case CREATE_TABLESPACE: - error = innobase_create_tablespace(hton, thd, alter_info); - break; - - case DROP_TABLESPACE: - error = innobase_drop_tablespace(hton, thd, alter_info); - break; - - default: - error = HA_ADMIN_NOT_IMPLEMENTED; - } - - if (error) { - /* These are the most common message params */ - const char* object_type = "TABLESPACE"; - const char* object = alter_info->tablespace_name; - - /* Modify those params as needed. */ - switch (alter_info->ts_cmd_type) { - case DROP_TABLESPACE: - ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_DROP_FILEGROUP_FAILED, - "%s %s", object_type, object); - break; - case CREATE_TABLESPACE: - ib_errf(thd, IB_LOG_LEVEL_ERROR, - ER_CREATE_FILEGROUP_FAILED, - "%s %s", object_type, object); - break; - case CREATE_LOGFILE_GROUP: - my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), - innobase_hton_name, "LOGFILE GROUP"); - break; - case ALTER_TABLESPACE: - case ALTER_ACCESS_MODE_TABLESPACE: - case DROP_LOGFILE_GROUP: - case ALTER_LOGFILE_GROUP: - case CHANGE_FILE_TABLESPACE: - case TS_CMD_NOT_DEFINED: - break; - } - } - - DBUG_RETURN(error); -} -#endif /* MYSQL_TABLESPACES */ - /** Remove all tables in the named database inside InnoDB. @param[in] hton handlerton from InnoDB @param[in] path Database path; Inside InnoDB the name of the last diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 8d879207fab..066eff12ca9 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -23,19 +23,6 @@ this program; if not, write to the Free Software Foundation, Inc., system clustered index when there is no primary key. */ extern const char innobase_index_reserve_name[]; -/* "innodb_file_per_table" tablespace name is reserved by InnoDB in order -to explicitly create a file_per_table tablespace for the table. */ -extern const char reserved_file_per_table_space_name[]; - -/* "innodb_system" tablespace name is reserved by InnoDB for the -system tablespace which uses space_id 0 and stores extra types of -system pages like UNDO and doublewrite. */ -extern const char reserved_system_space_name[]; - -/* "innodb_temporary" tablespace name is reserved by InnoDB for the -predefined shared temporary tablespace. */ -extern const char reserved_temporary_space_name[]; - /* Structure defines translation table between mysql index and InnoDB index structures */ struct innodb_idx_translate_t { @@ -677,52 +664,6 @@ extern const char reserved_file_per_table_space_name[]; //extern "C" int wsrep_trx_is_aborting(void *thd_ptr); #endif -/** Check if the explicit tablespace targeted is file_per_table. -@param[in] create_info Metadata for the table to create. -@return true if the table is intended to use a file_per_table tablespace. */ -UNIV_INLINE -bool -tablespace_is_file_per_table( - const HA_CREATE_INFO* create_info) -{ - return(create_info->tablespace != NULL - && (0 == strcmp(create_info->tablespace, - reserved_file_per_table_space_name))); -} - -/** Check if table will be explicitly put in an existing shared general -or system tablespace. -@param[in] create_info Metadata for the table to create. -@return true if the table will use a shared general or system tablespace. */ -UNIV_INLINE -bool -tablespace_is_shared_space( -const HA_CREATE_INFO* create_info) -{ - return(create_info->tablespace != NULL - && create_info->tablespace[0] != '\0' - && (0 != strcmp(create_info->tablespace, - reserved_file_per_table_space_name))); -} - -/** Check if table will be explicitly put in a general tablespace. -@param[in] create_info Metadata for the table to create. -@return true if the table will use a general tablespace. */ -UNIV_INLINE -bool -tablespace_is_general_space( - const HA_CREATE_INFO* create_info) -{ - return(create_info->tablespace != NULL - && create_info->tablespace[0] != '\0' - && (0 != strcmp(create_info->tablespace, - reserved_file_per_table_space_name)) - && (0 != strcmp(create_info->tablespace, - reserved_temporary_space_name)) - && (0 != strcmp(create_info->tablespace, - reserved_system_space_name))); -} - /** Parse hint for table and its indexes, and update the information in dictionary. @param[in] thd Connection thread @@ -748,15 +689,13 @@ public: HA_CREATE_INFO* create_info, char* table_name, char* temp_path, - char* remote_path, - char* tablespace) + char* remote_path) :m_thd(thd), m_form(form), m_create_info(create_info), m_table_name(table_name), m_temp_path(temp_path), m_remote_path(remote_path), - m_tablespace(tablespace), m_innodb_file_per_table(srv_file_per_table) {} @@ -875,9 +814,6 @@ private: /** Remote path (DATA DIRECTORY) or zero length-string */ char* m_remote_path; - /** Tablespace name or zero length-string. */ - char* m_tablespace; - /** Local copy of srv_file_per_table. */ bool m_innodb_file_per_table; @@ -894,9 +830,6 @@ private: /** Using DATA DIRECTORY */ bool m_use_data_dir; - /** Using a Shared General Tablespace */ - bool m_use_shared_space; - /** Table flags */ ulint m_flags; diff --git a/storage/innobase/handler/ha_innopart.cc b/storage/innobase/handler/ha_innopart.cc index 09a60be1577..80f3b410ee7 100644 --- a/storage/innobase/handler/ha_innopart.cc +++ b/storage/innobase/handler/ha_innopart.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2016, 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 @@ -2464,35 +2464,6 @@ ha_innopart::update_part_elem( } part_elem->index_file_name = NULL; - dict_get_and_save_space_name(ib_table, false); - if (ib_table->tablespace != NULL) { - ut_ad(part_elem->tablespace_name == NULL - || 0 == strcmp(part_elem->tablespace_name, - ib_table->tablespace)); - if (part_elem->tablespace_name == NULL - || strcmp(ib_table->tablespace, - part_elem->tablespace_name) != 0) { - - /* Play safe and allocate memory from TABLE and copy - instead of expose the internal data dictionary. */ - part_elem->tablespace_name = - strdup_root(&table->mem_root, - ib_table->tablespace); - } - } - else { - ut_ad(part_elem->tablespace_name == NULL - || 0 == strcmp(part_elem->tablespace_name, - "innodb_file_per_table")); - if (part_elem->tablespace_name != NULL - && 0 != strcmp(part_elem->tablespace_name, - "innodb_file_per_table")) { - - /* Update part_elem tablespace to NULL same as in - innodb data dictionary ib_table. */ - part_elem->tablespace_name = NULL; - } - } } /** Update create_info. @@ -2558,7 +2529,7 @@ ha_innopart::update_create_info( DBUG_VOID_RETURN; } - /* part_elem->data_file_name and tablespace_name should be correct from + /* part_elem->data_file_name should be correct from the .frm, but may have been changed, so update from SYS_DATAFILES. index_file_name is ignored, so remove it. */ @@ -2592,17 +2563,11 @@ set_create_info_dir( if (part_elem->data_file_name != NULL && part_elem->data_file_name[0] != '\0') { info->data_file_name = part_elem->data_file_name; - /* Also implies non-default tablespace. */ - info->tablespace = NULL; } if (part_elem->index_file_name != NULL && part_elem->index_file_name[0] != '\0') { info->index_file_name = part_elem->index_file_name; } - if (part_elem->tablespace_name != NULL - && part_elem->tablespace_name[0] != '\0') { - info->tablespace = part_elem->tablespace_name; - } } /** Set flags and append '/' to remote path if necessary. */ @@ -2647,12 +2612,10 @@ ha_innopart::create( /** absolute path of table */ char remote_path[FN_REFLEN]; char partition_name[FN_REFLEN]; - char tablespace_name[NAME_LEN + 1]; char* table_name_end; size_t table_name_len; char* partition_name_start; char table_data_file_name[FN_REFLEN]; - char table_level_tablespace_name[NAME_LEN + 1]; const char* index_file_name; size_t len; @@ -2661,8 +2624,7 @@ ha_innopart::create( create_info, table_name, temp_path, - remote_path, - tablespace_name); + remote_path); DBUG_ENTER("ha_innopart::create"); ut_ad(create_info != NULL); @@ -2708,11 +2670,6 @@ ha_innopart::create( table_data_file_name[0] = '\0'; } index_file_name = create_info->index_file_name; - if (create_info->tablespace != NULL) { - strcpy(table_level_tablespace_name, create_info->tablespace); - } else { - table_level_tablespace_name[0] = '\0'; - } info.allocate_trx(); @@ -2798,15 +2755,12 @@ ha_innopart::create( table_data_file_name; create_info->index_file_name = index_file_name; - create_info->tablespace = - table_level_tablespace_name; set_create_info_dir(part_elem, create_info); } } /* Reset table level DATA/INDEX DIRECTORY. */ create_info->data_file_name = table_data_file_name; create_info->index_file_name = index_file_name; - create_info->tablespace = table_level_tablespace_name; } innobase_commit_low(info.trx()); @@ -4238,27 +4192,13 @@ ha_innopart::create_new_partition( { int error; char norm_name[FN_REFLEN]; - const char* tablespace_name_backup = create_info->tablespace; const char* data_file_name_backup = create_info->data_file_name; DBUG_ENTER("ha_innopart::create_new_partition"); /* Delete by ddl_log on failure. */ normalize_table_name(norm_name, part_name); set_create_info_dir(part_elem, create_info); - /* The below check is the same as for CREATE TABLE, but since we are - doing an alter here it will not trigger the check in - create_option_tablespace_is_valid(). */ - if (tablespace_is_shared_space(create_info) - && create_info->data_file_name != NULL - && create_info->data_file_name[0] != '\0') { - my_printf_error(ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: DATA DIRECTORY cannot be used" - " with a TABLESPACE assignment.", MYF(0)); - DBUG_RETURN(HA_WRONG_CREATE_OPTION); - } - error = ha_innobase::create(norm_name, table, create_info); - create_info->tablespace = tablespace_name_backup; create_info->data_file_name = data_file_name_backup; if (error == HA_ERR_FOUND_DUPP_KEY) { DBUG_RETURN(HA_ERR_TABLE_EXIST); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 6b6667b5e56..8ba9f6cb175 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -4579,20 +4579,6 @@ prepare_inplace_alter_table_dict( goto new_clustered_failed; } - /* Use the old tablespace unless the tablespace - is changing. */ - if (DICT_TF_HAS_SHARED_SPACE(user_table->flags) - && (ha_alter_info->create_info->tablespace == NULL - || (0 == strcmp(ha_alter_info->create_info->tablespace, - user_table->tablespace)))) { - space_id = user_table->space; - } else if (tablespace_is_shared_space( - ha_alter_info->create_info)) { - space_id = fil_space_get_id_by_name( - ha_alter_info->create_info->tablespace); - ut_a(space_id != ULINT_UNDEFINED); - } - /* The initial space id 0 may be overridden later if this table is going to be a file_per_table tablespace. */ ctx->new_table = dict_mem_table_create( @@ -5596,37 +5582,16 @@ ha_innobase::prepare_inplace_alter_table( /* ALTER TABLE will not implicitly move a table from a single-table tablespace to the system tablespace when innodb_file_per_table=OFF. But it will implicitly move a table from the system tablespace to a - single-table tablespace if innodb_file_per_table = ON. - Tables found in a general tablespace will stay there unless ALTER - TABLE contains another TABLESPACE=name. If that is found it will - explicitly move a table to the named tablespace. - So if you specify TABLESPACE=`innodb_system` a table can be moved - into the system tablespace from either a general or file-per-table - tablespace. But from then on, it is labeled as using a shared space - (the create options have tablespace=='innodb_system' and the - SHARED_SPACE flag is set in the table flags) so it can no longer be - implicitly moved to a file-per-table tablespace. */ - bool in_system_space = is_system_tablespace(indexed_table->space); - bool is_file_per_table = !in_system_space - && !DICT_TF_HAS_SHARED_SPACE(indexed_table->flags); -#ifdef UNIV_DEBUG - bool in_general_space = !in_system_space - && DICT_TF_HAS_SHARED_SPACE(indexed_table->flags); - - /* The table being altered can only be in a system tablespace, - or its own file-per-table tablespace, or a general tablespace. */ - ut_ad(1 == in_system_space + is_file_per_table + in_general_space); -#endif /* UNIV_DEBUG */ + single-table tablespace if innodb_file_per_table = ON. */ create_table_info_t info(m_user_thd, altered_table, ha_alter_info->create_info, NULL, NULL, - NULL, NULL); - info.set_tablespace_type(is_file_per_table); + info.set_tablespace_type(indexed_table->space != TRX_SYS_SPACE); if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_INDEX) { if (info.gcols_in_fulltext_or_spatial()) { diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 01fadaf8e10..a400ee54758 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -6050,8 +6050,6 @@ i_s_dict_fill_sys_tables( if (is_system_tablespace(table->space)) { space_type = "System"; - } else if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { - space_type = "General"; } else { space_type = "Single"; } @@ -8045,9 +8043,6 @@ i_s_dict_fill_sys_tablespaces( file_format = trx_sys_file_format_id_to_name(atomic_blobs); if (is_system_tablespace(space)) { row_format = "Compact or Redundant"; - } else if (fsp_is_shared_tablespace(flags) && !is_compressed) { - file_format = "Any"; - row_format = "Any"; } else if (is_compressed) { row_format = "Compressed"; } else if (atomic_blobs) { @@ -8058,8 +8053,6 @@ i_s_dict_fill_sys_tablespaces( if (is_system_tablespace(space)) { space_type = "System"; - } else if (fsp_is_shared_tablespace(flags)) { - space_type = "General"; } else { space_type = "Single"; } @@ -8089,8 +8082,7 @@ i_s_dict_fill_sys_tablespaces( space_type)); char* filepath = NULL; - if (FSP_FLAGS_HAS_DATA_DIR(flags) - || FSP_FLAGS_GET_SHARED(flags)) { + if (FSP_FLAGS_HAS_DATA_DIR(flags)) { mutex_enter(&dict_sys->mutex); filepath = dict_get_first_path(space); mutex_exit(&dict_sys->mutex); diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index ab505e04083..316d90bec34 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -154,8 +154,6 @@ enum dberr_t { DB_TABLE_CORRUPT, /*!< Table/clustered index is corrupted */ - DB_WRONG_FILE_NAME, /*!< Invalid Filename */ - DB_COMPUTE_VALUE_FAILED, /*!< Compute generated value failed */ DB_NO_FK_ON_S_BASE_COL, /*!< Cannot add foreign constrain diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h index 51cef91d318..9065f7ebf3d 100644 --- a/storage/innobase/include/dict0crea.h +++ b/storage/innobase/include/dict0crea.h @@ -67,13 +67,6 @@ dict_create_table_step( /*===================*/ que_thr_t* thr); /*!< in: query thread */ -/** Builds a tablespace to store various objects. -@param[in,out] tablespace Tablespace object describing what to build. -@return DB_SUCCESS or error code. */ -dberr_t -dict_build_tablespace( - Tablespace* tablespace); - /** Builds a tablespace to contain a table, using file-per-table=1. @param[in,out] table Table to build in its own tablespace. @param[in] node Table create node diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index b29e6aedcc0..a7fe80e447d 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -992,7 +992,9 @@ dict_tf_get_format( @param[in] format, File Format @param[in] zip_ssize Zip Shift Size @param[in] use_data_dir Table uses DATA DIRECTORY -@param[in] shared_space Table uses a General Shared Tablespace */ +@param[in] page_compressed Table uses page compression +@param[in] page_compression_level Page compression level +@param[in] not_used For future */ UNIV_INLINE void dict_tf_set( @@ -1000,7 +1002,6 @@ dict_tf_set( rec_format_t format, ulint zip_ssize, bool use_data_dir, - bool shared_space, bool page_compressed, ulint page_compression_level, ulint not_used); @@ -1010,7 +1011,9 @@ dict_tf_set( @param[in] zip_ssize Zip Shift Size (log 2 minus 9) @param[in] atomic_blobs Table uses Compressed or Dynamic @param[in] data_dir Table uses DATA DIRECTORY -@param[in] shared_space Table uses a General Shared Tablespace */ +@param[in] page_compressed Table uses page compression +@param[in] page_compression_level Page compression level +@param[in] not_used For future */ UNIV_INLINE ulint dict_tf_init( @@ -1018,7 +1021,6 @@ dict_tf_init( ulint zip_ssize, bool atomic_blobs, bool data_dir, - bool shared_space, bool page_compressed, ulint page_compression_level, ulint not_used); @@ -1973,15 +1975,6 @@ dict_table_is_temporary( const dict_table_t* table) /*!< in: table to check */ MY_ATTRIBUTE((warn_unused_result)); -/** Check if the table is in a shared tablespace (System or General). -@param[in] id Space ID to check -@return true if id is a shared tablespace, false if not. */ -UNIV_INLINE -bool -dict_table_in_shared_tablespace( - const dict_table_t* table) - MY_ATTRIBUTE((warn_unused_result)); - /********************************************************************//** Turn-off redo-logging if temporary table. */ UNIV_INLINE diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index c8624ea8b7d..3bb00294bfa 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -660,7 +660,6 @@ dict_tf_is_valid( ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags); bool atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(flags); bool data_dir = DICT_TF_HAS_DATA_DIR(flags); - bool shared_space = DICT_TF_HAS_SHARED_SPACE(flags); ulint unused = DICT_TF_GET_UNUSED(flags); bool page_compression = DICT_TF_GET_PAGE_COMPRESSION(flags); ulint page_compression_level = DICT_TF_GET_PAGE_COMPRESSION_LEVEL(flags); @@ -711,11 +710,6 @@ dict_tf_is_valid( } - /* HAS_DATA_DIR and SHARED_SPACE are mutually exclusive. */ - if (data_dir && shared_space) { - flags_corrupt = true; - } - if (flags_corrupt) { ib::error() << "InnoDB: Error: table unused flags are:" << flags @@ -726,8 +720,7 @@ dict_tf_is_valid( << " data_dir:" << data_dir << " zip_ssize:" << zip_ssize << " page_compression:" << page_compression - << " page_compression_level:" << page_compression_level - << " shared_space:" << shared_space; + << " page_compression_level:" << page_compression_level; return (false); } else { return(true); @@ -753,13 +746,6 @@ dict_tf2_is_valid( return(false); } - bool file_per_table = ((flags2 & DICT_TF2_USE_FILE_PER_TABLE) != 0); - bool shared_space = DICT_TF_HAS_SHARED_SPACE(flags); - - if (file_per_table && shared_space) { - return(false); - } - return(true); } @@ -931,7 +917,6 @@ dict_table_get_format( @param[in] format File Format @param[in] zip_ssize Zip Shift Size @param[in] use_data_dir Table uses DATA DIRECTORY -@param[in] shared_space Table uses a General Shared Tablespace @param[in] page_compressed Table uses page compression @param[in] page_compression_level Page compression level @param[in] not_used For future */ @@ -943,7 +928,6 @@ dict_tf_set( rec_format_t format, ulint zip_ssize, bool use_data_dir, - bool shared_space, bool page_compressed, ulint page_compression_level, ulint not_used) @@ -973,10 +957,6 @@ dict_tf_set( *flags |= (1 << DICT_TF_POS_DATA_DIR); } - if (shared_space) { - *flags |= (1 << DICT_TF_POS_SHARED_SPACE); - } - if (page_compressed) { *flags |= (1 << DICT_TF_POS_ATOMIC_BLOBS) | (1 << DICT_TF_POS_PAGE_COMPRESSION) @@ -993,7 +973,6 @@ dict_tf_set( @param[in] zip_ssize Zip Shift Size (log 2 minus 9) @param[in] atomic_blobs Table uses Compressed or Dynamic @param[in] data_dir Table uses DATA DIRECTORY -@param[in] shared_space Table uses a General Shared Tablespace @param[in] page_compression Table uses page compression @param[in] page_compression_level used compression level @param[in] not_used For future */ @@ -1004,7 +983,6 @@ dict_tf_init( ulint zip_ssize, bool atomic_blobs, bool data_dir, - bool shared_space, bool page_compressed, ulint page_compression_level, ulint not_used) @@ -1027,10 +1005,6 @@ dict_tf_init( flags |= (1 << DICT_TF_POS_DATA_DIR); } - if (shared_space) { - flags |= (1 << DICT_TF_POS_SHARED_SPACE); - } - if (page_compressed) { flags |= (1 << DICT_TF_POS_ATOMIC_BLOBS) | (1 << DICT_TF_POS_PAGE_COMPRESSION) @@ -1073,8 +1047,7 @@ dict_sys_tables_type_to_tf( | DICT_TF_MASK_ATOMIC_BLOBS | DICT_TF_MASK_DATA_DIR | DICT_TF_MASK_PAGE_COMPRESSION - | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL - | DICT_TF_MASK_SHARED_SPACE); + | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL); ut_ad(!DICT_TF_GET_ZIP_SSIZE(flags) || DICT_TF_HAS_ATOMIC_BLOBS(flags)); return(flags); @@ -1109,8 +1082,7 @@ dict_tf_to_sys_tables_type( | DICT_TF_MASK_ATOMIC_BLOBS | DICT_TF_MASK_DATA_DIR | DICT_TF_MASK_PAGE_COMPRESSION - | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL - | DICT_TF_MASK_SHARED_SPACE); + | DICT_TF_MASK_PAGE_COMPRESSION_LEVEL); return(type); } @@ -1744,18 +1716,6 @@ dict_table_is_temporary( return(DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)); } -/** Check if the table is in a shared tablespace (System or General). -@param[in] id Space ID to check -@return true if id is a shared tablespace, false if not. */ -UNIV_INLINE -bool -dict_table_in_shared_tablespace( - const dict_table_t* table) -{ - return(is_system_tablespace(table->space) - || DICT_TF_HAS_SHARED_SPACE(table->flags)); -} - /********************************************************************//** Turn-off redo-logging if temporary table. */ UNIV_INLINE @@ -1778,8 +1738,8 @@ A patch was added to v3.23.52 which initializes the MIX_LEN field to 0. Since file-per-table tablespaces were added in 4.1, any SYS_TABLES record with a non-zero space ID will have a reliable MIX_LEN field. However, this test does not use flags2 from SYS_TABLES.MIX_LEN. Instead, -assume that if the tablespace is not a predefined system tablespace and it -is not a general shared tablespace, then it must be file-per-table. +assume that if the tablespace is not a predefined system tablespace, + then it must be file-per-table. Also, during ALTER TABLE, the DICT_TF2_USE_FILE_PER_TABLE flag may not be set on one of the file-per-table tablespaces. This test cannot be done on a table in the process of being created @@ -1792,8 +1752,7 @@ dict_table_is_file_per_table( const dict_table_t* table) /*!< in: table to check */ { bool is_file_per_table = - !is_system_tablespace(table->space) - && !DICT_TF_HAS_SHARED_SPACE(table->flags); + !is_system_tablespace(table->space); /* If the table is file-per-table and it is not redundant, then it should have the flags2 bit for DICT_TF2_USE_FILE_PER_TABLE. */ @@ -1801,7 +1760,7 @@ dict_table_is_file_per_table( || !DICT_TF_GET_COMPACT(table->flags) || DICT_TF2_FLAG_IS_SET(table, DICT_TF2_USE_FILE_PER_TABLE)); - return(is_file_per_table ); + return(is_file_per_table); } /** Get reference count. @@ -1833,20 +1792,6 @@ dict_table_t::release() --n_ref_count; } -/** Check if tablespace name is "innodb_general". -@param[in] tablespace_name tablespace name -@retval true if name is "innodb_general" -@retval false if name is not "innodb_general" */ -inline -bool -dict_table_has_temp_general_tablespace_name( - const char* tablespace_name) { - - return(tablespace_name != NULL - && strncmp(tablespace_name, general_space_name, - strlen(general_space_name)) == 0); -} - /** Encode the number of columns and number of virtual columns in a 4 bytes value. We could do this because the number of columns in InnoDB is limited to 1017 diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index 6d01c38c432..0a862bb17a9 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -201,15 +202,6 @@ dict_get_and_save_data_dir_path( dict_table_t* table, bool dict_mutex_own); -/** Make sure the tablespace name is saved in dict_table_t if needed. -Try to read it from the file dictionary first, then from SYS_TABLESPACES. -@param[in] table Table object -@param[in] dict_mutex_own) true if dict_sys->mutex is owned already */ -void -dict_get_and_save_space_name( - dict_table_t* table, - bool dict_mutex_own); - /** Loads a table definition and also all its index definitions, and also the cluster definition if the table is a member in a cluster. Also loads all foreign key constraints where the foreign key is in the table or where diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 68d2f5d07fa..6717e7085c2 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -137,12 +137,8 @@ This flag prevents older engines from attempting to open the table and allows InnoDB to update_create_info() accordingly. */ #define DICT_TF_WIDTH_DATA_DIR 1 -/** Width of the SHARED tablespace flag. -It is used to identify tables that exist inside a shared general tablespace. -If a table is created with the TABLESPACE=tsname option, an older engine will -not be able to find that table. This flag prevents older engines from attempting -to open the table and allows InnoDB to quickly find the tablespace. */ - +/** Width of the SHARED tablespace flag (Oracle MYSQL 5.7). +Not supported by MariaDB. */ #define DICT_TF_WIDTH_SHARED_SPACE 1 /** @@ -226,10 +222,6 @@ DEFAULT=0, ON = 1, OFF = 2 #define DICT_TF_MASK_DATA_DIR \ ((~(~0U << DICT_TF_WIDTH_DATA_DIR)) \ << DICT_TF_POS_DATA_DIR) -/** Bit mask of the SHARED_SPACE field */ -#define DICT_TF_MASK_SHARED_SPACE \ - ((~(~0U << DICT_TF_WIDTH_SHARED_SPACE)) \ - << DICT_TF_POS_SHARED_SPACE) /** Bit mask of the PAGE_COMPRESSION field */ #define DICT_TF_MASK_PAGE_COMPRESSION \ ((~(~0U << DICT_TF_WIDTH_PAGE_COMPRESSION)) \ @@ -267,10 +259,6 @@ DEFAULT=0, ON = 1, OFF = 2 #define DICT_TF_HAS_DATA_DIR(flags) \ ((flags & DICT_TF_MASK_DATA_DIR) \ >> DICT_TF_POS_DATA_DIR) -/** Return the value of the SHARED_SPACE field */ -#define DICT_TF_HAS_SHARED_SPACE(flags) \ - ((flags & DICT_TF_MASK_SHARED_SPACE) \ - >> DICT_TF_POS_SHARED_SPACE) /** Return the value of the PAGE_COMPRESSION field */ #define DICT_TF_GET_PAGE_COMPRESSION(flags) \ ((flags & DICT_TF_MASK_PAGE_COMPRESSION) \ @@ -307,7 +295,8 @@ for unknown bits in order to protect backward incompatibility. */ /* @{ */ /** Total number of bits in table->flags2. */ #define DICT_TF2_BITS 9 -#define DICT_TF2_UNUSED_BIT_MASK (~0U << DICT_TF2_BITS) +#define DICT_TF2_UNUSED_BIT_MASK (~0U << DICT_TF2_BITS | \ + 1U << DICT_TF_POS_SHARED_SPACE) #define DICT_TF2_BIT_MASK ~DICT_TF2_UNUSED_BIT_MASK /** TEMPORARY; TRUE for tables from CREATE TEMPORARY TABLE. */ @@ -1395,10 +1384,6 @@ struct dict_table_t { /** NULL or the directory path specified by DATA DIRECTORY. */ char* data_dir_path; - /** NULL or the tablespace name that this table is assigned to, - specified by the TABLESPACE option.*/ - id_name_t tablespace; - /** Space where the clustered index of the table is placed. */ uint32_t space; diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 0788f84d11a..eebe21d85bf 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -38,8 +38,6 @@ Created 10/25/1995 Heikki Tuuri #include #include -extern const char general_space_name[]; - // Forward declaration struct trx_t; class page_id_t; @@ -256,101 +254,10 @@ extern const char* dot_ext[]; #define DOT_ISL dot_ext[ISL] #define DOT_CFG dot_ext[CFG] -/** Wrapper for a path to a directory. -This folder may or may not yet esist. Since not all directory paths -end in "/", we should only use this for a directory path or a filepath -that has a ".ibd" extension. */ -class Folder -{ -public: - /** Default constructor */ - Folder() : m_folder(NULL) {} - - /** Constructor - @param[in] path pathname (not necessarily NUL-terminated) - @param[in] len length of the path, in bytes */ - Folder(const char* path, size_t len); - - /** Assignment operator - @param[in] folder folder string provided */ - class Folder& operator=(const char* path); - - /** Destructor */ - ~Folder() - { - ut_free(m_folder); - } - - /** Implicit type conversion - @return the wrapped object */ - operator const char*() const - { - return(m_folder); - } - - /** Explicit type conversion - @return the wrapped object */ - const char* operator()() const - { - return(m_folder); - } - - /** return the length of m_folder - @return the length of m_folder */ - size_t len() - { - return m_folder_len; - } - - /** Determine if two folders are equal - @param[in] other folder to compare to - @return whether the folders are equal */ - bool operator==(const Folder& other) const; - - /** Determine if the left folder is the same or an ancestor of - (contains) the right folder. - @param[in] other folder to compare to - @return whether this is the same or an ancestor or the other folder. */ - bool operator>=(const Folder& other) const; - - /** Determine if the left folder is an ancestor of (contains) - the right folder. - @param[in] other folder to compare to - @return whether this is an ancestor of the other folder */ - bool operator>(const Folder& other) const; - - /** Determine if the directory referenced by m_folder exists. - @return whether the directory exists */ - bool exists(); - -private: - /** Build the basic folder name from the path and length provided - @param[in] path pathname (not necessarily NUL-terminated) - @param[in] len length of the path, in bytes */ - void make_path(const char* path, size_t len); - - /** Resolve a relative path in m_folder to an absolute path - in m_abs_path setting m_abs_len. */ - void make_abs_path(); - - /** The wrapped folder string */ - char* m_folder; - - /** Length of m_folder */ - size_t m_folder_len; - - /** A full absolute path to the same file. */ - char m_abs_path[FN_REFLEN + 2]; - - /** Length of m_abs_path to the deepest folder */ - size_t m_abs_len; -}; - /** When mysqld is run, the default directory "." is the mysqld datadir, but in the MySQL Embedded Server Library and mysqlbackup it is not the default directory, and we must set the base file path explicitly */ extern const char* fil_path_to_mysql_datadir; -extern Folder folder_mysql_datadir; /** Initial size of a single-table tablespace in pages */ #define FIL_IBD_FILE_INITIAL_SIZE 4 @@ -1052,7 +959,6 @@ fil_make_filepath( /** Creates a new General or Single-Table tablespace @param[in] space_id Tablespace ID @param[in] name Tablespace name in dbname/tablename format. -For general tablespaces, the 'dbname/' part may be missing. @param[in] path Path and filename of the datafile to create. @param[in] flags Tablespace flags @param[in] size Initial size of the tablespace file in pages, diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 610c4e9927b..5129c63108a 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -220,9 +220,8 @@ public: void set_filepath(const char* filepath); /** Allocate and set the datafile or tablespace name in m_name. - If a name is provided, use it; else if the datafile is file-per-table, - extract a file-per-table tablespace name from m_filepath; else it is a - general tablespace, so just call it that for now. The value of m_name + If a name is provided, use it; else extract a file-per-table + tablespace name from m_filepath. The value of m_name will be freed in the destructor. @param[in] name Tablespace Name if known, NULL if not */ void set_name(const char* name); @@ -559,13 +558,10 @@ public: the path ".". @param[in] name tablespace name @param[in] filepath remote filepath of tablespace datafile - @param[in] is_shared true for general tablespace, - false for file-per-table @return DB_SUCCESS or error code */ static dberr_t create_link_file( const char* name, - const char* filepath, - bool is_shared = false); + const char* filepath); /** Delete an InnoDB Symbolic Link (ISL) file by name. @param[in] name tablespace name */ @@ -575,8 +571,6 @@ public: It is always created under the datadir of MySQL. For file-per-table tablespaces, the isl file is expected to be in a 'database' directory and called 'tablename.isl'. - For general tablespaces, there will be no 'database' directory. - The 'basename.isl' will be in the datadir. The caller must free the memory returned if it is not null. @param[in] link_filepath filepath of the ISL file @return Filepath of the IBD file read from the ISL file */ diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index edfb1bb47ef..129842982a3 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -274,7 +274,7 @@ fsp_header_get_tablespace_size(void); /*================================*/ /** Calculate the number of pages to extend a datafile. -We extend single-table and general tablespaces first one extent at a time, +We extend single-table tablespaces first one extent at a time, but 4 at a time for bigger tablespaces. It is not enough to extend always by one extent, because we need to add at least one extent to FSP_FREE. A single extent descriptor page will track many extents. And the extent @@ -644,21 +644,10 @@ bool fsp_flags_is_compressed( ulint flags); -/** Determine if two tablespaces are equivalent or compatible. -@param[in] flags1 First tablespace flags -@param[in] flags2 Second tablespace flags -@return true the flags are compatible, false if not */ -UNIV_INLINE -bool -fsp_flags_are_equal( - ulint flags1, - ulint flags2); - /** Initialize an FSP flags integer. @param[in] page_size page sizes in bytes and compression flag. @param[in] atomic_blobs Used by Dynammic and Compressed. @param[in] has_data_dir This tablespace is in a remote location. -@param[in] is_shared This tablespace can be shared by many tables. @param[in] is_temporary This tablespace is temporary. @return tablespace flags after initialization */ UNIV_INLINE @@ -667,7 +656,6 @@ fsp_flags_init( const page_size_t& page_size, bool atomic_blobs, bool has_data_dir, - bool is_shared, bool is_temporary, bool page_compression, ulint page_compression_level, diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index 7f50bddb662..9ff2dab75d4 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 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 @@ -53,40 +53,6 @@ fsp_flags_is_compressed( #define ACTUAL_SSIZE(ssize) (0 == ssize ? UNIV_PAGE_SSIZE_ORIG : ssize) -/** Determine if two tablespaces are equivalent or compatible. -@param[in] flags1 First tablespace flags -@param[in] flags2 Second tablespace flags -@return true the flags are compatible, false if not */ -UNIV_INLINE -bool -fsp_flags_are_equal( - ulint flags1, - ulint flags2) -{ - /* If either one of these flags is ULINT_UNDEFINED, - then they are not equal */ - if (flags1 == ULINT_UNDEFINED || flags2 == ULINT_UNDEFINED) { - return(false); - } - - if (!fsp_is_shared_tablespace(flags1) || !fsp_is_shared_tablespace(flags2)) { - /* At least one of these is a single-table tablespaces so all - flags must match. */ - return(flags1 == flags2); - } - - /* Both are shared tablespaces which can contain all formats. - But they must have the same logical and physical page size. - Once InnoDB can support multiple page sizes together, - the logical page size will not matter. */ - ulint zip_ssize1 = ACTUAL_SSIZE(FSP_FLAGS_GET_ZIP_SSIZE(flags1)); - ulint zip_ssize2 = ACTUAL_SSIZE(FSP_FLAGS_GET_ZIP_SSIZE(flags2)); - ulint page_ssize1 = ACTUAL_SSIZE(FSP_FLAGS_GET_PAGE_SSIZE(flags1)); - ulint page_ssize2 = ACTUAL_SSIZE(FSP_FLAGS_GET_PAGE_SSIZE(flags2)); - - return(zip_ssize1 == zip_ssize2 && page_ssize1 == page_ssize2); -} - /** Convert a page size, which is a power of 2, to an ssize, which is the number of bit shifts from 512 to make that page size. @param[in] page_size compressed page size in bytes @@ -179,7 +145,6 @@ fsp_flags_set_page_size( @param[in] page_size page sizes in bytes and compression flag. @param[in] atomic_blobs Used by Dynammic and Compressed. @param[in] has_data_dir This tablespace is in a remote location. -@param[in] is_shared This tablespace can be shared by many tables. @param[in] is_temporary This tablespace is temporary. @param[in] page_compressed Table uses page compression @param[in] page_compression_level Page compression level @@ -191,7 +156,6 @@ fsp_flags_init( const page_size_t& page_size, bool atomic_blobs, bool has_data_dir, - bool is_shared, bool is_temporary, bool page_compression, ulint page_compression_level, @@ -217,13 +181,6 @@ fsp_flags_init( flags |= FSP_FLAGS_MASK_DATA_DIR; } - /* Shared tablespaces can hold all row formats, so we only mark the - POST_ANTELOPE and ATOMIC_BLOB bits if it is compressed. */ - if (is_shared) { - ut_ad(!has_data_dir); - flags |= FSP_FLAGS_MASK_SHARED; - } - if (is_temporary) { ut_ad(!has_data_dir); flags |= FSP_FLAGS_MASK_TEMPORARY; diff --git a/storage/innobase/include/fsp0space.h b/storage/innobase/include/fsp0space.h index 31a1a4abc75..6ecca6211ed 100644 --- a/storage/innobase/include/fsp0space.h +++ b/storage/innobase/include/fsp0space.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -18,7 +19,7 @@ this program; if not, write to the Free Software Foundation, Inc., /**************************************************//** @file include/fsp0space.h -General shared tablespace implementation. +Shared tablespace interface Created 2013-7-26 by Kevin Lewis *******************************************************/ @@ -61,10 +62,6 @@ public: shutdown(); ut_ad(m_files.empty()); ut_ad(m_space_id == ULINT_UNDEFINED); - if (m_name != NULL) { - ut_free(m_name); - m_name = NULL; - } if (m_path != NULL) { ut_free(m_path); m_path = NULL; @@ -75,21 +72,8 @@ public: Tablespace(const Tablespace&); Tablespace& operator=(const Tablespace&); - /** Set tablespace name - @param[in] name tablespace name */ - void set_name(const char* name) - { - ut_ad(m_name == NULL); - m_name = mem_strdup(name); - ut_ad(m_name != NULL); - } - - /** Get tablespace name - @return tablespace name */ - const char* name() const - { - return(m_name); - } + void set_name(const char* name) { m_name = name; } + const char* name() const { return m_name; } /** Set tablespace path and filename members. @param[in] path where tablespace file(s) resides @@ -236,7 +220,7 @@ private: /* DATA MEMBERS */ /** Name of the tablespace. */ - char* m_name; + const char* m_name; /** Tablespace ID */ ulint m_space_id; diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h index 9bbe58bb1dd..1c535677e83 100644 --- a/storage/innobase/include/fsp0types.h +++ b/storage/innobase/include/fsp0types.h @@ -216,15 +216,6 @@ bool fsp_is_checksum_disabled( ulint space_id); -/** Check if tablespace is file-per-table. -@param[in] space_id Tablespace ID -@param[in] fsp_flags Tablespace Flags -@return true if tablespace is file-per-table. */ -bool -fsp_is_file_per_table( - ulint space_id, - ulint fsp_flags); - #ifdef UNIV_DEBUG /** Skip some of the sanity checks that are time consuming even in debug mode and can affect frequent verification runs that are done to ensure stability of @@ -343,10 +334,6 @@ is a tablespace with encryption. */ #define FSP_FLAGS_MASK_DATA_DIR \ ((~(~0U << FSP_FLAGS_WIDTH_DATA_DIR)) \ << FSP_FLAGS_POS_DATA_DIR) -/** Bit mask of the SHARED field */ -#define FSP_FLAGS_MASK_SHARED \ - ((~(~0U << FSP_FLAGS_WIDTH_SHARED)) \ - << FSP_FLAGS_POS_SHARED) /** Bit mask of the TEMPORARY field */ #define FSP_FLAGS_MASK_TEMPORARY \ ((~(~0U << FSP_FLAGS_WIDTH_TEMPORARY)) \ @@ -384,10 +371,6 @@ is a tablespace with encryption. */ #define FSP_FLAGS_HAS_DATA_DIR(flags) \ ((flags & FSP_FLAGS_MASK_DATA_DIR) \ >> FSP_FLAGS_POS_DATA_DIR) -/** Return the contents of the SHARED field */ -#define FSP_FLAGS_GET_SHARED(flags) \ - ((flags & FSP_FLAGS_MASK_SHARED) \ - >> FSP_FLAGS_POS_SHARED) /** Return the contents of the TEMPORARY field */ #define FSP_FLAGS_GET_TEMPORARY(flags) \ ((flags & FSP_FLAGS_MASK_TEMPORARY) \ @@ -407,8 +390,6 @@ is a tablespace with encryption. */ #define FSP_FLAGS_GET_ATOMIC_WRITES(flags) \ ((flags & FSP_FLAGS_MASK_ATOMIC_WRITES) \ >> FSP_FLAGS_POS_ATOMIC_WRITES) -/** Use an alias in the code for FSP_FLAGS_GET_SHARED() */ -#define fsp_is_shared_tablespace FSP_FLAGS_GET_SHARED /* @} */ /** Set a PAGE_COMPRESSION into the correct bits in a given diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 541fbe24d82..866853e6059 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -49,7 +49,6 @@ struct fts_string_t; #undef MYSQL_REPLACE_TRX_IN_THD #undef MYSQL_SPATIAL_INDEX #undef MYSQL_STORE_FTS_DOC_ID -#undef MYSQL_TABLESPACES /*********************************************************************//** Wrapper around MySQL's copy_and_convert function. diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 21bcd381c87..0bc4fe4def9 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4050,14 +4050,12 @@ row_drop_table_for_mysql( bool is_temp; bool ibd_file_missing; bool is_discarded; - bool shared_tablespace; case DB_SUCCESS: space_id = table->space; ibd_file_missing = table->ibd_file_missing; is_discarded = dict_table_is_discarded(table); is_temp = dict_table_is_temporary(table); - shared_tablespace = DICT_TF_HAS_SHARED_SPACE(table->flags); /* If there is a temp path then the temp flag is set. However, during recovery, we might have a temp flag but @@ -4086,7 +4084,7 @@ row_drop_table_for_mysql( filepath = fil_make_filepath( table->dir_path_of_temp_table, NULL, IBD, false); - } else if (!shared_tablespace) { + } else { filepath = fil_make_filepath( NULL, table->name.m_name, IBD, false); } @@ -4098,8 +4096,8 @@ row_drop_table_for_mysql( } /* Do not attempt to drop known-to-be-missing tablespaces, - nor system or shared general tablespaces. */ - if (is_discarded || ibd_file_missing || shared_tablespace + nor the system tablespace. */ + if (is_discarded || ibd_file_missing || is_system_tablespace(space_id)) { break; } diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index 828b126309f..d26d81c9239 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -649,15 +649,6 @@ row_quiesce_set_state( ER_TABLE_IN_SYSTEM_TABLESPACE, table_name); return(DB_UNSUPPORTED); - - } else if (DICT_TF_HAS_SHARED_SPACE(table->flags)) { - std::ostringstream err_msg; - err_msg << "FLUSH TABLES FOR EXPORT on table " << table->name - << " in a general tablespace."; - ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN, - ER_NOT_SUPPORTED_YET, err_msg.str().c_str()); - - return(DB_UNSUPPORTED); } else if (row_quiesce_table_has_fts_index(table)) { ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN, diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index 2d5ba6781d4..b372da4b939 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -1309,7 +1310,6 @@ row_truncate_fts( fts_table.name = table->name; fts_table.flags2 = table->flags2; fts_table.flags = table->flags; - fts_table.tablespace = table->tablespace; fts_table.space = table->space; /* table->data_dir_path is used for FTS AUX table @@ -1320,20 +1320,6 @@ row_truncate_fts( ut_ad(table->data_dir_path != NULL); } - /* table->tablespace() may not be always populated or - if table->tablespace() uses "innodb_general" name, - fetch the real name. */ - if (DICT_TF_HAS_SHARED_SPACE(table->flags) - && (table->tablespace() == NULL - || dict_table_has_temp_general_tablespace_name( - table->tablespace()))) { - dict_get_and_save_space_name(table, true); - ut_ad(table->tablespace() != NULL); - ut_ad(!dict_table_has_temp_general_tablespace_name( - table->tablespace())); - } - - fts_table.tablespace = table->tablespace(); fts_table.data_dir_path = table->data_dir_path; dberr_t err; @@ -1604,8 +1590,6 @@ row_truncate_prepare(dict_table_t* table, ulint* flags) dict_get_and_save_data_dir_path(table, true); - dict_get_and_save_space_name(table, true); - if (*flags != ULINT_UNDEFINED) { dberr_t err = fil_prepare_for_truncate(table->space); @@ -2212,76 +2196,52 @@ truncate_t::fixup_tables_in_non_system_tablespace() done and erased from this list. */ ut_a((*it)->m_space_id != TRX_SYS_SPACE); - /* Step-1: Drop tablespace (only for single-tablespace), - drop indexes and re-create indexes. */ + /* Drop tablespace, drop indexes and re-create indexes. */ - if (fsp_is_file_per_table((*it)->m_space_id, - (*it)->m_tablespace_flags)) { - /* The table is file_per_table */ + ib::info() << "Completing truncate for table with " + "id (" << (*it)->m_old_table_id << ") " + "residing in file-per-table tablespace with " + "id (" << (*it)->m_space_id << ")"; - ib::info() << "Completing truncate for table with " - "id (" << (*it)->m_old_table_id << ") " - "residing in file-per-table tablespace with " - "id (" << (*it)->m_space_id << ")"; + if (!fil_space_get((*it)->m_space_id)) { - if (!fil_space_get((*it)->m_space_id)) { + /* Create the database directory for name, + if it does not exist yet */ + fil_create_directory_for_tablename( + (*it)->m_tablename); - /* Create the database directory for name, - if it does not exist yet */ - fil_create_directory_for_tablename( - (*it)->m_tablename); + err = fil_ibd_create( + (*it)->m_space_id, + (*it)->m_tablename, + (*it)->m_dir_path, + (*it)->m_tablespace_flags, + FIL_IBD_FILE_INITIAL_SIZE, + (*it)->m_encryption, + (*it)->m_key_id); - err = fil_ibd_create( - (*it)->m_space_id, - (*it)->m_tablename, - (*it)->m_dir_path, - (*it)->m_tablespace_flags, - FIL_IBD_FILE_INITIAL_SIZE, - (*it)->m_encryption, - (*it)->m_key_id); - - if (err != DB_SUCCESS) { - /* If checkpoint is not yet done - and table is dropped and then we might - still have REDO entries for this table - which are INVALID. Ignore them. */ - ib::warn() << "Failed to create" - " tablespace for " - << (*it)->m_space_id - << " space-id"; - err = DB_ERROR; - break; - } + if (err != DB_SUCCESS) { + /* If checkpoint is not yet done + and table is dropped and then we might + still have REDO entries for this table + which are INVALID. Ignore them. */ + ib::warn() << "Failed to create" + " tablespace for " + << (*it)->m_space_id + << " space-id"; + err = DB_ERROR; + break; } - - ut_ad(fil_space_get((*it)->m_space_id)); - - err = fil_recreate_tablespace( - (*it)->m_space_id, - (*it)->m_format_flags, - (*it)->m_tablespace_flags, - (*it)->m_tablename, - **it, log_get_lsn()); - - } else { - /* Table is in a shared tablespace */ - - ib::info() << "Completing truncate for table with " - "id (" << (*it)->m_old_table_id << ") " - "residing in shared tablespace with " - "id (" << (*it)->m_space_id << ")"; - - /* Temp-tables in temp-tablespace are never restored.*/ - ut_ad((*it)->m_space_id != SRV_TMP_SPACE_ID); - - err = fil_recreate_table( - (*it)->m_space_id, - (*it)->m_format_flags, - (*it)->m_tablespace_flags, - (*it)->m_tablename, - **it); } + ut_ad(fil_space_get((*it)->m_space_id)); + + err = fil_recreate_tablespace( + (*it)->m_space_id, + (*it)->m_format_flags, + (*it)->m_tablespace_flags, + (*it)->m_tablename, + **it, log_get_lsn()); + /* Step-2: Update the SYS_XXXX tables to reflect new table-id and root_page_no. */ table_id_t new_id; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 2fa7a02e85e..5d478e4529f 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -3157,11 +3157,6 @@ srv_was_tablespace_truncated(const fil_space_t* space) return(false); } - bool has_shared_space = FSP_FLAGS_GET_SHARED(space->flags); - - if (is_system_tablespace(space->id) || has_shared_space) { - return(false); - } - - return(truncate_t::was_tablespace_truncated(space->id)); + return (!is_system_tablespace(space->id) + && truncate_t::was_tablespace_truncated(space->id)); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index dfed856b051..ddc766accd4 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -692,7 +692,7 @@ srv_undo_tablespace_open( /* Set the compressed page size to 0 (non-compressed) */ flags = fsp_flags_init( - univ_page_size, false, false, false, false, false, 0, 0); + univ_page_size, false, false, false, false, 0, 0); space = fil_space_create( undo_name, space_id, flags, FIL_TYPE_TABLESPACE, NULL, true); diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 9eb11c913c5..d43735bba2e 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -756,9 +756,6 @@ ut_strerr( case DB_FORCED_ABORT: return("Transaction aborted by another higher priority " "transaction"); - case DB_WRONG_FILE_NAME: - return("Invalid Filename"); - case DB_COMPUTE_VALUE_FAILED: return("Compute generated column failed"); case DB_NO_FK_ON_S_BASE_COL: From 7cf97ed4ee93f7df6d021ad54b9f09964a943c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 17 Jan 2017 11:37:49 +0200 Subject: [PATCH 087/167] =?UTF-8?q?MDEV-11816=20Disallow=20CREATE=20TEMPOR?= =?UTF-8?q?ARY=20TABLE=E2=80=A6ROW=5FFORMAT=3DCOMPRESSED?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MySQL 5.7 allows temporary tables to be created in ROW_FORMAT=COMPRESSED. The usefulness of this is questionable. WL#7899 in MySQL 8.0.0 prevents the creation of such compressed tables, so that all InnoDB temporary tables will be located inside the predefined InnoDB temporary tablespace. Pick up and adjust some tests from MySQL 5.7 and 8.0. dict_tf_to_fsp_flags(): Remove the parameter is_temp. fsp_flags_init(): Remove the parameter is_temporary. row_mysql_drop_temp_tables(): Remove. There cannot be any temporary tables in InnoDB. (This never removed #sql* tables in the datadir which were created by DDL.) dict_table_t::dir_path_of_temp_table: Remove. create_table_info_t::m_temp_path: Remove. create_table_info_t::create_options_are_invalid(): Do not allow ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE for temporary tables. create_table_info_t::innobase_table_flags(): Do not unnecessarily prevent CREATE TEMPORARY TABLE with SPATIAL INDEX. (MySQL 5.7 does allow this.) fil_space_belongs_in_lru(): The only FIL_TYPE_TEMPORARY tablespace is never subjected to closing least-recently-used files. --- mysql-test/suite/innodb/include/dml_ops.inc | 82 + .../r/temp_table.result} | 17 +- .../r/temp_table_savepoint.result} | 173 +- .../suite/innodb/r/temporary_table.result | 639 +++++ .../r/temporary_table_optimization.result | 266 +++ .../t/temp_table.test} | 30 +- .../t/temp_table_savepoint.test} | 193 +- .../suite/innodb/t/temporary_table.test | 445 ++++ .../innodb/t/temporary_table_optimization.opt | 1 + .../t/temporary_table_optimization.test | 243 ++ .../include/innodb_temp_table_dml.inc | 40 - .../suite/innodb_zip/r/wl6501_scale_1.result | 268 +-- mysql-test/suite/innodb_zip/r/wl6915_1.result | 2079 ----------------- mysql-test/suite/innodb_zip/t/disabled.def | 14 - .../suite/innodb_zip/t/wl6501_scale_1.test | 4 - mysql-test/suite/innodb_zip/t/wl6560.test | 422 ---- mysql-test/suite/innodb_zip/t/wl6915_1.test | 650 ------ sql/share/errmsg-utf8.txt | 2 + storage/innobase/btr/btr0btr.cc | 3 +- storage/innobase/btr/btr0cur.cc | 23 +- storage/innobase/dict/dict0crea.cc | 17 +- storage/innobase/dict/dict0dict.cc | 18 +- storage/innobase/dict/dict0load.cc | 17 +- storage/innobase/fil/fil0fil.cc | 40 +- storage/innobase/fsp/fsp0file.cc | 5 +- storage/innobase/handler/ha_innodb.cc | 117 +- storage/innobase/handler/ha_innodb.h | 10 +- storage/innobase/handler/ha_innopart.cc | 4 - storage/innobase/handler/handler0alter.cc | 1 - storage/innobase/include/dict0dict.h | 5 +- storage/innobase/include/dict0mem.h | 6 - storage/innobase/include/fil0fil.h | 8 +- storage/innobase/include/fsp0fsp.h | 5 +- storage/innobase/include/fsp0fsp.ic | 7 - storage/innobase/include/row0mysql.h | 5 - storage/innobase/log/log0recv.cc | 2 - storage/innobase/page/page0page.cc | 1 + storage/innobase/page/page0zip.cc | 6 +- storage/innobase/row/row0import.cc | 2 +- storage/innobase/row/row0mysql.cc | 137 +- storage/innobase/row/row0trunc.cc | 7 +- storage/innobase/srv/srv0start.cc | 2 +- 42 files changed, 2028 insertions(+), 3988 deletions(-) create mode 100644 mysql-test/suite/innodb/include/dml_ops.inc rename mysql-test/suite/{innodb_zip/r/wl6470_1.result => innodb/r/temp_table.result} (96%) rename mysql-test/suite/{innodb_zip/r/wl6470_2.result => innodb/r/temp_table_savepoint.result} (73%) create mode 100644 mysql-test/suite/innodb/r/temporary_table.result create mode 100644 mysql-test/suite/innodb/r/temporary_table_optimization.result rename mysql-test/suite/{innodb_zip/t/wl6470_1.test => innodb/t/temp_table.test} (74%) rename mysql-test/suite/{innodb_zip/t/wl6470_2.test => innodb/t/temp_table_savepoint.test} (67%) create mode 100644 mysql-test/suite/innodb/t/temporary_table.test create mode 100644 mysql-test/suite/innodb/t/temporary_table_optimization.opt create mode 100644 mysql-test/suite/innodb/t/temporary_table_optimization.test delete mode 100644 mysql-test/suite/innodb_zip/include/innodb_temp_table_dml.inc delete mode 100644 mysql-test/suite/innodb_zip/r/wl6915_1.result delete mode 100644 mysql-test/suite/innodb_zip/t/disabled.def delete mode 100644 mysql-test/suite/innodb_zip/t/wl6560.test delete mode 100644 mysql-test/suite/innodb_zip/t/wl6915_1.test diff --git a/mysql-test/suite/innodb/include/dml_ops.inc b/mysql-test/suite/innodb/include/dml_ops.inc new file mode 100644 index 00000000000..4908dfb6bee --- /dev/null +++ b/mysql-test/suite/innodb/include/dml_ops.inc @@ -0,0 +1,82 @@ +delimiter |; +create procedure populate_t1() +begin + declare i int default 1; + while (i <= 200) do + insert into t1 values (i, 'a', 'b'); + set i = i + 1; + end while; +end| +create procedure populate_t1_small() +begin + declare i int default 1; + while (i <= 20) do + insert into t1 values (i, 'c', 'd'); + set i = i + 1; + end while; +end| +create procedure populate_t1_small2() +begin + declare i int default 30; + while (i <= 50) do + insert into t1 values (i, 'e', 'f'); + set i = i + 1; + end while; +end| +delimiter ;| +# +begin; +select count(*) from t1; +call populate_t1(); +select count(*) from t1; +select * from t1 limit 10; +rollback; +select count(*) from t1; +# +begin; +call populate_t1(); +select count(*) from t1; +commit; +select count(*) from t1; +# +truncate table t1; +select count(*) from t1; +# +call populate_t1_small(); +select count(*) from t1; +rollback; +select count(*) from t1; +truncate table t1; +# +call populate_t1(); +select count(*) from t1; +delete from t1 where keyc <= 60; +select count(*) from t1; +call populate_t1_small(); +select count(*) from t1; +select * from t1 limit 10; +begin; +call populate_t1_small2(); +select count(*) from t1; +select * from t1 where keyc > 30 limit 10; +rollback; +select count(*) from t1; +select * from t1 where keyc > 30 limit 10; +# +update t1 set keyc = keyc + 2000; +select * from t1 limit 10; +rollback; +begin; +update t1 set keyc = keyc + 2000; +select * from t1 limit 10; +rollback; +select * from t1 limit 10; +commit; +select * from t1 limit 10; +# +insert into t2 select * from t1 where keyc < 2101; +select count(*) from t2; +# +drop procedure populate_t1; +drop procedure populate_t1_small; +drop procedure populate_t1_small2; diff --git a/mysql-test/suite/innodb_zip/r/wl6470_1.result b/mysql-test/suite/innodb/r/temp_table.result similarity index 96% rename from mysql-test/suite/innodb_zip/r/wl6470_1.result rename to mysql-test/suite/innodb/r/temp_table.result index ea1866d69eb..e90da0d5e77 100644 --- a/mysql-test/suite/innodb_zip/r/wl6470_1.result +++ b/mysql-test/suite/innodb/r/temp_table.result @@ -194,18 +194,22 @@ count(*) drop procedure populate_t1; drop procedure populate_t1_small; drop procedure populate_t1_small2; -drop table t1; -drop table t2; +drop temporary table t1,t2; create temporary table t1 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) ) engine = innodb key_block_size = 4; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +create temporary table t1 +(keyc int, c1 char(100), c2 char(100), +primary key(keyc), index sec_index(c1) +) engine = innodb; set innodb_strict_mode=off; create temporary table t2 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) ) engine = innodb key_block_size = 8; -set innodb_strict_mode=default; +set innodb_strict_mode=on; create procedure populate_t1() begin declare i int default 1; @@ -394,9 +398,7 @@ count(*) drop procedure populate_t1; drop procedure populate_t1_small; drop procedure populate_t1_small2; -drop table t1; -drop table t2; -set global innodb_file_per_table = 0; +drop temporary table t1, t2; create temporary table t1 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) @@ -593,6 +595,3 @@ count(*) drop procedure populate_t1; drop procedure populate_t1_small; drop procedure populate_t1_small2; -drop table t1; -drop table t2; -set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6470_2.result b/mysql-test/suite/innodb/r/temp_table_savepoint.result similarity index 73% rename from mysql-test/suite/innodb_zip/r/wl6470_2.result rename to mysql-test/suite/innodb/r/temp_table_savepoint.result index b001cd73882..d61eef404da 100644 --- a/mysql-test/suite/innodb_zip/r/wl6470_2.result +++ b/mysql-test/suite/innodb/r/temp_table_savepoint.result @@ -2,8 +2,6 @@ create procedure populate_tables() begin declare n int default 20; declare inner_loop int default 100; -set global innodb_file_per_table=on; -drop table if exists t1,t2,t3,t4; create temporary table t1(c1 int not null, c2 int not null, c3 char(255) not null, @@ -14,7 +12,7 @@ c7 varchar(2000) not null, c8 datetime, c9 decimal(6,3), primary key (c1), -index (c3,c4(50),c5(50)), +index (c3,c4(50),c5(50)), index (c2)) engine=innodb row_format=redundant; create temporary table t2(c1 int not null, @@ -30,19 +28,6 @@ primary key (c1), index (c3,c4(50),c5(50)), index (c2)) engine=innodb row_format=compact; -create temporary table t3(c1 int not null, -c2 int not null, -c3 char(255) not null, -c4 text(6000) not null, -c5 blob(6000) not null, -c6 varchar(2000) not null, -c7 varchar(2000) not null, -c8 datetime, -c9 decimal(6,3), -primary key (c1), -index (c3,c4(50),c5(50)), -index (c2)) -engine=innodb row_format=compressed key_block_size=4; create temporary table t4(c1 int not null, c2 int not null, c3 char(255) not null, @@ -74,16 +59,12 @@ insert into t6 values (50),(100),(150),(190); while (n > 0) do start transaction; insert into t1 values(n,n,repeat(concat(' tc3_',n),30), -repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), -repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), +repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), +repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), now(),(100.55+n)); insert into t2 values(n,n,repeat(concat(' tc3_',n),30), -repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), -repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), -now(),(100.55+n)); -insert into t3 values(n,n,repeat(concat(' tc3_',n),30), -repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), -repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), +repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), +repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), now(),(100.55+n)); insert into t4 values(n,n,repeat(concat(' tc3_',n),30), repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), @@ -95,33 +76,27 @@ repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), now(),(100.55+n)); if (n > 10) then commit; -else +else delete from t1 where c1 > 10 ; delete from t2 where c1 > 10 ; -delete from t3 where c1 > 10 ; delete from t4 where c1 > 10 ; delete from t5 where c1 > 10 ; rollback; start transaction; update t1 set c1 = c1 + 1000 where c1 > 10; update t2 set c1 = c1 + 1000 where c1 > 10; -update t3 set c1 = c1 + 1000 where c1 > 10; update t4 set c1 = c1 + 1000 where c1 > 10; update t5 set c1 = c1 + 1000 where c1 > 10; rollback; -end if; +end if; start transaction; insert into t1 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), +repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), +repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t2 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), -now(),(100.55+n+inner_loop)); -insert into t3 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), +repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), +repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t4 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), @@ -133,26 +108,20 @@ repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245 now(),(100.55+n+inner_loop)); delete from t1 where c1 between 100 and 110; delete from t2 where c1 between 100 and 110; -delete from t3 where c1 between 100 and 110; delete from t4 where c1 between 100 and 110; delete from t5 where c1 between 100 and 110; -update t1 set c1 = c1+1 where c1>110; -update t2 set c1 = c1+1 where c1>110; -update t3 set c1 = c1+1 where c1>110; -update t4 set c1 = c1+1 where c1>110; -update t5 set c1 = c1+1 where c1>110; +update t1 set c1 = c1+1 where c1>110; +update t2 set c1 = c1+1 where c1>110; +update t4 set c1 = c1+1 where c1>110; +update t5 set c1 = c1+1 where c1>110; savepoint a; insert into t1 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), +repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), +repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t2 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), -now(),(100.55+n+inner_loop)); -insert into t3 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), +repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), +repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t4 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), @@ -164,16 +133,12 @@ repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245 now(),(100.55+n+inner_loop)); savepoint b; insert into t1 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), +repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), +repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t2 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), -now(),(100.55+n+inner_loop)); -insert into t3 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), -repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), -repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), +repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), +repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t4 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), @@ -189,16 +154,13 @@ rollback to a; commit; commit; rollback; -set n = n - 1; +set n = n - 1; end while; end| connect con1,localhost,root,,; +call populate_tables();; connect con2,localhost,root,,; -#---client 1 : dml operation ---" -connection con1; -#---client 2 : dml operation ---" -connection con2; -# In connection 1 +call populate_tables();; connection con1; select count(*) from t1; count(*) @@ -206,9 +168,6 @@ count(*) select count(*) from t2; count(*) 20 -select count(*) from t3; -count(*) -20 select count(*) from t4; count(*) 20 @@ -259,28 +218,6 @@ c1 136 138 140 -select c1 from t3; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 select c1 from t4; c1 11 @@ -325,7 +262,6 @@ c1 136 138 140 -# In connection 2 connection con2; select count(*) from t1; count(*) @@ -333,9 +269,6 @@ count(*) select count(*) from t2; count(*) 20 -select count(*) from t3; -count(*) -20 select count(*) from t4; count(*) 20 @@ -386,28 +319,6 @@ c1 136 138 140 -select c1 from t3; -c1 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 select c1 from t4; c1 11 @@ -452,7 +363,6 @@ c1 136 138 140 -# In connection 1 connection con1; set autocommit = 0; insert into t1 values (20,1,'a','a','a','a','a',now(),100.55); @@ -465,11 +375,6 @@ ERROR 23000: Duplicate entry '20' for key 'PRIMARY' insert ignore into t2 values (20,1,'a','a','a','a','a',now(),100.55); Warnings: Warning 1062 Duplicate entry '20' for key 'PRIMARY' -insert into t3 values (20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t3 values (20,1,'a','a','a','a','a',now(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' insert into t4 values (20,1,'a','a','a','a','a',now(),100.55); ERROR 23000: Duplicate entry '20' for key 'PRIMARY' insert ignore into t4 values (20,1,'a','a','a','a','a',now(),100.55); @@ -486,9 +391,6 @@ ERROR 23000: Duplicate entry '20' for key 'PRIMARY' insert into t2 values (1,1,'a','a','a','a','a',now(),100.55), (20,1,'a','a','a','a','a',now(),100.55); ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert into t3 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' insert into t4 values (1,1,'a','a','a','a','a',now(),100.55), (20,1,'a','a','a','a','a',now(),100.55); ERROR 23000: Duplicate entry '20' for key 'PRIMARY' @@ -502,9 +404,6 @@ c1 c2 select c1,c2 from t2 where c1 in (20,1); c1 c2 20 20 -select c1,c2 from t3 where c1 in (20,1); -c1 c2 -20 20 select c1,c2 from t4 where c1 in (20,1); c1 c2 20 20 @@ -513,7 +412,6 @@ c1 c2 20 20 replace into t1 values (20,1,'a','a','a','a','a',now(),100.55); replace into t2 values (20,1,'a','a','a','a','a',now(),100.55); -replace into t3 values (20,1,'a','a','a','a','a',now(),100.55); replace into t4 values (20,1,'a','a','a','a','a',now(),100.55); replace into t5 values (20,1,'a','a','a','a','a',now(),100.55); select c1,c2,c3,c4,c5,c6,c7,c9 from t1 where c1 = 20; @@ -522,9 +420,6 @@ c1 c2 c3 c4 c5 c6 c7 c9 select c1,c2,c3,c4,c5,c6,c7,c9 from t2 where c1 = 20; c1 c2 c3 c4 c5 c6 c7 c9 20 1 a a a a a 100.550 -select c1,c2,c3,c4,c5,c6,c7,c9 from t3 where c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 select c1,c2,c3,c4,c5,c6,c7,c9 from t4 where c1 = 20; c1 c2 c3 c4 c5 c6 c7 c9 20 1 a a a a a 100.550 @@ -533,7 +428,6 @@ c1 c2 c3 c4 c5 c6 c7 c9 20 1 a a a a a 100.550 update ignore t1 set c1 = 20 where c1 = 140 ; update ignore t2 set c1 = 20 where c1 = 140 ; -update ignore t3 set c1 = 20 where c1 = 140 ; update ignore t4 set c1 = 20 where c1 = 140 ; update ignore t5 set c1 = 20 where c1 = 140 ; select count(*) from t1 where c1 = 140; @@ -542,25 +436,22 @@ count(*) select count(*) from t2 where c1 = 140; count(*) 1 -select count(*) from t3 where c1 = 140; -count(*) -1 select count(*) from t4 where c1 = 140; count(*) 1 select count(*) from t5 where c1 = 140; count(*) 1 -"running select * into outfile from t1 ; +select * into outfile "VARDIR/tmp/t1.outfile" from t1; create temporary table temp_1 engine = innodb as select * from t1 where 1=2; select count(*) from temp_1; count(*) 0 -"running load data infile into temp_1 ; +load data infile 'VARDIR/tmp/t1.outfile' into table temp_1; select count(*) from temp_1; count(*) 20 -alter table temp_1 add column c10 int default 99 , +alter table temp_1 add column c10 int default 99 , add column c11 varchar(100) default 'test'; alter table temp_1 add primary key (c1); insert into temp_1 (c1,c2,c3,c4,c5,c6,c7,c8,c9) values (-1,-1,'a','a','a','a','a',now(),100.55); @@ -570,15 +461,12 @@ c1 c2 c3 c4 c5 c6 c7 c9 c10 c11 select count(*) from temp_1 where c10 = 99 and c11 like 'test'; count(*) 21 -insert into temp_1 (c1,c2,c3,c4,c5,c6,c7,c8,c9) values (-1,-1,'a','a','a','a','a',now(),100.55) +insert into temp_1 (c1,c2,c3,c4,c5,c6,c7,c8,c9) values (-1,-1,'a','a','a','a','a',now(),100.55) on duplicate key update c1=-2,c2=-2; select c1,c2,c3,c4,c5,c6,c7,c9,c10,c11 from temp_1 where c1 < 0; c1 c2 c3 c4 c5 c6 c7 c9 c10 c11 -2 -2 a a a a a 100.550 99 test -drop table t1 ,t2 ,t3,t4,t5,t6,temp_1; disconnect con1; -connection con2; -drop table t1 ,t2 ,t3,t4,t5,t6; disconnect con2; connection default; drop procedure populate_tables; @@ -664,4 +552,3 @@ count(*) drop prepare stm; drop prepare stm_1; drop prepare stm_2; -drop table prep_1; diff --git a/mysql-test/suite/innodb/r/temporary_table.result b/mysql-test/suite/innodb/r/temporary_table.result new file mode 100644 index 00000000000..1fb73f4e775 --- /dev/null +++ b/mysql-test/suite/innodb/r/temporary_table.result @@ -0,0 +1,639 @@ +# files in MYSQL_DATA_DIR +ibtmp1 +create temporary table t1 (i int, f float, c char(100)) engine=innodb; +insert into t1 values (100, 1.1, 'pune'); +insert into t1 values (99, 1.2, 'mumbai'); +insert into t1 values (98, 1.3, 'jaipur'); +insert into t1 values (97, 1.4, 'delhi'); +insert into t1 values (96, 1.5, 'ahmedabad'); +select * from t1; +i f c +100 1.1 pune +99 1.2 mumbai +98 1.3 jaipur +97 1.4 delhi +96 1.5 ahmedabad +select * from t1 where i = 98; +i f c +98 1.3 jaipur +select * from t1 where i < 100; +i f c +99 1.2 mumbai +98 1.3 jaipur +97 1.4 delhi +96 1.5 ahmedabad +explain select * from t1 where f > 1.29999; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where +alter table t1 add index sec_index(f); +explain select * from t1 where f > 1.29999; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL sec_index NULL NULL NULL 5 Using where +select * from t1 where f > 1.29999; +i f c +98 1.3 jaipur +97 1.4 delhi +96 1.5 ahmedabad +explain select * from t1 where i = 100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where +alter table t1 add unique index pri_index(i); +explain select * from t1 where i = 100; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const pri_index pri_index 5 const 1 +select * from t1 where i = 100; +i f c +100 1.1 pune +delete from t1 where i < 97; +select * from t1; +i f c +100 1.1 pune +99 1.2 mumbai +98 1.3 jaipur +97 1.4 delhi +insert into t1 values (96, 1.5, 'kolkata'); +select * from t1; +i f c +100 1.1 pune +99 1.2 mumbai +98 1.3 jaipur +97 1.4 delhi +96 1.5 kolkata +update t1 set f = 1.44 where c = 'delhi'; +select * from t1; +i f c +100 1.1 pune +99 1.2 mumbai +98 1.3 jaipur +97 1.44 delhi +96 1.5 kolkata +truncate table t1; +insert into t1 values (100, 1.1, 'pune'); +insert into t1 values (99, 1.2, 'mumbai'); +insert into t1 values (98, 1.3, 'jaipur'); +insert into t1 values (97, 1.4, 'delhi'); +insert into t1 values (96, 1.5, 'ahmedabad'); +select * from t1; +i f c +100 1.1 pune +99 1.2 mumbai +98 1.3 jaipur +97 1.4 delhi +96 1.5 ahmedabad +alter table t1 discard tablespace; +ERROR HY000: Cannot DISCARD/IMPORT tablespace associated with temporary table +alter table t1 import tablespace; +ERROR HY000: Cannot DISCARD/IMPORT tablespace associated with temporary table +drop temporary table t1; +create temporary table t1 +(keyc int, c1 char(100), c2 char(100), +primary key(keyc)) engine = innodb; +CREATE PROCEDURE populate_t1() +BEGIN +DECLARE i INT DEFAULT 1; +while (i <= 20000) DO +insert into t1 values (i, 'a', 'b'); +SET i = i + 1; +END WHILE; +END| +set autocommit=0; +select count(*) from t1; +count(*) +0 +call populate_t1(); +select count(*) from t1; +count(*) +20000 +select * from t1 limit 10; +keyc c1 c2 +1 a b +2 a b +3 a b +4 a b +5 a b +6 a b +7 a b +8 a b +9 a b +10 a b +set autocommit=1; +truncate table t1; +select * from t1; +keyc c1 c2 +# test condition of full-temp-tablespace +create temporary table t1 +(keyc int, c1 char(100), c2 char(100), +primary key(keyc)) engine = innodb; +begin; +call populate_t1(); +ERROR HY000: The table 't1' is full +drop procedure populate_t1; +# test read-only mode +# files in MYSQL_DATA_DIR +ibtmp1 +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show tables; +Tables_in_test +create temporary table t1 (keyc int, c1 char(100), c2 char(100)) engine = innodb; +ERROR HY000: Can't create table `test`.`t1` (errno: 165 "Table is read only") +# test various bad start-up parameters +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +create temporary table t ( +i int) +engine = innodb row_format = compressed; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +create temporary table t ( +i int) +engine = innodb row_format = compressed key_block_size = 8; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +create temporary table t ( +i int) +engine = innodb row_format = dynamic; +show warnings; +Level Code Message +drop table t; +create temporary table t ( +i int) +engine = innodb row_format = dynamic; +show warnings; +Level Code Message +drop table t; +set innodb_strict_mode = off; +create temporary table t ( +i int) +engine = innodb row_format = compressed key_block_size = 8; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +show warnings; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +set innodb_strict_mode = default; +drop table t; +create temporary table t ( +i int) +engine = innodb row_format = compressed; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +#files in MYSQL_TMP_DIR, expecting only default temporary tablespace file +ibtmp1 +create temporary table t ( +i int) +engine = innodb row_format = dynamic; +show warnings; +Level Code Message +drop table t; +create temporary table t ( +i int) +engine = innodb row_format = dynamic; +show warnings; +Level Code Message +drop table t; +set innodb_strict_mode = off; +create temporary table t ( +i int) +engine = innodb row_format = dynamic key_block_size = 4; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +show warnings; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +drop table t; +create temporary table t ( +i int) +engine = innodb row_format = compact; +show warnings; +Level Code Message +drop table t; +create temporary table t ( +i int) +engine = innodb key_block_size = 4; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +show warnings; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +drop table t; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=4 +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPACT; +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=4 +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED; +Warnings: +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8 +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC KEY_BLOCK_SIZE = 8; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8 +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC; +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +Warnings: +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +ALTER TABLE t1 KEY_BLOCK_SIZE = 4; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 +ALTER TABLE t1 KEY_BLOCK_SIZE = 4 ROW_FORMAT = COMPRESSED; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 +ALTER TABLE t1 ROW_FORMAT = DYNAMIC KEY_BLOCK_SIZE = 4; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4 +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4 +DROP TABLE t1; +set innodb_strict_mode = ON; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4, ROW_FORMAT = COMPACT; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 7; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY, +c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC; +SHOW WARNINGS; +Level Code Message +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `c` char(10) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 ( +i INT NOT NULL PRIMARY KEY +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +ALTER TABLE t1 KEY_BLOCK_SIZE = 4; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +ALTER TABLE t1 ROW_FORMAT = DYNAMIC KEY_BLOCK_SIZE = 4; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; +set innodb_strict_mode = OFF; +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +Warnings: +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +set innodb_strict_mode = ON; +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +set innodb_strict_mode = OFF; +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +Warnings: +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +ALTER TABLE t1 KEY_BLOCK_SIZE = 8; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=8. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +set innodb_strict_mode = ON; +ALTER TABLE t1 ADD COLUMN j INT; +ERROR HY000: CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +SHOW WARNINGS; +Level Code Message +Error 4047 CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE. +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8 +set innodb_strict_mode = OFF; +ALTER TABLE t1 KEY_BLOCK_SIZE = 0; +Warnings: +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + PRIMARY KEY (`i`) KEY_BLOCK_SIZE=8 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; +set innodb_strict_mode = ON; +ALTER TABLE t1 ADD COLUMN j INT; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `i` int(11) NOT NULL, + `j` int(11) DEFAULT NULL, + PRIMARY KEY (`i`) KEY_BLOCK_SIZE=8 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC diff --git a/mysql-test/suite/innodb/r/temporary_table_optimization.result b/mysql-test/suite/innodb/r/temporary_table_optimization.result new file mode 100644 index 00000000000..63c4f388bf7 --- /dev/null +++ b/mysql-test/suite/innodb/r/temporary_table_optimization.result @@ -0,0 +1,266 @@ +create temporary table t1 (i int) engine = innodb; +insert into t1 values (1), (2), (3), (4); +select * from t1; +i +1 +2 +3 +4 +select * from t1 where i = 4; +i +4 +drop table t1; +create temporary table t1 (i int) engine = innodb; +insert into t1 values (1), (2), (3), (4); +select * from t1; +i +1 +2 +3 +4 +select * from t1 where i = 4; +i +4 +drop table t1; +create temporary table t2 (i int) engine = innodb; +insert into t2 values (1), (2), (3), (4); +select * from t2; +i +1 +2 +3 +4 +select * from t2 where i = 4; +i +4 +drop table t2; +create temporary table t1 +(keyc int, c1 char(100), c2 char(100), +primary key(keyc)) engine = innodb; +create procedure populate_t1() +begin +declare i int default 1; +while (i <= 200) DO +insert into t1 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set autocommit=0; +select count(*) from t1; +count(*) +0 +call populate_t1(); +select count(*) from t1; +count(*) +200 +select * from t1 limit 10; +keyc c1 c2 +1 a b +2 a b +3 a b +4 a b +5 a b +6 a b +7 a b +8 a b +9 a b +10 a b +set autocommit=1; +truncate table t1; +select count(*) from t1; +count(*) +0 +drop table t1; +create temporary table t1 (i int) engine = innodb; +insert into t1 values (1), (2), (3), (4); +select * from t1; +i +1 +2 +3 +4 +select * from t1 where i = 4; +i +4 +drop table t1; +create temporary table t1 +(keyc int, c1 char(100), c2 char(100), +primary key(keyc)) +engine = innodb; +begin; +select count(*) from t1; +count(*) +0 +call populate_t1(); +select count(*) from t1; +count(*) +200 +rollback; +select count(*) from t1; +count(*) +0 +begin; +call populate_t1(); +commit; +select count(*) from t1; +count(*) +200 +truncate table t1; +select count(*) from t1; +count(*) +0 +drop table t1; +drop procedure populate_t1; +create temporary table t1 (t1_i int, t1_f float) engine = innodb; +insert into t1 values (1, 1.1), (2, 2.2), (3, 2.2), (4, 4.4); +explain select * from t1 where t1_i = 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where +alter table t1 add unique index pri_index(t1_i); +explain select * from t1 where t1_i = 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const pri_index pri_index 5 const 1 +select * from t1 where t1_i = 1; +t1_i t1_f +1 1.1 +alter table t1 add unique index sec_index(t1_f); +ERROR 23000: Duplicate entry '2.2' for key 'sec_index' +alter table t1 add index sec_index(t1_f); +explain select * from t1 where t1_f > 2.2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL sec_index NULL NULL NULL 4 Using where +select * from t1 where t1_f > 2.2; +t1_i t1_f +2 2.2 +3 2.2 +4 4.4 +alter table t1 add column (t1_c char(10)); +select * from t1; +t1_i t1_f t1_c +1 1.1 NULL +2 2.2 NULL +3 2.2 NULL +4 4.4 NULL +insert into t1 values (5, 5.5, 'krunal'); +alter table t1 drop column t1_f; +show create table t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `t1_i` int(11) DEFAULT NULL, + `t1_c` char(10) DEFAULT NULL, + UNIQUE KEY `pri_index` (`t1_i`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +select * from t1 where t1_f > 2.2; +ERROR 42S22: Unknown column 't1_f' in 'where clause' +alter table t1 add index sec_index2(t1_c), algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +drop table t1; +create temporary table t1 (i int, f float) engine = innodb; +insert into t1 values (10, 1.1), (20, 2.2); +select * from t1; +i f +10 1.1 +20 2.2 +alter table t1 discard tablespace; +ERROR HY000: Cannot DISCARD/IMPORT tablespace associated with temporary table +alter table t1 import tablespace; +ERROR HY000: Cannot DISCARD/IMPORT tablespace associated with temporary table +drop table t1; +create temporary table t1 (i int) engine=innodb; +insert into t1 values (1), (2), (3); +select * from t1; +i +1 +2 +3 +alter table t1 rename t2; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +select * from t2; +i +1 +2 +3 +insert into t2 values (1), (2), (6), (7); +select * from t2; +i +1 +2 +3 +1 +2 +6 +7 +drop table t2; +SET sql_mode = 'NO_ENGINE_SUBSTITUTION'; +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = dynamic engine=innodb; +drop table t; +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = dynamic engine=innodb; +drop table t; +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = dynamic engine=innodb; +drop table t; +SET innodb_strict_mode=OFF; +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = compact engine=innodb; +ERROR HY000: Index column size too large. The maximum column size is 767 bytes +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = dynamic engine=innodb; +drop table t; +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = compressed engine=innodb; +drop table t; +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = compact engine=innodb; +ERROR HY000: Index column size too large. The maximum column size is 767 bytes +create temporary table t ( +a int not null, +b blob not null, +index sk (b(3021)) +) row_format = dynamic engine=innodb; +drop table t; +CREATE TABLE t1 ( i INT ) ENGINE = Innodb; +CREATE TEMPORARY TABLE t2 ( i INT ) ENGINE = Innodb; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%t_'; +COUNT(*) +0 +SELECT COUNT(*) FROM information_schema.INNODB_SYS_TABLES WHERE NAME LIKE '%test%t_'; +COUNT(*) +1 +CREATE TEMPORARY table t3 ( i INT ) ENGINE = Innodb; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%t_'; +COUNT(*) +0 +SELECT COUNT(*) FROM information_schema.INNODB_SYS_TABLES WHERE NAME LIKE '%test%t_'; +COUNT(*) +1 +DROP TABLE t1,t2,t3; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%t_'; +COUNT(*) +0 +SELECT COUNT(*) FROM information_schema.INNODB_SYS_TABLES WHERE NAME LIKE '%test%t_'; +COUNT(*) +0 diff --git a/mysql-test/suite/innodb_zip/t/wl6470_1.test b/mysql-test/suite/innodb/t/temp_table.test similarity index 74% rename from mysql-test/suite/innodb_zip/t/wl6470_1.test rename to mysql-test/suite/innodb/t/temp_table.test index ecf6b601d3d..4809f278fb6 100644 --- a/mysql-test/suite/innodb_zip/t/wl6470_1.test +++ b/mysql-test/suite/innodb/t/temp_table.test @@ -1,6 +1,4 @@ --source include/have_innodb.inc ---source include/have_innodb_zip.inc ---source include/big_test.inc #################################################################### # TC to test temp-table DML optimization changes for correctness # @@ -22,28 +20,29 @@ create temporary table t2 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) ) engine = innodb; ---source suite/innodb_zip/include/innodb_dml_ops.inc -drop table t1; -drop table t2; +--source suite/innodb/include/dml_ops.inc +drop temporary table t1,t2; # ---disable_warnings +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE create temporary table t1 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) ) engine = innodb key_block_size = 4; +create temporary table t1 + (keyc int, c1 char(100), c2 char(100), + primary key(keyc), index sec_index(c1) + ) engine = innodb; set innodb_strict_mode=off; +--disable_warnings create temporary table t2 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) ) engine = innodb key_block_size = 8; -set innodb_strict_mode=default; +set innodb_strict_mode=on; --enable_warnings ---source suite/innodb_zip/include/innodb_dml_ops.inc -drop table t1; -drop table t2; +--source suite/innodb/include/dml_ops.inc +drop temporary table t1, t2; # -let $file_per_table = `select @@innodb_file_per_table`; -set global innodb_file_per_table = 0; create temporary table t1 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) @@ -52,9 +51,4 @@ create temporary table t2 (keyc int, c1 char(100), c2 char(100), primary key(keyc), index sec_index(c1) ) engine = innodb; ---source suite/innodb_zip/include/innodb_dml_ops.inc -drop table t1; -drop table t2; -eval set global innodb_file_per_table = $file_per_table; -# - +--source suite/innodb/include/dml_ops.inc diff --git a/mysql-test/suite/innodb_zip/t/wl6470_2.test b/mysql-test/suite/innodb/t/temp_table_savepoint.test similarity index 67% rename from mysql-test/suite/innodb_zip/t/wl6470_2.test rename to mysql-test/suite/innodb/t/temp_table_savepoint.test index 020c27b97b9..314ac148fca 100644 --- a/mysql-test/suite/innodb_zip/t/wl6470_2.test +++ b/mysql-test/suite/innodb/t/temp_table_savepoint.test @@ -1,11 +1,10 @@ --source include/have_innodb.inc ---source include/have_innodb_zip.inc --source include/no_valgrind_without_big.inc #################################################################### # TC to test temp-table DML optimization changes for correctness # # Sceanrio covered in single testcase : # -# - Tables with row format(redundant,compressed,dynamic,compact # +# - Tables with row format(redundant,dynamic,compact) # # - Table with primary,composite,prefix,secondary index # # - Insert/delete/update with transactioons # # - Transaction with commit,rollback,savepoint statements # @@ -14,37 +13,20 @@ # - Inserting data using # # - Insert into .. , Load data infile..,insert ignore # # - Insert into .. on duplicate update # -# - Check basic delete and upadte [ignore] # +# - Check basic delete and update [ignore] # # - Check constraints like duplicate key,default value # # - Alter add column , add primary key # # - with prepare and execute statement # #################################################################### -# run for page size >= 8k ---disable_warnings -if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE LOWER(variable_name) = 'innodb_page_size' AND variable_value >= 8192`) -{ - --skip Test requires InnoDB with page size >= 8k. -} ---enable_warnings - - -# Save initial values of server variable ---disable_query_log -let $innodb_file_per_table_orig=`select @@innodb_file_per_table`; -SET sql_mode = 'NO_ENGINE_SUBSTITUTION'; ---enable_query_log - -# Create procedure to perform +# Create procedure to perform # 1. Create temp table with row types , index , sufficent data types -# 2. Perform DML with transaction +# 2. Perform DML with transaction delimiter |; create procedure populate_tables() begin declare n int default 20; declare inner_loop int default 100; - set global innodb_file_per_table=on; - drop table if exists t1,t2,t3,t4; create temporary table t1(c1 int not null, c2 int not null, @@ -56,7 +38,7 @@ create procedure populate_tables() c8 datetime, c9 decimal(6,3), primary key (c1), - index (c3,c4(50),c5(50)), + index (c3,c4(50),c5(50)), index (c2)) engine=innodb row_format=redundant; @@ -74,20 +56,6 @@ create procedure populate_tables() index (c2)) engine=innodb row_format=compact; - create temporary table t3(c1 int not null, - c2 int not null, - c3 char(255) not null, - c4 text(6000) not null, - c5 blob(6000) not null, - c6 varchar(2000) not null, - c7 varchar(2000) not null, - c8 datetime, - c9 decimal(6,3), - primary key (c1), - index (c3,c4(50),c5(50)), - index (c2)) - engine=innodb row_format=compressed key_block_size=4; - create temporary table t4(c1 int not null, c2 int not null, c3 char(255) not null, @@ -115,23 +83,19 @@ create procedure populate_tables() index (c3,c4(50),c5(50)), index (c2)) engine=innodb; - + create temporary table t6 ( a int ) engine = innodb; insert into t6 values (50),(100),(150),(190); while (n > 0) do start transaction; insert into t1 values(n,n,repeat(concat(' tc3_',n),30), - repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), - repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), + repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), + repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), now(),(100.55+n)); insert into t2 values(n,n,repeat(concat(' tc3_',n),30), - repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), - repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), - now(),(100.55+n)); - insert into t3 values(n,n,repeat(concat(' tc3_',n),30), - repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), - repeat(concat(' tc6_',n),800),repeat(concat(' tc7_',n),800), + repeat(concat(' tc4_',n),8),repeat(concat(' tc_',n),8), + repeat(concat(' tc6_',n),8),repeat(concat(' tc7_',n),8), now(),(100.55+n)); insert into t4 values(n,n,repeat(concat(' tc3_',n),30), repeat(concat(' tc4_',n),800),repeat(concat(' tc_',n),800), @@ -144,35 +108,29 @@ create procedure populate_tables() if (n > 10) then commit; - else + else delete from t1 where c1 > 10 ; delete from t2 where c1 > 10 ; - delete from t3 where c1 > 10 ; delete from t4 where c1 > 10 ; delete from t5 where c1 > 10 ; - + rollback; start transaction; update t1 set c1 = c1 + 1000 where c1 > 10; update t2 set c1 = c1 + 1000 where c1 > 10; - update t3 set c1 = c1 + 1000 where c1 > 10; update t4 set c1 = c1 + 1000 where c1 > 10; update t5 set c1 = c1 + 1000 where c1 > 10; rollback; - end if; + end if; start transaction; insert into t1 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), + repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), + repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t2 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), - now(),(100.55+n+inner_loop)); - insert into t3 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), + repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), + repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t4 values(n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), @@ -185,29 +143,23 @@ create procedure populate_tables() delete from t1 where c1 between 100 and 110; delete from t2 where c1 between 100 and 110; - delete from t3 where c1 between 100 and 110; delete from t4 where c1 between 100 and 110; delete from t5 where c1 between 100 and 110; - update t1 set c1 = c1+1 where c1>110; - update t2 set c1 = c1+1 where c1>110; - update t3 set c1 = c1+1 where c1>110; - update t4 set c1 = c1+1 where c1>110; - update t5 set c1 = c1+1 where c1>110; + update t1 set c1 = c1+1 where c1>110; + update t2 set c1 = c1+1 where c1>110; + update t4 set c1 = c1+1 where c1>110; + update t5 set c1 = c1+1 where c1>110; savepoint a; insert into t1 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), + repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), + repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t2 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), - now(),(100.55+n+inner_loop)); - insert into t3 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), + repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), + repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t4 values(300+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), @@ -220,16 +172,12 @@ create procedure populate_tables() savepoint b; insert into t1 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), + repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), + repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t2 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), - now(),(100.55+n+inner_loop)); - insert into t3 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), - repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), - repeat(concat(' tc6_',n+inner_loop),245),repeat(concat(' tc7_',n+inner_loop),245), + repeat(concat(' tc4_',n+inner_loop),8),repeat(concat(' tc_',n+inner_loop),8), + repeat(concat(' tc6_',n+inner_loop),2),repeat(concat(' tc7_',n+inner_loop),2), now(),(100.55+n+inner_loop)); insert into t4 values(400+n+inner_loop,n+inner_loop,repeat(concat(' tc3_',n+inner_loop),30), repeat(concat(' tc4_',n+inner_loop),800),repeat(concat(' tc_',n+inner_loop),800), @@ -245,67 +193,42 @@ create procedure populate_tables() commit; commit; rollback; - set n = n - 1; + set n = n - 1; end while; end| delimiter ;| # Create two client for concurrent execution connect (con1,localhost,root,,); +--send call populate_tables(); + connect (con2,localhost,root,,); - ---echo #---client 1 : dml operation ---" -connection con1; --- disable_query_log -eval set global innodb_file_per_table=$innodb_file_per_table_orig; --- enable_query_log --- disable_query_log -# call procedure --send call populate_tables(); --- enable_query_log ---echo #---client 2 : dml operation ---" -connection con2; --- disable_query_log -eval set global innodb_file_per_table=$innodb_file_per_table_orig; --- enable_query_log --- disable_query_log -# call procedure ---send call populate_tables(); --- enable_query_log - -# check data of client connection 1 ---echo # In connection 1 connection con1; --reap -# 20 rows exepceted in 5 tables +# 20 rows expected select count(*) from t1; select count(*) from t2; -select count(*) from t3; select count(*) from t4; select count(*) from t5; select c1 from t1; select c1 from t2; -select c1 from t3; select c1 from t4; select c1 from t5; -# check data of client connection 2 ---echo # In connection 2 + connection con2; --reap -# 20 rows exepceted in 5 tables +# 20 rows expected select count(*) from t1; select count(*) from t2; -select count(*) from t3; select count(*) from t4; select count(*) from t5; select c1 from t1; select c1 from t2; -select c1 from t3; select c1 from t4; select c1 from t5; ---echo # In connection 1 connection con1; set autocommit = 0; @@ -317,9 +240,6 @@ insert ignore into t1 values (20,1,'a','a','a','a','a',now(),100.55); insert into t2 values (20,1,'a','a','a','a','a',now(),100.55); insert ignore into t2 values (20,1,'a','a','a','a','a',now(),100.55); --error ER_DUP_ENTRY -insert into t3 values (20,1,'a','a','a','a','a',now(),100.55); -insert ignore into t3 values (20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY insert into t4 values (20,1,'a','a','a','a','a',now(),100.55); insert ignore into t4 values (20,1,'a','a','a','a','a',now(),100.55); --error ER_DUP_ENTRY @@ -334,9 +254,6 @@ insert into t1 values (1,1,'a','a','a','a','a',now(),100.55), insert into t2 values (1,1,'a','a','a','a','a',now(),100.55), (20,1,'a','a','a','a','a',now(),100.55); --error ER_DUP_ENTRY -insert into t3 values (1,1,'a','a','a','a','a',now(),100.55), -(20,1,'a','a','a','a','a',now(),100.55); ---error ER_DUP_ENTRY insert into t4 values (1,1,'a','a','a','a','a',now(),100.55), (20,1,'a','a','a','a','a',now(),100.55); --error ER_DUP_ENTRY @@ -347,74 +264,59 @@ set autocommit = 1; select c1,c2 from t1 where c1 in (20,1); select c1,c2 from t2 where c1 in (20,1); -select c1,c2 from t3 where c1 in (20,1); select c1,c2 from t4 where c1 in (20,1); select c1,c2 from t5 where c1 in (20,1); #replace statement replace into t1 values (20,1,'a','a','a','a','a',now(),100.55); replace into t2 values (20,1,'a','a','a','a','a',now(),100.55); -replace into t3 values (20,1,'a','a','a','a','a',now(),100.55); replace into t4 values (20,1,'a','a','a','a','a',now(),100.55); replace into t5 values (20,1,'a','a','a','a','a',now(),100.55); # verify row is replaced from (20,20) to (20,1) select c1,c2,c3,c4,c5,c6,c7,c9 from t1 where c1 = 20; select c1,c2,c3,c4,c5,c6,c7,c9 from t2 where c1 = 20; -select c1,c2,c3,c4,c5,c6,c7,c9 from t3 where c1 = 20; select c1,c2,c3,c4,c5,c6,c7,c9 from t4 where c1 = 20; select c1,c2,c3,c4,c5,c6,c7,c9 from t5 where c1 = 20; -# Update ignore. statement is gonored as 20 value exits +# Update ignore. statement is ignored as 20 value exists update ignore t1 set c1 = 20 where c1 = 140 ; update ignore t2 set c1 = 20 where c1 = 140 ; -update ignore t3 set c1 = 20 where c1 = 140 ; update ignore t4 set c1 = 20 where c1 = 140 ; update ignore t5 set c1 = 20 where c1 = 140 ; # see record 140 is present as last update ignored select count(*) from t1 where c1 = 140; select count(*) from t2 where c1 = 140; -select count(*) from t3 where c1 = 140; select count(*) from t4 where c1 = 140; select count(*) from t5 where c1 = 140; -# Load data infile ---echo "running select * into outfile from t1 ; ---disable_query_log +--replace_result $MYSQLTEST_VARDIR VARDIR eval select * into outfile "$MYSQLTEST_VARDIR/tmp/t1.outfile" from t1; ---enable_query_log -# Create table as select + create temporary table temp_1 engine = innodb as select * from t1 where 1=2; select count(*) from temp_1; ---echo "running load data infile into temp_1 ; ---disable_query_log + +--replace_result $MYSQLTEST_VARDIR VARDIR eval load data infile '$MYSQLTEST_VARDIR/tmp/t1.outfile' into table temp_1; ---enable_query_log select count(*) from temp_1; +--remove_file $MYSQLTEST_VARDIR/tmp/t1.outfile # Alter table to add column and primary key -alter table temp_1 add column c10 int default 99 , +alter table temp_1 add column c10 int default 99 , add column c11 varchar(100) default 'test'; alter table temp_1 add primary key (c1); insert into temp_1 (c1,c2,c3,c4,c5,c6,c7,c8,c9) values (-1,-1,'a','a','a','a','a',now(),100.55); select c1,c2,c3,c4,c5,c6,c7,c9,c10,c11 from temp_1 where c1 < 0; select count(*) from temp_1 where c10 = 99 and c11 like 'test'; # insert on duplicate key update -insert into temp_1 (c1,c2,c3,c4,c5,c6,c7,c8,c9) values (-1,-1,'a','a','a','a','a',now(),100.55) +insert into temp_1 (c1,c2,c3,c4,c5,c6,c7,c8,c9) values (-1,-1,'a','a','a','a','a',now(),100.55) on duplicate key update c1=-2,c2=-2; select c1,c2,c3,c4,c5,c6,c7,c9,c10,c11 from temp_1 where c1 < 0; -#cleanup -drop table t1 ,t2 ,t3,t4,t5,t6,temp_1; disconnect con1; - -connection con2; -drop table t1 ,t2 ,t3,t4,t5,t6; disconnect con2; - connection default; drop procedure populate_tables; - # case 2 - with prepare and execute let $prep_loop= 5; create temporary table prep_1(c1 int not null, @@ -457,12 +359,3 @@ select count(*) from prep_1; drop prepare stm; drop prepare stm_1; drop prepare stm_2; -drop table prep_1; - ---remove_file $MYSQLTEST_VARDIR/tmp/t1.outfile - --- disable_query_log -eval set global innodb_file_per_table=$innodb_file_per_table_orig; -SET sql_mode = default; --- enable_query_log - diff --git a/mysql-test/suite/innodb/t/temporary_table.test b/mysql-test/suite/innodb/t/temporary_table.test new file mode 100644 index 00000000000..9f63fe52f3b --- /dev/null +++ b/mysql-test/suite/innodb/t/temporary_table.test @@ -0,0 +1,445 @@ +# +# InnoDB temporary table test case, including +# WL#6560: InnoDB: separate tablespace for innodb-temp-tables. +# WL#7899: InnoDB: Map compressed temporary tables to uncompressed +# + +--source include/have_innodb.inc +# Embedded server does not restart of server +--source include/not_embedded.inc +--source include/no_valgrind_without_big.inc + +--disable_query_log +call mtr.add_suppression("last file in setting innodb_temp_data_file_path"); +call mtr.add_suppression("The table 't1' is full"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error"); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); +call mtr.add_suppression("InnoDB: Tablespace doesn't support raw devices"); +call mtr.add_suppression("InnoDB: The innodb_temporary data file 'ibtmp1' must be at least"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted"); +call mtr.add_suppression("innodb_temporary and innodb_system file names seem to be the same"); +call mtr.add_suppression("Could not create the shared innodb_temporary"); +call mtr.add_suppression("InnoDB: syntax error in file path"); +--enable_query_log + +let $MYSQL_TMP_DIR = `select @@tmpdir`; +let $MYSQL_DATA_DIR = `select @@datadir`; + +--echo # files in MYSQL_DATA_DIR +--list_files $MYSQL_DATA_DIR/ ibtmp* + +create temporary table t1 (i int, f float, c char(100)) engine=innodb; +insert into t1 values (100, 1.1, 'pune'); +insert into t1 values (99, 1.2, 'mumbai'); +insert into t1 values (98, 1.3, 'jaipur'); +insert into t1 values (97, 1.4, 'delhi'); +insert into t1 values (96, 1.5, 'ahmedabad'); +select * from t1; +select * from t1 where i = 98; +select * from t1 where i < 100; + +explain select * from t1 where f > 1.29999; +alter table t1 add index sec_index(f); +explain select * from t1 where f > 1.29999; +select * from t1 where f > 1.29999; + +explain select * from t1 where i = 100; +alter table t1 add unique index pri_index(i); +explain select * from t1 where i = 100; +select * from t1 where i = 100; + +delete from t1 where i < 97; +select * from t1; +insert into t1 values (96, 1.5, 'kolkata'); +select * from t1; + +update t1 set f = 1.44 where c = 'delhi'; +select * from t1; + +truncate table t1; +insert into t1 values (100, 1.1, 'pune'); +insert into t1 values (99, 1.2, 'mumbai'); +insert into t1 values (98, 1.3, 'jaipur'); +insert into t1 values (97, 1.4, 'delhi'); +insert into t1 values (96, 1.5, 'ahmedabad'); +select * from t1; + +--error ER_CANNOT_DISCARD_TEMPORARY_TABLE +alter table t1 discard tablespace; +--error ER_CANNOT_DISCARD_TEMPORARY_TABLE +alter table t1 import tablespace; +drop temporary table t1; + +create temporary table t1 + (keyc int, c1 char(100), c2 char(100), + primary key(keyc)) engine = innodb; +delimiter |; +CREATE PROCEDURE populate_t1() +BEGIN + DECLARE i INT DEFAULT 1; + while (i <= 20000) DO + insert into t1 values (i, 'a', 'b'); + SET i = i + 1; + END WHILE; +END| +delimiter ;| +set autocommit=0; +select count(*) from t1; +call populate_t1(); +select count(*) from t1; +select * from t1 limit 10; +set autocommit=1; +truncate table t1; +select * from t1; +# + +--echo # test condition of full-temp-tablespace +--let $restart_parameters= --innodb_temp_data_file_path=ibtmp1:12M +--source include/restart_mysqld.inc + +create temporary table t1 + (keyc int, c1 char(100), c2 char(100), + primary key(keyc)) engine = innodb; +begin; +--error ER_RECORD_FILE_FULL +call populate_t1(); + +drop procedure populate_t1; + +--echo # test read-only mode +--let $restart_parameters = --innodb-read-only +--source include/restart_mysqld.inc + +--echo # files in MYSQL_DATA_DIR +--list_files $MYSQL_DATA_DIR/ ibtmp* + +--error ER_NO_SUCH_TABLE +select * from t1; +show tables; +--error ER_CANT_CREATE_TABLE +create temporary table t1 (keyc int, c1 char(100), c2 char(100)) engine = innodb; + +--echo # test various bad start-up parameters + +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_RANGE = -50000; +let SEARCH_ABORT = NOT FOUND; +let $check_no_innodb=SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); + +--let $restart_parameters= --innodb_data_file_path=ibdata1:12M:autoextend --innodb_temp_data_file_path=ibdata1:12M:autoextend +--source include/restart_mysqld.inc +--let SEARCH_PATTERN = innodb_temporary and innodb_system file names seem to be the same +--source include/search_pattern_in_file.inc +eval $check_no_innodb; + +--let $restart_parameters= --innodb_temp_data_file_path=foobar:3Gnewraw +--source include/restart_mysqld.inc +--let SEARCH_PATTERN = support raw device +--source include/search_pattern_in_file.inc +eval $check_no_innodb; + +--let $restart_parameters= --innodb_temp_data_file_path=barbar:3Graw +--source include/restart_mysqld.inc +--source include/search_pattern_in_file.inc +eval $check_no_innodb; + +--let $restart_parameters= --innodb_temp_data_file_path=ibtmp1:2M:autoextend +--source include/restart_mysqld.inc +--let SEARCH_PATTERN = The innodb_temporary data file 'ibtmp1' must be at least +--source include/search_pattern_in_file.inc +eval $check_no_innodb; + +--let $restart_parameters= --innodb_temp_data_file_path= +--source include/restart_mysqld.inc +--let SEARCH_PATTERN = InnoDB: syntax error in file path +--source include/search_pattern_in_file.inc +eval $check_no_innodb; + +--let $restart_parameters= +--source include/restart_mysqld.inc + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +create temporary table t ( + i int) + engine = innodb row_format = compressed; +# +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +create temporary table t ( + i int) + engine = innodb row_format = compressed key_block_size = 8; +# +create temporary table t ( + i int) + engine = innodb row_format = dynamic; +show warnings; +drop table t; +# +create temporary table t ( + i int) + engine = innodb row_format = dynamic; +show warnings; +drop table t; +set innodb_strict_mode = off; +# +create temporary table t ( + i int) + engine = innodb row_format = compressed key_block_size = 8; +show warnings; +set innodb_strict_mode = default; +# +drop table t; +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +create temporary table t ( + i int) + engine = innodb row_format = compressed; +--echo #files in MYSQL_TMP_DIR, expecting only default temporary tablespace file +--list_files $MYSQL_TMP_DIR/ *.ibd +--list_files $MYSQL_DATA_DIR/ ibtmp* +# +create temporary table t ( + i int) + engine = innodb row_format = dynamic; +show warnings; +drop table t; +# +create temporary table t ( + i int) + engine = innodb row_format = dynamic; +show warnings; +drop table t; +set innodb_strict_mode = off; +# +create temporary table t ( + i int) + engine = innodb row_format = dynamic key_block_size = 4; +show warnings; +drop table t; +# +create temporary table t ( + i int) + engine = innodb row_format = compact; +show warnings; +drop table t; +# +create temporary table t ( + i int) + engine = innodb key_block_size = 4; +show warnings; +drop table t; +# + +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPACT; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# + +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC KEY_BLOCK_SIZE = 8; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# + +# Test alter table for temporary tables with row format = compressed or +# key_block_size +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; + +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +ALTER TABLE t1 KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +ALTER TABLE t1 KEY_BLOCK_SIZE = 4 ROW_FORMAT = COMPRESSED; +SHOW WARNINGS; +SHOW CREATE TABLE t1; + +ALTER TABLE t1 ROW_FORMAT = DYNAMIC KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# Set innodb_strict_mode=ON and test compressed temporary tables again. +set innodb_strict_mode = ON; + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; +# + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4, ROW_FORMAT = COMPACT; +SHOW WARNINGS; +# + +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; +# + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED; +SHOW WARNINGS; +# + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 8; +SHOW WARNINGS; +# + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = COMPRESSED KEY_BLOCK_SIZE = 7; +SHOW WARNINGS; +# + +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY, + c CHAR(10) NOT NULL +) ENGINE = InnoDB ROW_FORMAT = DYNAMIC; +SHOW WARNINGS; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# + +CREATE TEMPORARY TABLE t1 ( + i INT NOT NULL PRIMARY KEY +) ENGINE = InnoDB ROW_FORMAT = REDUNDANT; + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +SHOW WARNINGS; + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +ALTER TABLE t1 KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +ALTER TABLE t1 ROW_FORMAT = DYNAMIC KEY_BLOCK_SIZE = 4; +SHOW WARNINGS; + +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; + +# +# Some checking for turning innodb_strict_mode ON and OFF. +set innodb_strict_mode = OFF; + +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +SHOW WARNINGS; + +set innodb_strict_mode = ON; + +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; +SHOW CREATE TABLE t1; + +set innodb_strict_mode = OFF; + +ALTER TABLE t1 ROW_FORMAT = COMPRESSED; +SHOW WARNINGS; + +ALTER TABLE t1 KEY_BLOCK_SIZE = 8; +SHOW WARNINGS; + +set innodb_strict_mode = ON; + +--error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE +ALTER TABLE t1 ADD COLUMN j INT; +SHOW WARNINGS; +SHOW CREATE TABLE t1; + +set innodb_strict_mode = OFF; + +ALTER TABLE t1 KEY_BLOCK_SIZE = 0; +SHOW CREATE TABLE t1; + +ALTER TABLE t1 ROW_FORMAT = DYNAMIC; + +set innodb_strict_mode = ON; +ALTER TABLE t1 ADD COLUMN j INT; +SHOW CREATE TABLE t1; diff --git a/mysql-test/suite/innodb/t/temporary_table_optimization.opt b/mysql-test/suite/innodb/t/temporary_table_optimization.opt new file mode 100644 index 00000000000..2f73da1ead6 --- /dev/null +++ b/mysql-test/suite/innodb/t/temporary_table_optimization.opt @@ -0,0 +1 @@ +--loose-innodb-sys-datafiles --loose-innodb-sys-tables diff --git a/mysql-test/suite/innodb/t/temporary_table_optimization.test b/mysql-test/suite/innodb/t/temporary_table_optimization.test new file mode 100644 index 00000000000..ae41c87839b --- /dev/null +++ b/mysql-test/suite/innodb/t/temporary_table_optimization.test @@ -0,0 +1,243 @@ +# +# WL#6469: Optimizing CREATE/DROP performance for temporary tables +# +--source include/no_valgrind_without_big.inc +--source include/have_innodb.inc + +######################################################################### +# # +# Will test following scenarios: # +# 1. Create/Drop of temp-table. (with and w/o explicit pk) # +# 2. Truncate temp-table (result in table drop and recreate). # +# 3. Alter of temp-table. # +# 4. Import/Discard of temp-table (to check blocked action) # +# 5. Renaming of temp-table # +# 6. Creating temp-table with large prefix. # +# 7. Check Temp table info not stored in I_S datafile and tables # +######################################################################### + + +#------------------------------------------------------------- +# +# 1. Create/Drop of temp-table. (with and w/o explicit pk) # +# +create temporary table t1 (i int) engine = innodb; +insert into t1 values (1), (2), (3), (4); +select * from t1; +select * from t1 where i = 4; +drop table t1; +# +# recreate table wih same name to ensure entries are removed. +create temporary table t1 (i int) engine = innodb; +insert into t1 values (1), (2), (3), (4); +select * from t1; +select * from t1 where i = 4; +drop table t1; +# +create temporary table t2 (i int) engine = innodb; +insert into t2 values (1), (2), (3), (4); +select * from t2; +select * from t2 where i = 4; +drop table t2; + +#------------------------------------------------------------- +# +# 2. Truncate temp-table (result in table drop and recreate). # +# +create temporary table t1 + (keyc int, c1 char(100), c2 char(100), + primary key(keyc)) engine = innodb; +delimiter |; +create procedure populate_t1() +begin + declare i int default 1; + while (i <= 200) DO + insert into t1 values (i, 'a', 'b'); + set i = i + 1; + end while; +end| +delimiter ;| +set autocommit=0; +select count(*) from t1; +call populate_t1(); +select count(*) from t1; +select * from t1 limit 10; +set autocommit=1; +truncate table t1; +select count(*) from t1; +drop table t1; +# +# recreate table wih same name to ensure entries are removed. +create temporary table t1 (i int) engine = innodb; +insert into t1 values (1), (2), (3), (4); +select * from t1; +select * from t1 where i = 4; +drop table t1; +# +create temporary table t1 + (keyc int, c1 char(100), c2 char(100), + primary key(keyc)) + engine = innodb; +begin; +select count(*) from t1; +call populate_t1(); +select count(*) from t1; +rollback; +select count(*) from t1; +begin; +call populate_t1(); +commit; +select count(*) from t1; +truncate table t1; +select count(*) from t1; +drop table t1; +# +drop procedure populate_t1; + + +#------------------------------------------------------------- +# +# 3. Alter of temp-table. +# +create temporary table t1 (t1_i int, t1_f float) engine = innodb; +insert into t1 values (1, 1.1), (2, 2.2), (3, 2.2), (4, 4.4); +# +explain select * from t1 where t1_i = 1; +alter table t1 add unique index pri_index(t1_i); +explain select * from t1 where t1_i = 1; +select * from t1 where t1_i = 1; +# +--error ER_DUP_ENTRY +alter table t1 add unique index sec_index(t1_f); +alter table t1 add index sec_index(t1_f); +explain select * from t1 where t1_f > 2.2; +select * from t1 where t1_f > 2.2; +# +alter table t1 add column (t1_c char(10)); +select * from t1; +insert into t1 values (5, 5.5, 'krunal'); +# +alter table t1 drop column t1_f; +show create table t1; +--error ER_BAD_FIELD_ERROR +select * from t1 where t1_f > 2.2; +# +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table t1 add index sec_index2(t1_c), algorithm=inplace; +# +drop table t1; + +#------------------------------------------------------------- +# +# 4. Import/Discard of temp-table (to check blocked action) +# +create temporary table t1 (i int, f float) engine = innodb; +insert into t1 values (10, 1.1), (20, 2.2); +select * from t1; +# +--error ER_CANNOT_DISCARD_TEMPORARY_TABLE +alter table t1 discard tablespace; +--error ER_CANNOT_DISCARD_TEMPORARY_TABLE +alter table t1 import tablespace; +drop table t1; + +#------------------------------------------------------------- +# +# 5. Renaming of temp-table # +# +create temporary table t1 (i int) engine=innodb; +insert into t1 values (1), (2), (3); +select * from t1; +# +alter table t1 rename t2; +--error ER_NO_SUCH_TABLE +select * from t1; +select * from t2; +insert into t2 values (1), (2), (6), (7); +select * from t2; +drop table t2; + + +#------------------------------------------------------------- +# +# 6. Creating temp-table with large prefix. # +# +SET sql_mode = 'NO_ENGINE_SUBSTITUTION'; +# This will lead to warnings on innodb_page_size=8k or 4k: +# 8k: Specified key was too long; max key length is 1536 bytes +# 4k: Specified key was too long; max key length is 768 bytes +--disable_warnings +# +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = dynamic engine=innodb; +drop table t; +# +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = dynamic engine=innodb; +drop table t; +# +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = dynamic engine=innodb; +drop table t; +# +SET innodb_strict_mode=OFF; +--error ER_INDEX_COLUMN_TOO_LONG +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = compact engine=innodb; +# +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = dynamic engine=innodb; +drop table t; +# +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = compressed engine=innodb; +drop table t; +# +--error ER_INDEX_COLUMN_TOO_LONG +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = compact engine=innodb; +# +create temporary table t ( + a int not null, + b blob not null, + index sk (b(3021)) + ) row_format = dynamic engine=innodb; +drop table t; +--enable_warnings +# + +#------------------------------------------------------------- +# +# 7. Temp table info not stored in I_S +# +CREATE TABLE t1 ( i INT ) ENGINE = Innodb; +CREATE TEMPORARY TABLE t2 ( i INT ) ENGINE = Innodb; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%t_'; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_TABLES WHERE NAME LIKE '%test%t_'; +CREATE TEMPORARY table t3 ( i INT ) ENGINE = Innodb; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%t_'; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_TABLES WHERE NAME LIKE '%test%t_'; +DROP TABLE t1,t2,t3; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_DATAFILES WHERE PATH LIKE '%test%t_'; +SELECT COUNT(*) FROM information_schema.INNODB_SYS_TABLES WHERE NAME LIKE '%test%t_'; diff --git a/mysql-test/suite/innodb_zip/include/innodb_temp_table_dml.inc b/mysql-test/suite/innodb_zip/include/innodb_temp_table_dml.inc deleted file mode 100644 index 42e0908f810..00000000000 --- a/mysql-test/suite/innodb_zip/include/innodb_temp_table_dml.inc +++ /dev/null @@ -1,40 +0,0 @@ -# insert test -insert into t1 values (100, 1.1, 'pune'); -insert into t1 values (99, 1.2, 'mumbai'); -insert into t1 values (98, 1.3, 'jaipur'); -insert into t1 values (97, 1.4, 'delhi'); -insert into t1 values (96, 1.5, 'ahmedabad'); -select * from t1; -select * from t1 where i = 98; -select * from t1 where i < 100; -# -# add index using alter table table -explain select * from t1 where f > 1.29999; -alter table t1 add index sec_index(f); -explain select * from t1 where f > 1.29999; -select * from t1 where f > 1.29999; -# -explain select * from t1 where i = 100; -alter table t1 add unique index pri_index(i); -explain select * from t1 where i = 100; -select * from t1 where i = 100; -# -# delete test -delete from t1 where i < 97; -select * from t1; -insert into t1 values (96, 1.5, 'kolkata'); -select * from t1; -# -# update test -update t1 set f = 1.44 where c = 'delhi'; -select * from t1; -# -# truncate table -truncate table t1; -insert into t1 values (100, 1.1, 'pune'); -insert into t1 values (99, 1.2, 'mumbai'); -insert into t1 values (98, 1.3, 'jaipur'); -insert into t1 values (97, 1.4, 'delhi'); -insert into t1 values (96, 1.5, 'ahmedabad'); -select * from t1; - diff --git a/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result index 9c197737137..72fdceab7e4 100644 --- a/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result +++ b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result @@ -20,33 +20,143 @@ set i = i + 1; end while; end| set global innodb_file_per_table = 1; -set global innodb_file_format = 'Antelope'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html create table tNUMBER (i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), index cNUMBER_idx(cNUMBER)) engine=innodb row_format=compact key_block_size=NUMBER; Warnings: -Warning NUMBER InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Warning NUMBER InnoDB: ignoring KEY_BLOCK_SIZE=NUMBER. +Warning NUMBER InnoDB: ignoring KEY_BLOCK_SIZE=NUMBER unless ROW_FORMAT=COMPRESSED. create table t2 (i int, c1 char(100), c2 char(100), index c1_idx(c1)) engine=innodb row_format=compact key_block_size=16; Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16 unless ROW_FORMAT=COMPRESSED. create temporary table t3 (i int, c1 char(100), c2 char(100), index c1_idx(c1)) engine=innodb row_format=compact key_block_size=16; Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +begin; +call populate(); +commit; +select count(*) from t1; +count(*) +5000 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +truncate table t1; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16 unless ROW_FORMAT=COMPRESSED. +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +5000 +select count(*) from t3; +count(*) +5000 +call populate_small(); +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +7000 +select count(*) from t3; +count(*) +7000 +truncate table t2; +Warnings: +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16 unless ROW_FORMAT=COMPRESSED. +# WL#7811/WL#7743/WL#7141 TODO: Remove the warnings! +truncate table t3; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +select count(*) from t1; +count(*) +2000 +select count(*) from t2; +count(*) +0 +select count(*) from t3; +count(*) +0 +call populate_small(); +select count(*) from t1; +count(*) +4000 +select count(*) from t2; +count(*) +2000 +select count(*) from t3; +count(*) +2000 +drop table t1; +drop table t2; +drop table t3; +drop procedure populate; +drop procedure populate_small; +set global innodb_file_per_table = 1; +set innodb_strict_mode=OFF; +create procedure populate() +begin +declare i int default 1; +while (i <= 5000) do +insert into t1 values (i, 'a', 'b'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +create procedure populate_small() +begin +declare i int default 10001; +while (i <= 12000) do +insert into t1 values (i, 'c', 'd'); +insert into t2 values (i, 'a', 'b'); +insert into t3 values (i, 'a', 'b'); +set i = i + 1; +end while; +end| +set global innodb_file_per_table = 1; +create table tNUMBER +(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), +index cNUMBER_idx(cNUMBER)) +engine=innodb row_format=compressed +key_block_size=NUMBER; +create table t2 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compressed +key_block_size=16; +create temporary table t3 +(i int, c1 char(100), c2 char(100), +index c1_idx(c1)) +engine=innodb row_format=compressed +key_block_size=16; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. select count(*) from t1; count(*) 0 @@ -89,7 +199,12 @@ select count(*) from t3; count(*) 7000 truncate table t2; +# WL#7811/WL#7743/WL#7141 TODO: Remove the warnings! truncate table t3; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. select count(*) from t1; count(*) 2000 @@ -114,120 +229,6 @@ drop table t2; drop table t3; drop procedure populate; drop procedure populate_small; -set global innodb_file_format = Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table = 1; -set innodb_strict_mode=OFF; -create procedure populate() -begin -declare i int default 1; -while (i <= 5000) do -insert into t1 values (i, 'a', 'b'); -insert into t2 values (i, 'a', 'b'); -insert into t3 values (i, 'a', 'b'); -set i = i + 1; -end while; -end| -create procedure populate_small() -begin -declare i int default 10001; -while (i <= 12000) do -insert into t1 values (i, 'c', 'd'); -insert into t2 values (i, 'a', 'b'); -insert into t3 values (i, 'a', 'b'); -set i = i + 1; -end while; -end| -set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -create table tNUMBER -(i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), -index cNUMBER_idx(cNUMBER)) -engine=innodb row_format=compressed -key_block_size=NUMBER; -create table t2 -(i int, c1 char(100), c2 char(100), -index c1_idx(c1)) -engine=innodb row_format=compressed -key_block_size=16; -create temporary table t3 -(i int, c1 char(100), c2 char(100), -index c1_idx(c1)) -engine=innodb row_format=compressed -key_block_size=16; -select count(*) from t1; -count(*) -0 -select count(*) from t2; -count(*) -0 -select count(*) from t3; -count(*) -0 -begin; -call populate(); -commit; -select count(*) from t1; -count(*) -5000 -select count(*) from t2; -count(*) -5000 -select count(*) from t3; -count(*) -5000 -truncate table t1; -select count(*) from t1; -count(*) -0 -select count(*) from t2; -count(*) -5000 -select count(*) from t3; -count(*) -5000 -call populate_small(); -select count(*) from t1; -count(*) -2000 -select count(*) from t2; -count(*) -7000 -select count(*) from t3; -count(*) -7000 -truncate table t2; -truncate table t3; -select count(*) from t1; -count(*) -2000 -select count(*) from t2; -count(*) -0 -select count(*) from t3; -count(*) -0 -call populate_small(); -select count(*) from t1; -count(*) -4000 -select count(*) from t2; -count(*) -2000 -select count(*) from t3; -count(*) -2000 -drop table t1; -drop table t2; -drop table t3; -drop procedure populate; -drop procedure populate_small; -set global innodb_file_format = Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; set innodb_strict_mode=OFF; create procedure populate() @@ -251,9 +252,6 @@ set i = i + 1; end while; end| set global innodb_file_per_table = 0; -set global innodb_file_format = 'Antelope'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html create table tNUMBER (i int, cNUMBER char(NUMBER), cNUMBER char(NUMBER), index cNUMBER_idx(cNUMBER)) @@ -261,7 +259,6 @@ engine=innodb row_format=compact key_block_size=NUMBER; Warnings: Warning NUMBER InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. -Warning NUMBER InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Warning NUMBER InnoDB: ignoring KEY_BLOCK_SIZE=NUMBER. create table t2 (i int, c1 char(100), c2 char(100), @@ -270,7 +267,6 @@ engine=innodb row_format=compact key_block_size=16; Warnings: Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. create temporary table t3 (i int, c1 char(100), c2 char(100), @@ -278,9 +274,7 @@ index c1_idx(c1)) engine=innodb row_format=compact key_block_size=16; Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. select count(*) from t1; count(*) 0 @@ -303,6 +297,9 @@ select count(*) from t3; count(*) 5000 truncate table t1; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. select count(*) from t1; count(*) 0 @@ -323,7 +320,13 @@ select count(*) from t3; count(*) 7000 truncate table t2; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. +# WL#7811/WL#7743/WL#7141 TODO: Remove the warnings! truncate table t3; +Warnings: +Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. select count(*) from t1; count(*) 2000 @@ -348,7 +351,4 @@ drop table t2; drop table t3; drop procedure populate; drop procedure populate_small; -set global innodb_file_format = Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6915_1.result b/mysql-test/suite/innodb_zip/r/wl6915_1.result deleted file mode 100644 index bba81098e9d..00000000000 --- a/mysql-test/suite/innodb_zip/r/wl6915_1.result +++ /dev/null @@ -1,2079 +0,0 @@ -call mtr.ADD_suppression(".*Resizing redo log.*"); -call mtr.ADD_suppression(".*Starting to delete and rewrite log files.*"); -call mtr.ADD_suppression(".*New log files created.*"); -SELECT @@global.innodb_undo_tablespaces; -@@global.innodb_undo_tablespaces -0 -CREATE PROCEDURE populate_tables(IN id VARCHAR(10)) -begin -declare n int default 20; -set global innodb_file_per_table=on; -DROP TABLE IF EXISTS t1,t2,t3,t4; -CREATE TEMPORARY TABLE t1_temp(c1 int NOT NULL, -c2 int NOT NULL, -c3 char(255) NOT NULL, -c4 text(600) NOT NULL, -c5 blob(600) NOT NULL, -c6 varchar(600) NOT NULL, -c7 varchar(600) NOT NULL, -c8 datetime, -c9 decimal(6,3), -PRIMARY KEY (c1), -INDEX (c3,c4(50),c5(50)), -INDEX (c2)) -ENGINE=InnoDB ROW_FORMAT=redundant; -set @s = concat("CREATE TABLE t1",id," ( c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=redundant;"); -PREPARE createTable FROM @s; -EXECUTE createTable; -DEALLOCATE PREPARE createTable; -CREATE TEMPORARY TABLE t2_temp(c1 int NOT NULL, -c2 int NOT NULL, -c3 char(255) NOT NULL, -c4 text(600) NOT NULL, -c5 blob(600) NOT NULL, -c6 varchar(600) NOT NULL, -c7 varchar(600) NOT NULL, -c8 datetime, -c9 decimal(6,3), -PRIMARY KEY (c1), -INDEX (c3,c4(50),c5(50)), -INDEX (c2)) -ENGINE=InnoDB ROW_FORMAT=compact; -set @s = concat("CREATE TABLE t2",id," (c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=compact;"); -PREPARE createTable FROM @s; -EXECUTE createTable; -DEALLOCATE PREPARE createTable; -CREATE TEMPORARY TABLE t3_temp(c1 int NOT NULL, -c2 int NOT NULL, -c3 char(255) NOT NULL, -c4 text(600) NOT NULL, -c5 blob(600) NOT NULL, -c6 varchar(600) NOT NULL, -c7 varchar(600) NOT NULL, -c8 datetime, -c9 decimal(6,3), -PRIMARY KEY (c1), -INDEX (c3,c4(50),c5(50)), -INDEX (c2)) -ENGINE=InnoDB ROW_FORMAT=compressed key_block_size=4; -set @s = concat("CREATE TABLE t3",id," (c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=compressed key_block_size=4;"); -PREPARE createTable FROM @s; -EXECUTE createTable; -DEALLOCATE PREPARE createTable; -CREATE TEMPORARY TABLE t4_temp(c1 int NOT NULL, -c2 int NOT NULL, -c3 char(255) NOT NULL, -c4 text(600) NOT NULL, -c5 blob(600) NOT NULL, -c6 varchar(600) NOT NULL, -c7 varchar(600) NOT NULL, -c8 datetime, -c9 decimal(6,3), -PRIMARY KEY (c1), -INDEX (c3,c4(50),c5(50)), -INDEX (c2)) -ENGINE=InnoDB ROW_FORMAT=dynamic; -set @s = concat("CREATE TABLE t4",id," (c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=dynamic;"); -PREPARE createTable FROM @s; -EXECUTE createTable; -DEALLOCATE PREPARE createTable; -while (n > 0) do -START TRANSACTION; -set @s = concat("INSERT INTO t1",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t1_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), -REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), -REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), -NOW(),(100.55+n)); -set @s = concat("INSERT INTO t2",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t2_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), -REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), -REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), -NOW(),(100.55+n)); -savepoint a; -set @s = concat("INSERT INTO t3",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t3_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), -REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), -REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), -NOW(),(100.55+n)); -savepoint b; -set @s = concat("INSERT INTO t4",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t4_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), -REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), -REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), -NOW(),(100.55+n)); -if (n > 10) then -if (n > 10 and n <=12) then -ROLLBACK TO SAVEPOINT a; -COMMIT; -end if; -if (n > 12 and n < 15) then -ROLLBACK TO SAVEPOINT b; -COMMIT; -end if; -if (n > 15) then -COMMIT; -end if; -else -if (n > 5) then -START TRANSACTION; -DELETE FROM t1_temp WHERE c1 > 10 ; -DELETE FROM t2_temp WHERE c1 > 10 ; -DELETE FROM t3_temp WHERE c1 > 10 ; -DELETE FROM t4_temp WHERE c1 > 10 ; -rollback; -START TRANSACTION; -update t1_temp set c1 = c1 + 1000 WHERE c1 > 10; -update t2_temp set c1 = c1 + 1000 WHERE c1 > 10; -update t3_temp set c1 = c1 + 1000 WHERE c1 > 10; -update t4_temp set c1 = c1 + 1000 WHERE c1 > 10; -rollback; -end if; -end if; -if (n < 5) then -rollback; -end if; -FLUSH logs; -ALTER TABLE t1_temp DROP PRIMARY KEY; -ALTER TABLE t1_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); -ALTER TABLE t2_temp DROP PRIMARY KEY; -ALTER TABLE t2_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); -ALTER TABLE t3_temp DROP PRIMARY KEY; -ALTER TABLE t3_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); -ALTER TABLE t4_temp DROP PRIMARY KEY; -ALTER TABLE t4_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); -FLUSH tables; -START TRANSACTION; -set @s = concat("INSERT INTO t1",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t1_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t2",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t2_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t3",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t3_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t4",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t4_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -DELETE FROM t1_temp WHERE c1 between 100 and 110; -DELETE FROM t2_temp WHERE c1 between 100 and 110; -DELETE FROM t3_temp WHERE c1 between 100 and 110; -DELETE FROM t4_temp WHERE c1 between 100 and 110; -update t1_temp set c1 = c1+1 WHERE c1>110; -update t2_temp set c1 = c1+1 WHERE c1>110; -update t3_temp set c1 = c1+1 WHERE c1>110; -update t4_temp set c1 = c1+1 WHERE c1>110; -savepoint a; -set @s = concat("INSERT INTO t1",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t1_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t2",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t2_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t3",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t3_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t4",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t4_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -savepoint b; -set @s = concat("INSERT INTO t1",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t1_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t2",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t2_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t3",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t3_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -set @s = concat("INSERT INTO t4",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); -PREPARE insertIntoTable FROM @s; -EXECUTE insertIntoTable; -DEALLOCATE PREPARE insertIntoTable; -INSERT INTO t4_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), -REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), -REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), -NOW(),(100.55+n+100)); -savepoint c; -rollback to b; -rollback to a; -COMMIT; -COMMIT; -rollback; -set n = n - 1; -end while; -end| -connect con1,localhost,root,,; -connect con2,localhost,root,,; -#---client 1 : dml operation ---" -connection con1; -#---client 2 : dml operation ---" -connection con2; -# In connection 1 -connection con1; -SELECT count(*) FROM t1_1; -count(*) -36 -SELECT count(*) FROM t2_1; -count(*) -36 -SELECT count(*) FROM t3_1; -count(*) -34 -SELECT count(*) FROM t4_1; -count(*) -32 -SELECT c1 FROM t1_1; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t2_1; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t3_1; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t4_1; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT count(*) FROM t1_temp; -count(*) -26 -SELECT count(*) FROM t2_temp; -count(*) -26 -SELECT count(*) FROM t3_temp; -count(*) -24 -SELECT count(*) FROM t4_temp; -count(*) -22 -SELECT c1 FROM t1_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t2_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t3_temp; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t4_temp; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -# In connection 2 -connection con2; -SELECT count(*) FROM t1_2; -count(*) -36 -SELECT count(*) FROM t2_2; -count(*) -36 -SELECT count(*) FROM t3_2; -count(*) -34 -SELECT count(*) FROM t4_2; -count(*) -32 -SELECT c1 FROM t1_2; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t2_2; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t3_2; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t4_2; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT count(*) FROM t1_temp; -count(*) -26 -SELECT count(*) FROM t2_temp; -count(*) -26 -SELECT count(*) FROM t3_temp; -count(*) -24 -SELECT count(*) FROM t4_temp; -count(*) -22 -SELECT c1 FROM t1_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t2_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t3_temp; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t4_temp; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -# In connection 1 -connection con1; -set AUTOCOMMIT = 0; -ALTER TABLE t1_temp DROP PRIMARY KEY; -ALTER TABLE t1_temp ADD PRIMARY KEY (c1); -ALTER TABLE t2_temp DROP PRIMARY KEY; -ALTER TABLE t2_temp ADD PRIMARY KEY (c1); -ALTER TABLE t3_temp DROP PRIMARY KEY; -ALTER TABLE t3_temp ADD PRIMARY KEY (c1); -ALTER TABLE t4_temp DROP PRIMARY KEY; -ALTER TABLE t4_temp ADD PRIMARY KEY (c1); -INSERT INTO t1_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t1_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' -INSERT INTO t2_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t2_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' -INSERT INTO t3_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t3_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' -INSERT INTO t4_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -insert ignore into t4_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -Warnings: -Warning 1062 Duplicate entry '20' for key 'PRIMARY' -INSERT INTO t1_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -INSERT INTO t2_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -INSERT INTO t3_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -INSERT INTO t4_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); -ERROR 23000: Duplicate entry '20' for key 'PRIMARY' -set AUTOCOMMIT = 1; -SELECT c1,c2 FROM t1_temp WHERE c1 in (20,1); -c1 c2 -20 20 -SELECT c1,c2 FROM t2_temp WHERE c1 in (20,1); -c1 c2 -20 20 -SELECT c1,c2 FROM t3_temp WHERE c1 in (20,1); -c1 c2 -20 20 -SELECT c1,c2 FROM t4_temp WHERE c1 in (20,1); -c1 c2 -20 20 -REPLACE INTO t1_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -REPLACE INTO t2_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -REPLACE INTO t3_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -REPLACE INTO t4_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t1_temp WHERE c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t2_temp WHERE c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t3_temp WHERE c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t4_temp WHERE c1 = 20; -c1 c2 c3 c4 c5 c6 c7 c9 -20 1 a a a a a 100.550 -update ignore t1_temp set c1 = 20 WHERE c1 = 140 ; -update ignore t2_temp set c1 = 20 WHERE c1 = 140 ; -update ignore t3_temp set c1 = 20 WHERE c1 = 140 ; -update ignore t4_temp set c1 = 20 WHERE c1 = 140 ; -SELECT count(*) FROM t1_temp WHERE c1 = 140; -count(*) -1 -SELECT count(*) FROM t2_temp WHERE c1 = 140; -count(*) -1 -SELECT count(*) FROM t3_temp WHERE c1 = 140; -count(*) -1 -SELECT count(*) FROM t4_temp WHERE c1 = 140; -count(*) -1 -ALTER TABLE t1_temp ADD COLUMN c10 int default 99 , -ADD COLUMN c11 varchar(100) default 'test'; -ALTER TABLE t1_temp DROP PRIMARY KEY; -ALTER TABLE t1_temp ADD PRIMARY KEY (c1); -INSERT INTO t1_temp (c1,c2,c3,c4,c5,c6,c7,c8,c9) VALUES (-1,-1,'a','a','a','a','a',NOW(),100.55); -SELECT c1,c2,c3,c4,c5,c6,c7,c9,c10,c11 FROM t1_temp WHERE c1 < 0; -c1 c2 c3 c4 c5 c6 c7 c9 c10 c11 --1 -1 a a a a a 100.550 99 test -SELECT count(*) FROM t1_temp WHERE c10 = 99 and c11 like 'test'; -count(*) -27 -INSERT INTO t1_temp (c1,c2,c3,c4,c5,c6,c7,c8,c9) VALUES (-1,-1,'a','a','a','a','a',NOW(),100.55) -ON DUPLICATE KEY UPDATE c1=-2,c2=-2; -SELECT c1,c2,c3,c4,c5,c6,c7,c9,c10,c11 FROM t1_temp WHERE c1 < 0; -c1 c2 c3 c4 c5 c6 c7 c9 c10 c11 --2 -2 a a a a a 100.550 99 test -DROP TABLE t1_1 ,t2_1 ,t3_1,t4_1; -disconnect con1; -connection con2; -DROP TABLE t1_2 ,t2_2 ,t3_2,t4_2; -disconnect con2; -connection default; -connect con1,localhost,root,,; -connect con2,localhost,root,,; -connection con1; -call populate_tables('_1');; -connection con2; -call populate_tables('_2');; -"#connection 1 - verify tables" -connection con1; -SELECT count(*) FROM t1_1; -count(*) -36 -SELECT count(*) FROM t2_1; -count(*) -36 -SELECT count(*) FROM t3_1; -count(*) -34 -SELECT count(*) FROM t4_1; -count(*) -32 -SELECT c1 FROM t1_1; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t2_1; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t3_1; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t4_1; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT count(*) FROM t1_temp; -count(*) -26 -SELECT count(*) FROM t2_temp; -count(*) -26 -SELECT count(*) FROM t3_temp; -count(*) -24 -SELECT count(*) FROM t4_temp; -count(*) -22 -SELECT c1 FROM t1_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t2_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t3_temp; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t4_temp; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -DROP TABLE t1_1 ,t2_1 ,t3_1,t4_1; -disconnect con1; -"#connection 2 - verify tables" -connection con2; -SELECT count(*) FROM t1_2; -count(*) -36 -SELECT count(*) FROM t2_2; -count(*) -36 -SELECT count(*) FROM t3_2; -count(*) -34 -SELECT count(*) FROM t4_2; -count(*) -32 -SELECT c1 FROM t1_2; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t2_2; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t3_2; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t4_2; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT count(*) FROM t1_temp; -count(*) -26 -SELECT count(*) FROM t2_temp; -count(*) -26 -SELECT count(*) FROM t3_temp; -count(*) -24 -SELECT count(*) FROM t4_temp; -count(*) -22 -SELECT c1 FROM t1_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t2_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t3_temp; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t4_temp; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -DROP TABLE t1_2 ,t2_2 ,t3_2,t4_2; -disconnect con2; -connection default; -connect con1,localhost,root,,; -connect con2,localhost,root,,; -connection con1; -call populate_tables('_1');; -connection con2; -call populate_tables('_2');; -"#connection 1 - verify tables" -connection con1; -SELECT count(*) FROM t1_1; -count(*) -36 -SELECT count(*) FROM t2_1; -count(*) -36 -SELECT count(*) FROM t3_1; -count(*) -34 -SELECT count(*) FROM t4_1; -count(*) -32 -SELECT c1 FROM t1_1; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t2_1; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t3_1; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t4_1; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT count(*) FROM t1_temp; -count(*) -26 -SELECT count(*) FROM t2_temp; -count(*) -26 -SELECT count(*) FROM t3_temp; -count(*) -24 -SELECT count(*) FROM t4_temp; -count(*) -22 -SELECT c1 FROM t1_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t2_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t3_temp; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t4_temp; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -DROP TABLE t1_1 ,t2_1 ,t3_1,t4_1; -disconnect con1; -"#connection 2 - verify tables" -connection con2; -SELECT count(*) FROM t1_2; -count(*) -36 -SELECT count(*) FROM t2_2; -count(*) -36 -SELECT count(*) FROM t3_2; -count(*) -34 -SELECT count(*) FROM t4_2; -count(*) -32 -SELECT c1 FROM t1_2; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t2_2; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t3_2; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT c1 FROM t4_2; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -SELECT count(*) FROM t1_temp; -count(*) -26 -SELECT count(*) FROM t2_temp; -count(*) -26 -SELECT count(*) FROM t3_temp; -count(*) -24 -SELECT count(*) FROM t4_temp; -count(*) -22 -SELECT c1 FROM t1_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t2_temp; -c1 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t3_temp; -c1 -5 -6 -7 -8 -9 -10 -13 -14 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -SELECT c1 FROM t4_temp; -c1 -5 -6 -7 -8 -9 -10 -15 -16 -17 -18 -19 -20 -122 -124 -126 -128 -130 -132 -134 -136 -138 -140 -DROP TABLE t1_2 ,t2_2 ,t3_2,t4_2; -disconnect con2; -connection default; -DROP PROCEDURE populate_tables; diff --git a/mysql-test/suite/innodb_zip/t/disabled.def b/mysql-test/suite/innodb_zip/t/disabled.def deleted file mode 100644 index 02adb097c9d..00000000000 --- a/mysql-test/suite/innodb_zip/t/disabled.def +++ /dev/null @@ -1,14 +0,0 @@ -############################################################################## -# -# List the test cases that are to be disabled temporarily. -# -# Separate the test case name and the comment with ':'. -# -# : BUG# -# -# Do not use any TAB characters for whitespace. -# -############################################################################## - -wl6560 : Very long, timeout - diff --git a/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test b/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test index 8c746fe8abf..e6392759d5e 100644 --- a/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test +++ b/mysql-test/suite/innodb_zip/t/wl6501_scale_1.test @@ -22,20 +22,16 @@ let $wl6501_file_per_table = 1; let $wl6501_row_fmt = compact; let $wl6501_kbs = 16; -let $wl6501_file_format = 'Antelope'; --source suite/innodb_zip/include/innodb_wl6501_scale.inc # Single-Tablespace/Compressed let $wl6501_file_per_table = 1; let $wl6501_row_fmt = compressed; let $wl6501_kbs = 16; -let $wl6501_file_format = 'Barracuda'; --source suite/innodb_zip/include/innodb_wl6501_scale.inc # System-Tablespace/Non-Compressed let $wl6501_file_per_table = 0; let $wl6501_row_fmt = compact; let $wl6501_kbs = 16; -let $wl6501_file_format = 'Antelope'; --source suite/innodb_zip/include/innodb_wl6501_scale.inc - diff --git a/mysql-test/suite/innodb_zip/t/wl6560.test b/mysql-test/suite/innodb_zip/t/wl6560.test deleted file mode 100644 index 55d36747938..00000000000 --- a/mysql-test/suite/innodb_zip/t/wl6560.test +++ /dev/null @@ -1,422 +0,0 @@ -# -# WL#6560: InnoDB: separate tablespace for innodb-temp-tables. -# - ---source include/have_innodb.inc ---source include/have_innodb_zip.inc -# Embedded server does not restart of server ---source include/not_embedded.inc --- source include/big_test.inc - ---disable_query_log -call mtr.add_suppression("Tablespace innodb_temporary ran out of space. Please add another file or use 'autoextend' for the last file in setting innodb_temp_data_file_path."); -call mtr.add_suppression("The table 't1' is full"); ---enable_query_log - -################################################################################ -# -# Will test following scenarios: -# 1. creation of shared temp-tablespace. -# 2. ddl + dml operation involving temp-tablespace. -# insert/delete/update/select -# create/drop/alter/truncate/import-discard (though blocked). -# 3. ddl + dml operation on compressed table. -# (table doesn't reside in shared temp-tablespace). -# 4. Test bulk-loading that result in auto-extension of temp-tablespace. -# 5. re-creation of temp-tablespace on re-start. -# also to ensure non-existence of existing temp-table. -# 6. restart server in innodb-read-only mode. this will also -# block creation of temp-tables. -# 7. try starting server with shared and temp-tablespace filename same. -# 8. try re-starting server with param so that temp-tablespace can't be -# expanded and insert enough data to make it full. -# 9. tests for different row format types and key block sizes for -# compressed tables. -# 10. try restarting server with raw device specified for temp-tablespace. -# 11. try restarting server with temp-tablespace less than min. threshold -# 12. no file specified for temp-tablespace. -################################################################################ - -#----------------------------------------------------------------------------- -# -# create test-bed -# -let $per_table = `select @@innodb_file_per_table`; - -set global innodb_file_per_table = off; -let $MYSQL_TMP_DIR = `select @@tmpdir`; -let $MYSQL_DATA_DIR = `select @@datadir`; -let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; -let $args = --loose-console --core-file > $SEARCH_FILE 2>&1; -let crash = --loose-console > $SEARCH_FILE 2>&1 --innodb-force-recovery-crash; -let readonly = $args --innodb_read_only; -let nameconflicts = $args --innodb_data_file_path="ibdata1:12M:autoextend:max:134217728" --innodb_temp_data_file_path="ibdata1:12M:autoextend"; -let rawdevice1 = $args --innodb_temp_data_file_path="/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw"; -let rawdevice2 = $args --innodb_temp_data_file_path="/dev/hdd1:3Graw;/dev/hdd2:2Graw"; -let sizeoftempfile1 = $args --innodb_temp_data_file_path="ibtmp1:2M:autoextend"; -let sizeoftempfile2 = $args --innodb_data_file_path="ibdata1:2M:autoextend"; -let notemptablespacefile = $args --innodb_temp_data_file_path=""; - -#----------------------------------------------------------------------------- -# -# 1. creation of shared temp-tablespace. -# ---echo # files in MYSQL_DATA_DIR ---list_files $MYSQL_DATA_DIR/ ibtmp* - - -#----------------------------------------------------------------------------- -# -# 2. ddl + dml operation involving temp-tablespace. -# insert/delete/update/select -# create/drop/alter/truncate/import-discard (though blocked). -# -select @@global.innodb_file_per_table; -create temporary table t1 (i int, f float, c char(100)) engine=innodb; -# ---source suite/innodb_zip/include/innodb_temp_table_dml.inc -# -# alter table ---error ER_CANNOT_DISCARD_TEMPORARY_TABLE -alter table t1 discard tablespace; ---error ER_CANNOT_DISCARD_TEMPORARY_TABLE -alter table t1 import tablespace; -# -# drop table -drop table t1; - -#----------------------------------------------------------------------------- -# -# 3. ddl + dml operation on compressed table. -# (table doesn't reside in shared temp-tablespace). -# ---echo #files in MYSQL_TMP_DIR ---list_files $MYSQL_TMP_DIR/ *.ibd -set global innodb_file_per_table = 1; -select @@global.innodb_file_per_table; -create temporary table t1 - (i int, f float, c char(100)) engine = innodb key_block_size = 4; -show create table t1; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -# ---source suite/innodb_zip/include/innodb_temp_table_dml.inc -# -# alter table ---error ER_CANNOT_DISCARD_TEMPORARY_TABLE -alter table t1 discard tablespace; -# -# drop table -drop table t1; -set global innodb_file_per_table = off; - -#----------------------------------------------------------------------------- -# -# 4. Test bulk-loading that result in auto-extension of temp-tablespace. -# -create temporary table t1 - (keyc int, c1 char(100), c2 char(100), - primary key(keyc)) engine = innodb; -delimiter |; -CREATE PROCEDURE populate_t1() -BEGIN - DECLARE i INT DEFAULT 1; - while (i <= 20000) DO - insert into t1 values (i, 'a', 'b'); - SET i = i + 1; - END WHILE; -END| -delimiter ;| -set autocommit=0; -select count(*) from t1; -call populate_t1(); -select count(*) from t1; -select * from t1 limit 10; -set autocommit=1; -truncate table t1; -select count(*) from t1; -# -drop procedure populate_t1; -drop table t1; - -#----------------------------------------------------------------------------- -# -# 5. re-creation of temp-tablespace on re-start. -# also to ensure non-existence of existing temp-table. -# -create temporary table t1 (keyc int, c1 char(100), c2 char(100)) engine = innodb; -insert into t1 values (1, 'c', 'b'); -select * from t1; -# ---source include/restart_mysqld.inc -# ---echo # files in MYSQL_DATA_DIR ---list_files $MYSQL_DATA_DIR/ ibtmp* -use test; ---error ER_NO_SUCH_TABLE -select * from t1; - -#----------------------------------------------------------------------------- -# -# 6. restart server in innodb-read-only mode. this will also -# block creation of temp-tables. -# -# ---echo "testing temp-table creation in --innodb_read_only mode" -let $restart_parameters=--innodb-read-only; ---source include/restart_mysqld.inc -# -use test; -show tables; ---error ER_INNODB_READ_ONLY, 1005 -create temporary table t1 (keyc int, c1 char(100), c2 char(100)) engine = innodb; - -#----------------------------------------------------------------------------- -# -# 7. try starting server with shared and temp-tablespace filename same. -# ---source include/shutdown_mysqld.inc ---echo "testing system and temp tablespace name conflict" ---error 1 ---exec $MYSQLD_CMD $nameconflicts -let SEARCH_PATTERN = innodb_temporary and innodb_system file names seem to be the same; ---source ./include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo "restarting server in normal mode" ---enable_reconnect -let $restart_parameters = restart; ---source include/start_mysqld.inc -# -show tables; -create temporary table t1 (keyc int, c1 char(100), c2 char(100)) engine = innodb; -drop table t1; - -#----------------------------------------------------------------------------- -# -# 8. try re-starting server with param so that temp-tablespace can't be expanded -# and insert enough data to make it full. -# ---echo # test condition of full-temp-tablespace -let $restart_parameters=--innodb_temp_data_file_path=ibtmp1:12M; ---source include/restart_mysqld.inc -# -create temporary table t1 - (keyc int, c1 char(100), c2 char(100), - primary key(keyc)) engine = innodb; -delimiter |; -CREATE PROCEDURE populate_t1() -BEGIN - DECLARE i INT DEFAULT 1; - while (i <= 20000) DO - insert into t1 values (i, 'a', 'b'); - SET i = i + 1; - END WHILE; -END| -delimiter ;| -set autocommit=0; -select count(*) from t1; ---error ER_RECORD_FILE_FULL -call populate_t1(); -# -drop procedure populate_t1; -drop table t1; - -#----------------------------------------------------------------------------- -# -# 9. tests for different row format types and key block sizes for -# compressed tables. -# -set innodb_strict_mode = off; ---disable_warnings -set global innodb_file_per_table = 0; -set global innodb_file_format = 'Antelope'; -create temporary table t ( - i int) - engine = innodb row_format = compressed; ---replace_regex /[0-9]+/NUMBER/ -show warnings; -drop table t; -# -create temporary table t ( - i int) - engine = innodb row_format = compressed key_block_size = 8; ---replace_regex /[0-9]+/NUMBER/ -show warnings; -# -drop table t; -set global innodb_file_per_table = 1; -create temporary table t ( - i int) - engine = innodb row_format = compressed key_block_size = 8; ---replace_regex /[0-9]+/NUMBER/ -show warnings; -drop table t; -# -create temporary table t ( - i int) - engine = innodb row_format = dynamic; ---replace_regex /[0-9]+/NUMBER/ -show warnings; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -drop table t; -# -set innodb_strict_mode = on; -create temporary table t ( - i int) - engine = innodb row_format = dynamic; ---replace_regex /[0-9]+/NUMBER/ -drop table t; -# -set global innodb_file_format = 'Barracuda'; -set innodb_strict_mode = off; -create temporary table t ( - i int) - engine = innodb row_format = compressed key_block_size = 8; ---replace_regex /[0-9]+/NUMBER/ -# explicitly disabling it else it will generate warning of ignoring -# key_block_size when suite is run with innodb-page-size=4k -#show warnings; -set innodb_strict_mode = default; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -# -drop table t; -create temporary table t ( - i int) - engine = innodb row_format = compressed; ---replace_regex /[0-9]+/NUMBER/ -show warnings; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -drop table t; -# -create temporary table t ( - i int) - engine = innodb row_format = dynamic; ---replace_regex /[0-9]+/NUMBER/ -show warnings; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -drop table t; -# -set innodb_strict_mode = on; -create temporary table t ( - i int) - engine = innodb row_format = dynamic; ---replace_regex /[0-9]+/NUMBER/ -show warnings; -drop table t; -set innodb_strict_mode = off; -# ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -create temporary table t ( - i int) - engine = innodb row_format = dynamic key_block_size = 4; ---replace_regex /[0-9]+/NUMBER/ -show warnings; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -drop table t; -# -create temporary table t ( - i int) - engine = innodb row_format = compact; ---replace_regex /[0-9]+/NUMBER/ -show warnings; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -drop table t; -# -create temporary table t ( - i int) - engine = innodb key_block_size = 4; ---replace_regex /[0-9]+/NUMBER/ -show warnings; ---echo #files in MYSQL_TMP_DIR ---replace_regex /#sql[0-9a-f_]*/#sql/ ---list_files $MYSQL_TMP_DIR/ *.ibd -drop table t; -# - -#----------------------------------------------------------------------------- -# -# 10. try restarting server with raw device specified for temp-tablespace. -# ---source include/shutdown_mysqld.inc ---echo "testing temp tablespace non-support for raw device" ---error 1 ---exec $MYSQLD_CMD $rawdevice1 -let SEARCH_PATTERN = support raw device; ---source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo "testing temp tablespace non-support for raw device" ---error 1 ---exec $MYSQLD_CMD $rawdevice2 -let SEARCH_PATTERN = support raw device; ---source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE - ---source include/start_mysqld.inc - -show tables; -create temporary table t1 ( - keyc int, c1 char(100), c2 char(100) - ) engine = innodb; -drop table t1; - -#----------------------------------------------------------------------------- -# -# 11. try restarting server with temp-tablespace less than min. threshold -# ---source include/shutdown_mysqld.inc ---echo "try starting server with temp-tablespace size < min. threshold" ---error 1 ---exec $MYSQLD_CMD $sizeoftempfile1 -let SEARCH_PATTERN = Tablespace size must be at least; ---source ./include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo "try starting server with sys-tablespace size < min. threshold" ---error 1 ---exec $MYSQLD_CMD $sizeoftempfile2 -let SEARCH_PATTERN = Tablespace size must be at least; ---source ./include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE - ---source include/start_mysqld.inc - -show tables; -create temporary table t1 ( - keyc int, c1 char(100), c2 char(100) - ) engine = innodb; -drop table t1; - -#----------------------------------------------------------------------------- -# -# 12. no file specified for temp-tablespace. -# ---source include/shutdown_mysqld.inc - ---echo "try starting server with no file specified for temp-tablespace" ---error 1 ---exec $MYSQLD_CMD $notemptablespacefile -let SEARCH_PATTERN = init function returned error; ---source ./include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE - ---source include/start_mysqld.inc - -show tables; -create temporary table t1 ( - keyc int, c1 char(100), c2 char(100) - ) engine = innodb; -drop table t1; diff --git a/mysql-test/suite/innodb_zip/t/wl6915_1.test b/mysql-test/suite/innodb_zip/t/wl6915_1.test deleted file mode 100644 index 7f0f734d16a..00000000000 --- a/mysql-test/suite/innodb_zip/t/wl6915_1.test +++ /dev/null @@ -1,650 +0,0 @@ ---source include/have_innodb.inc ---source include/have_innodb_zip.inc ---source include/have_no_undo_tablespaces.inc ---source include/big_test.inc - -# Embedded server does not support restarting ---source include/not_embedded.inc -# Avoid CrashReporter popup on Mac ---source include/not_crashrep.inc - -#################################################################### -# TC to test temp-table undolog changes correctness # -# Sceanrio covered in single testcase : # -# - Tables with row format(redundant,compressed,dynamic,compact # -# - Table with primary,composite,prefix,secondary INDEX # -# - Insert/delete/update with transactioons # -# - Transaction with COMMIT,rollback,savepoint statements # -# - Transaction having temporary table and normal table # -# - Concurrency by execution of two clients creating tables with # -# same names # -# - Inserting data using # -# - Insert into .. , Load data infile..,insert ignore # -# - Insert into .. on duplicate update # -# - Check basic delete and upadte [ignore] # -# - Check constraints like duplicate key,default value # -# - Alter ADD COLUMN , ADD PRIMARY KEY # -# - Flush Tables, logs command # -# - Vary innodb_undo_tablespaces=0,innodb_undo_logs # -# innodb_log_files_in_group # -# - Verify rseg message from server log # -#################################################################### - -# run for page size >= 8k ---disable_warnings -if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE LOWER(variable_name) = 'innodb_page_size' AND variable_value >= 8192`) -{ - --skip Test requires InnoDB with page size >= 8k. -} ---enable_warnings - -call mtr.ADD_suppression(".*Resizing redo log.*"); -call mtr.ADD_suppression(".*Starting to delete and rewrite log files.*"); -call mtr.ADD_suppression(".*New log files created.*"); -# Save initial VALUES of server variable ---disable_query_log -let $innodb_file_per_table_orig=`SELECT @@innodb_file_per_table`; ---enable_query_log - -SELECT @@global.innodb_undo_tablespaces; - -# Create procedure to perform -# 1. Create temp table with row types , INDEX , sufficent data types -# 2. Perform DML with transaction -delimiter |; -CREATE PROCEDURE populate_tables(IN id VARCHAR(10)) - begin - declare n int default 20; - set global innodb_file_per_table=on; - DROP TABLE IF EXISTS t1,t2,t3,t4; - - CREATE TEMPORARY TABLE t1_temp(c1 int NOT NULL, - c2 int NOT NULL, - c3 char(255) NOT NULL, - c4 text(600) NOT NULL, - c5 blob(600) NOT NULL, - c6 varchar(600) NOT NULL, - c7 varchar(600) NOT NULL, - c8 datetime, - c9 decimal(6,3), - PRIMARY KEY (c1), - INDEX (c3,c4(50),c5(50)), - INDEX (c2)) - ENGINE=InnoDB ROW_FORMAT=redundant; - - set @s = concat("CREATE TABLE t1",id," ( c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=redundant;"); - PREPARE createTable FROM @s; - EXECUTE createTable; - DEALLOCATE PREPARE createTable; - - - CREATE TEMPORARY TABLE t2_temp(c1 int NOT NULL, - c2 int NOT NULL, - c3 char(255) NOT NULL, - c4 text(600) NOT NULL, - c5 blob(600) NOT NULL, - c6 varchar(600) NOT NULL, - c7 varchar(600) NOT NULL, - c8 datetime, - c9 decimal(6,3), - PRIMARY KEY (c1), - INDEX (c3,c4(50),c5(50)), - INDEX (c2)) - ENGINE=InnoDB ROW_FORMAT=compact; - - set @s = concat("CREATE TABLE t2",id," (c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=compact;"); - PREPARE createTable FROM @s; - EXECUTE createTable; - DEALLOCATE PREPARE createTable; - - CREATE TEMPORARY TABLE t3_temp(c1 int NOT NULL, - c2 int NOT NULL, - c3 char(255) NOT NULL, - c4 text(600) NOT NULL, - c5 blob(600) NOT NULL, - c6 varchar(600) NOT NULL, - c7 varchar(600) NOT NULL, - c8 datetime, - c9 decimal(6,3), - PRIMARY KEY (c1), - INDEX (c3,c4(50),c5(50)), - INDEX (c2)) - ENGINE=InnoDB ROW_FORMAT=compressed key_block_size=4; - - set @s = concat("CREATE TABLE t3",id," (c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=compressed key_block_size=4;"); - PREPARE createTable FROM @s; - EXECUTE createTable; - DEALLOCATE PREPARE createTable; - - CREATE TEMPORARY TABLE t4_temp(c1 int NOT NULL, - c2 int NOT NULL, - c3 char(255) NOT NULL, - c4 text(600) NOT NULL, - c5 blob(600) NOT NULL, - c6 varchar(600) NOT NULL, - c7 varchar(600) NOT NULL, - c8 datetime, - c9 decimal(6,3), - PRIMARY KEY (c1), - INDEX (c3,c4(50),c5(50)), - INDEX (c2)) - ENGINE=InnoDB ROW_FORMAT=dynamic; - - set @s = concat("CREATE TABLE t4",id," (c1 int NOT NULL, c2 int NOT NULL, c3 char(255) NOT NULL, c4 text(600) NOT NULL, c5 blob(600) NOT NULL, c6 varchar(600) NOT NULL, c7 varchar(600) NOT NULL, c8 datetime, c9 decimal(6,3), PRIMARY KEY (c1), INDEX (c3,c4(50),c5(50)), INDEX (c2)) ENGINE=InnoDB ROW_FORMAT=dynamic;"); - PREPARE createTable FROM @s; - EXECUTE createTable; - DEALLOCATE PREPARE createTable; - - while (n > 0) do - START TRANSACTION; - set @s = concat("INSERT INTO t1",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t1_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), - REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), - REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), - NOW(),(100.55+n)); - - set @s = concat("INSERT INTO t2",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - - INSERT INTO t2_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), - REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), - REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), - NOW(),(100.55+n)); - - savepoint a; - - set @s = concat("INSERT INTO t3",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - - INSERT INTO t3_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), - REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), - REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), - NOW(),(100.55+n)); - - savepoint b; - - set @s = concat("INSERT INTO t4",id," VALUES(",n,",",n,",REPEAT(concat(' tc3_',",n,"),30), REPEAT(concat(' tc4_',",n,"),70),REPEAT(concat(' tc_',",n,"),70), REPEAT(concat(' tc6_',",n,"),70),REPEAT(concat(' tc7_',",n,"),70), NOW(),(100.55+",n,"));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - - INSERT INTO t4_temp VALUES(n,n,REPEAT(concat(' tc3_',n),30), - REPEAT(concat(' tc4_',n),70),REPEAT(concat(' tc_',n),70), - REPEAT(concat(' tc6_',n),70),REPEAT(concat(' tc7_',n),70), - NOW(),(100.55+n)); - - - if (n > 10) then - if (n > 10 and n <=12) then - ROLLBACK TO SAVEPOINT a; - COMMIT; - end if; - if (n > 12 and n < 15) then - ROLLBACK TO SAVEPOINT b; - COMMIT; - end if; - if (n > 15) then - COMMIT; - end if; - - else - if (n > 5) then - START TRANSACTION; - DELETE FROM t1_temp WHERE c1 > 10 ; - DELETE FROM t2_temp WHERE c1 > 10 ; - DELETE FROM t3_temp WHERE c1 > 10 ; - DELETE FROM t4_temp WHERE c1 > 10 ; - - rollback; - START TRANSACTION; - update t1_temp set c1 = c1 + 1000 WHERE c1 > 10; - update t2_temp set c1 = c1 + 1000 WHERE c1 > 10; - update t3_temp set c1 = c1 + 1000 WHERE c1 > 10; - update t4_temp set c1 = c1 + 1000 WHERE c1 > 10; - rollback; - end if; - end if; - - if (n < 5) then - rollback; - end if; - - FLUSH logs; - ALTER TABLE t1_temp DROP PRIMARY KEY; - ALTER TABLE t1_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); - ALTER TABLE t2_temp DROP PRIMARY KEY; - ALTER TABLE t2_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); - ALTER TABLE t3_temp DROP PRIMARY KEY; - ALTER TABLE t3_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); - ALTER TABLE t4_temp DROP PRIMARY KEY; - ALTER TABLE t4_temp ADD PRIMARY KEY (c1,c3(10),c4(10)); - FLUSH tables; - - START TRANSACTION; - set @s = concat("INSERT INTO t1",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t1_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t2",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t2_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t3",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t3_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t4",id," VALUES(",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t4_temp VALUES(n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - - - DELETE FROM t1_temp WHERE c1 between 100 and 110; - DELETE FROM t2_temp WHERE c1 between 100 and 110; - DELETE FROM t3_temp WHERE c1 between 100 and 110; - DELETE FROM t4_temp WHERE c1 between 100 and 110; - - update t1_temp set c1 = c1+1 WHERE c1>110; - update t2_temp set c1 = c1+1 WHERE c1>110; - update t3_temp set c1 = c1+1 WHERE c1>110; - update t4_temp set c1 = c1+1 WHERE c1>110; - - savepoint a; - - set @s = concat("INSERT INTO t1",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t1_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t2",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t2_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t3",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t3_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t4",id," VALUES(300+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t4_temp VALUES(300+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - savepoint b; - - set @s = concat("INSERT INTO t1",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t1_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t2",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t2_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t3",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t3_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - set @s = concat("INSERT INTO t4",id," VALUES(400+",n,"+100,",n,"+100,REPEAT(concat(' tc3_',",n,"+100),30), REPEAT(concat(' tc4_',",n,"+100),70),REPEAT(concat(' tc_',",n,"+100),70), REPEAT(concat(' tc6_',",n,"+100),60),REPEAT(concat(' tc7_',",n,"+100),60), NOW(),(100.55+",n,"+100));"); - PREPARE insertIntoTable FROM @s; - EXECUTE insertIntoTable; - DEALLOCATE PREPARE insertIntoTable; - INSERT INTO t4_temp VALUES(400+n+100,n+100,REPEAT(concat(' tc3_',n+100),30), - REPEAT(concat(' tc4_',n+100),70),REPEAT(concat(' tc_',n+100),70), - REPEAT(concat(' tc6_',n+100),60),REPEAT(concat(' tc7_',n+100),60), - NOW(),(100.55+n+100)); - savepoint c; - rollback to b; - rollback to a; - COMMIT; - COMMIT; - rollback; - set n = n - 1; - end while; -end| -delimiter ;| - -# Create two client for concurrent execution -connect (con1,localhost,root,,); -connect (con2,localhost,root,,); - ---echo #---client 1 : dml operation ---" -connection con1; --- disable_query_log -eval set global innodb_file_per_table=$innodb_file_per_table_orig; - --- enable_query_log --- disable_query_log -# call procedure ---send call populate_tables('_1'); --- enable_query_log - ---echo #---client 2 : dml operation ---" -connection con2; --- disable_query_log -eval set global innodb_file_per_table=$innodb_file_per_table_orig; --- enable_query_log --- disable_query_log -# call procedure ---send call populate_tables('_2'); - --- enable_query_log - -# check data of client connection 1 ---echo # In connection 1 -connection con1; ---reap -# 20 rows exepceted in 5 tables -SELECT count(*) FROM t1_1; -SELECT count(*) FROM t2_1; -SELECT count(*) FROM t3_1; -SELECT count(*) FROM t4_1; -SELECT c1 FROM t1_1; -SELECT c1 FROM t2_1; -SELECT c1 FROM t3_1; -SELECT c1 FROM t4_1; -SELECT count(*) FROM t1_temp; -SELECT count(*) FROM t2_temp; -SELECT count(*) FROM t3_temp; -SELECT count(*) FROM t4_temp; -SELECT c1 FROM t1_temp; -SELECT c1 FROM t2_temp; -SELECT c1 FROM t3_temp; -SELECT c1 FROM t4_temp; -# check data of client connection 2 ---echo # In connection 2 -connection con2; ---reap -# 20 rows exepceted in 5 tables -SELECT count(*) FROM t1_2; -SELECT count(*) FROM t2_2; -SELECT count(*) FROM t3_2; -SELECT count(*) FROM t4_2; -SELECT c1 FROM t1_2; -SELECT c1 FROM t2_2; -SELECT c1 FROM t3_2; -SELECT c1 FROM t4_2; -SELECT count(*) FROM t1_temp; -SELECT count(*) FROM t2_temp; -SELECT count(*) FROM t3_temp; -SELECT count(*) FROM t4_temp; -SELECT c1 FROM t1_temp; -SELECT c1 FROM t2_temp; -SELECT c1 FROM t3_temp; -SELECT c1 FROM t4_temp; - ---echo # In connection 1 -connection con1; - -set AUTOCOMMIT = 0; -ALTER TABLE t1_temp DROP PRIMARY KEY; -ALTER TABLE t1_temp ADD PRIMARY KEY (c1); -ALTER TABLE t2_temp DROP PRIMARY KEY; -ALTER TABLE t2_temp ADD PRIMARY KEY (c1); -ALTER TABLE t3_temp DROP PRIMARY KEY; -ALTER TABLE t3_temp ADD PRIMARY KEY (c1); -ALTER TABLE t4_temp DROP PRIMARY KEY; -ALTER TABLE t4_temp ADD PRIMARY KEY (c1); -# Check duplicate key constraint + insert ignore ---error ER_DUP_ENTRY -INSERT INTO t1_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -insert ignore into t1_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); ---error ER_DUP_ENTRY -INSERT INTO t2_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -insert ignore into t2_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); ---error ER_DUP_ENTRY -INSERT INTO t3_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -insert ignore into t3_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); ---error ER_DUP_ENTRY -INSERT INTO t4_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -insert ignore into t4_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); - -# check rollback due to duplicate value in second record of insert ---error ER_DUP_ENTRY -INSERT INTO t1_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); ---error ER_DUP_ENTRY -INSERT INTO t2_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); ---error ER_DUP_ENTRY -INSERT INTO t3_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); ---error ER_DUP_ENTRY -INSERT INTO t4_temp VALUES (1,1,'a','a','a','a','a',NOW(),100.55), -(20,1,'a','a','a','a','a',NOW(),100.55); - -set AUTOCOMMIT = 1; - -SELECT c1,c2 FROM t1_temp WHERE c1 in (20,1); -SELECT c1,c2 FROM t2_temp WHERE c1 in (20,1); -SELECT c1,c2 FROM t3_temp WHERE c1 in (20,1); -SELECT c1,c2 FROM t4_temp WHERE c1 in (20,1); - -#replace statement -REPLACE INTO t1_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -REPLACE INTO t2_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -REPLACE INTO t3_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -REPLACE INTO t4_temp VALUES (20,1,'a','a','a','a','a',NOW(),100.55); -# verify row is replaced FROM (20,20) to (20,1) -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t1_temp WHERE c1 = 20; -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t2_temp WHERE c1 = 20; -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t3_temp WHERE c1 = 20; -SELECT c1,c2,c3,c4,c5,c6,c7,c9 FROM t4_temp WHERE c1 = 20; - -# Update ignore. statement is gonored as 20 value exits -update ignore t1_temp set c1 = 20 WHERE c1 = 140 ; -update ignore t2_temp set c1 = 20 WHERE c1 = 140 ; -update ignore t3_temp set c1 = 20 WHERE c1 = 140 ; -update ignore t4_temp set c1 = 20 WHERE c1 = 140 ; -# see record 140 is present as last update ignored -SELECT count(*) FROM t1_temp WHERE c1 = 140; -SELECT count(*) FROM t2_temp WHERE c1 = 140; -SELECT count(*) FROM t3_temp WHERE c1 = 140; -SELECT count(*) FROM t4_temp WHERE c1 = 140; - -# Alter table to ADD COLUMN and PRIMARY KEY -ALTER TABLE t1_temp ADD COLUMN c10 int default 99 , -ADD COLUMN c11 varchar(100) default 'test'; -ALTER TABLE t1_temp DROP PRIMARY KEY; -ALTER TABLE t1_temp ADD PRIMARY KEY (c1); -INSERT INTO t1_temp (c1,c2,c3,c4,c5,c6,c7,c8,c9) VALUES (-1,-1,'a','a','a','a','a',NOW(),100.55); -SELECT c1,c2,c3,c4,c5,c6,c7,c9,c10,c11 FROM t1_temp WHERE c1 < 0; -SELECT count(*) FROM t1_temp WHERE c10 = 99 and c11 like 'test'; -# insert on duplicate key update -INSERT INTO t1_temp (c1,c2,c3,c4,c5,c6,c7,c8,c9) VALUES (-1,-1,'a','a','a','a','a',NOW(),100.55) -ON DUPLICATE KEY UPDATE c1=-2,c2=-2; -SELECT c1,c2,c3,c4,c5,c6,c7,c9,c10,c11 FROM t1_temp WHERE c1 < 0; - -# - -#cleanup -DROP TABLE t1_1 ,t2_1 ,t3_1,t4_1; -disconnect con1; - -connection con2; -DROP TABLE t1_2 ,t2_2 ,t3_2,t4_2; -disconnect con2; - - -connection default; -# -## trying with VALUES innodb_undo_tablespaces, innodb_undo_logs ,innodb_log_files_in_group -## -let $restart_parameters=--innodb_undo_tablespaces=0 --innodb_rollback_segments=20 --innodb_undo_logs=20 --innodb_log_files_in_group=4; ---source include/restart_mysqld.inc - -# Create two client for concurrent execution -connect (con1,localhost,root,,); -connect (con2,localhost,root,,); -# -# -connection con1; ---send call populate_tables('_1'); -connection con2; ---send call populate_tables('_2'); ---echo "#connection 1 - verify tables" -connection con1; ---reap -SELECT count(*) FROM t1_1; -SELECT count(*) FROM t2_1; -SELECT count(*) FROM t3_1; -SELECT count(*) FROM t4_1; -SELECT c1 FROM t1_1; -SELECT c1 FROM t2_1; -SELECT c1 FROM t3_1; -SELECT c1 FROM t4_1; -SELECT count(*) FROM t1_temp; -SELECT count(*) FROM t2_temp; -SELECT count(*) FROM t3_temp; -SELECT count(*) FROM t4_temp; -SELECT c1 FROM t1_temp; -SELECT c1 FROM t2_temp; -SELECT c1 FROM t3_temp; -SELECT c1 FROM t4_temp; -DROP TABLE t1_1 ,t2_1 ,t3_1,t4_1; -disconnect con1; ---echo "#connection 2 - verify tables" -connection con2; ---reap -SELECT count(*) FROM t1_2; -SELECT count(*) FROM t2_2; -SELECT count(*) FROM t3_2; -SELECT count(*) FROM t4_2; -SELECT c1 FROM t1_2; -SELECT c1 FROM t2_2; -SELECT c1 FROM t3_2; -SELECT c1 FROM t4_2; -SELECT count(*) FROM t1_temp; -SELECT count(*) FROM t2_temp; -SELECT count(*) FROM t3_temp; -SELECT count(*) FROM t4_temp; -SELECT c1 FROM t1_temp; -SELECT c1 FROM t2_temp; -SELECT c1 FROM t3_temp; -SELECT c1 FROM t4_temp; -DROP TABLE t1_2 ,t2_2 ,t3_2,t4_2; -disconnect con2; - -connection default; -# innodb_undo_logs > non redo rsegment -let $restart_parameters=--innodb_undo_tablespaces=0 --innodb_rollback_segments=30 --innodb_undo_logs=20 --innodb_log_files_in_group=4; ---source include/restart_mysqld.inc - -connect (con1,localhost,root,,); -connect (con2,localhost,root,,); - -connection con1; ---send call populate_tables('_1'); -connection con2; ---send call populate_tables('_2'); ---echo "#connection 1 - verify tables" -connection con1; ---reap -SELECT count(*) FROM t1_1; -SELECT count(*) FROM t2_1; -SELECT count(*) FROM t3_1; -SELECT count(*) FROM t4_1; -SELECT c1 FROM t1_1; -SELECT c1 FROM t2_1; -SELECT c1 FROM t3_1; -SELECT c1 FROM t4_1; -SELECT count(*) FROM t1_temp; -SELECT count(*) FROM t2_temp; -SELECT count(*) FROM t3_temp; -SELECT count(*) FROM t4_temp; -SELECT c1 FROM t1_temp; -SELECT c1 FROM t2_temp; -SELECT c1 FROM t3_temp; -SELECT c1 FROM t4_temp; -DROP TABLE t1_1 ,t2_1 ,t3_1,t4_1; -disconnect con1; ---echo "#connection 2 - verify tables" -connection con2; ---reap -SELECT count(*) FROM t1_2; -SELECT count(*) FROM t2_2; -SELECT count(*) FROM t3_2; -SELECT count(*) FROM t4_2; -SELECT c1 FROM t1_2; -SELECT c1 FROM t2_2; -SELECT c1 FROM t3_2; -SELECT c1 FROM t4_2; -SELECT count(*) FROM t1_temp; -SELECT count(*) FROM t2_temp; -SELECT count(*) FROM t3_temp; -SELECT count(*) FROM t4_temp; -SELECT c1 FROM t1_temp; -SELECT c1 FROM t2_temp; -SELECT c1 FROM t3_temp; -SELECT c1 FROM t4_temp; -DROP TABLE t1_2 ,t2_2 ,t3_2,t4_2; -disconnect con2; - -# - -connection default; -DROP PROCEDURE populate_tables; - -# check message in log -let $error_log= $MYSQLTEST_VARDIR/log/my_restart.err; -let SEARCH_FILE= $error_log; -# We get depending on the platform either "./ibdata1" or ".\ibdata1". -let SEARCH_PATTERN=redo rollback segment.*found.*redo rollback segment.*active ---source include/search_pattern_in_file.inc -let SEARCH_PATTERN=non-redo rollback.*active ---source include/search_pattern_in_file.inc - - -SHOW TABLES; - --- disable_query_log -eval set global innodb_file_per_table=$innodb_file_per_table_orig; --- enable_query_log - diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 03fba3fde49..eea7f19d1f5 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7438,3 +7438,5 @@ ER_JSON_PATH_ARRAY eng "JSON path should end with an array identifier in argument %d to function '%s'" ER_JSON_ONE_OR_ALL eng "Argument 2 to function '%s' must be "one" or "all"." +ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE + eng "CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE." diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index f150a98e6ef..4bebb9ee7dd 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -335,8 +335,7 @@ btr_root_adjust_on_import( } else { /* Check that the table flags and the tablespace flags match. */ - ulint flags = dict_tf_to_fsp_flags( - table->flags, false); + ulint flags = dict_tf_to_fsp_flags(table->flags); ulint fsp_flags = fil_space_get_flags(table->space); err = flags == fsp_flags ? DB_SUCCESS : DB_CORRUPTION; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 87d88cea820..4d0499418a2 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3048,12 +3048,12 @@ fail_err: if (*rec) { } else if (page_size.is_compressed()) { + ut_ad(!dict_table_is_temporary(index->table)); /* Reset the IBUF_BITMAP_FREE bits, because page_cur_tuple_insert() will have attempted page reorganize before failing. */ if (leaf - && !dict_index_is_clust(index) - && !dict_table_is_temporary(index->table)) { + && !dict_index_is_clust(index)) { ibuf_reset_free_bits(block); } @@ -3649,6 +3649,8 @@ btr_cur_update_in_place( /* Check that enough space is available on the compressed page. */ if (page_zip) { + ut_ad(!dict_table_is_temporary(index->table)); + if (!btr_cur_update_alloc_zip( page_zip, btr_cur_get_page_cur(cursor), index, offsets, rec_offs_size(offsets), @@ -3725,9 +3727,9 @@ func_exit: if (page_zip && !(flags & BTR_KEEP_IBUF_BITMAP) && !dict_index_is_clust(index) - && !dict_table_is_temporary(index->table) && page_is_leaf(buf_block_get_frame(block))) { /* Update the free bits in the insert buffer. */ + ut_ad(!dict_table_is_temporary(index->table)); ibuf_update_free_bits_zip(block, mtr); } @@ -3876,6 +3878,8 @@ any_extern: #endif /* UNIV_ZIP_DEBUG */ if (page_zip) { + ut_ad(!dict_table_is_temporary(index->table)); + if (page_zip_rec_needs_ext(new_rec_size, page_is_comp(page), dict_index_get_n_fields(index), dict_table_page_size(index->table))) { @@ -3994,12 +3998,12 @@ any_extern: func_exit: if (!(flags & BTR_KEEP_IBUF_BITMAP) - && !dict_index_is_clust(index) - && !dict_table_is_temporary(index->table)) { + && !dict_index_is_clust(index)) { /* Update the free bits in the insert buffer. */ if (page_zip) { + ut_ad(!dict_table_is_temporary(index->table)); ibuf_update_free_bits_zip(block, mtr); - } else { + } else if (!dict_table_is_temporary(index->table)) { ibuf_update_free_bits_low(block, max_ins_size, mtr); } } @@ -4123,6 +4127,7 @@ btr_cur_pessimistic_update( #ifdef UNIV_ZIP_DEBUG ut_a(!page_zip || page_zip_validate(page_zip, page, index)); #endif /* UNIV_ZIP_DEBUG */ + ut_ad(!page_zip || !dict_table_is_temporary(index->table)); /* The insert buffer tree should never be updated in place. */ ut_ad(!dict_index_is_ibuf(index)); ut_ad(trx_id > 0 @@ -4153,8 +4158,8 @@ btr_cur_pessimistic_update( if (page_zip && optim_err != DB_ZIP_OVERFLOW && !dict_index_is_clust(index) - && !dict_table_is_temporary(index->table) && page_is_leaf(page)) { + ut_ad(!dict_table_is_temporary(index->table)); ibuf_update_free_bits_zip(block, mtr); } @@ -4327,14 +4332,14 @@ btr_cur_pessimistic_update( page_cursor->rec, index, *offsets); } } else if (!dict_index_is_clust(index) - && !dict_table_is_temporary(index->table) && page_is_leaf(page)) { /* Update the free bits in the insert buffer. This is the same block which was skipped by BTR_KEEP_IBUF_BITMAP. */ if (page_zip) { + ut_ad(!dict_table_is_temporary(index->table)); ibuf_update_free_bits_zip(block, mtr); - } else { + } else if (!dict_table_is_temporary(index->table)) { ibuf_update_free_bits_low(block, max_ins_size, mtr); } diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 44624f6b654..c5d8e7ee21f 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -404,6 +404,7 @@ dict_build_tablespace_for_table( DICT_TF2_FTS_AUX_HEX_NAME);); if (needs_file_per_table) { + ut_ad(!dict_table_is_temporary(table)); /* This table will need a new tablespace. */ ut_ad(dict_table_get_format(table) <= UNIV_FORMAT_MAX); @@ -424,21 +425,10 @@ dict_build_tablespace_for_table( table->space = static_cast(space); /* Determine the tablespace flags. */ - bool is_temp = dict_table_is_temporary(table); bool has_data_dir = DICT_TF_HAS_DATA_DIR(table->flags); - ulint fsp_flags = dict_tf_to_fsp_flags(table->flags, - is_temp); + ulint fsp_flags = dict_tf_to_fsp_flags(table->flags); - /* Determine the full filepath */ - if (is_temp) { - /* Temporary table filepath contains a full path - and a filename without the extension. */ - ut_ad(table->dir_path_of_temp_table); - filepath = fil_make_filepath( - table->dir_path_of_temp_table, - NULL, IBD, false); - - } else if (has_data_dir) { + if (has_data_dir) { ut_ad(table->data_dir_path); filepath = fil_make_filepath( table->data_dir_path, @@ -474,7 +464,6 @@ dict_build_tablespace_for_table( mtr_start(&mtr); mtr.set_named_space(table->space); - dict_disable_redo_if_temporary(table, &mtr); bool ret = fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 58d5870bf95..3cf236e643b 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1696,25 +1696,17 @@ dict_table_rename_in_cache( ib::info() << "Delete of " << filepath << " failed."; } - ut_free(filepath); } else if (dict_table_is_file_per_table(table)) { - if (table->dir_path_of_temp_table != NULL) { - ib::error() << "Trying to rename a TEMPORARY TABLE " - << old_name - << " ( " << table->dir_path_of_temp_table - << " )"; - return(DB_ERROR); - } - char* new_path = NULL; char* old_path = fil_space_get_first_path(table->space); + ut_ad(!dict_table_is_temporary(table)); + if (DICT_TF_HAS_DATA_DIR(table->flags)) { new_path = os_file_make_new_pathname( old_path, new_name); - err = RemoteDatafile::create_link_file( new_name, new_path); @@ -7254,12 +7246,9 @@ Other bits are the same. dict_table_t::flags | 0 | 1 | 1 | 1 fil_space_t::flags | 0 | 0 | 1 | 1 @param[in] table_flags dict_table_t::flags -@param[in] is_temp whether the tablespace is temporary @return tablespace flags (fil_space_t::flags) */ ulint -dict_tf_to_fsp_flags( - ulint table_flags, - bool is_temp) +dict_tf_to_fsp_flags(ulint table_flags) { DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure", return(ULINT_UNDEFINED);); @@ -7276,7 +7265,6 @@ dict_tf_to_fsp_flags( ulint fsp_flags = fsp_flags_init(page_size, has_atomic_blobs, has_data_dir, - is_temp, 0, 0, 0); diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index a3da3a755d6..756e1010d66 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1239,8 +1239,7 @@ dict_check_sys_tables( char* filepath = dict_get_first_path(space_id); /* Check that the .ibd file exists. */ - bool is_temp = flags2 & DICT_TF2_TEMPORARY; - ulint fsp_flags = dict_tf_to_fsp_flags(flags, is_temp); + ulint fsp_flags = dict_tf_to_fsp_flags(flags); validate = true; /* Encryption */ dberr_t err = fil_ibd_open( @@ -2513,9 +2512,9 @@ dict_get_and_save_data_dir_path( dict_table_t* table, bool dict_mutex_own) { - bool is_temp = DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY); + ut_ad(!dict_table_is_temporary(table)); - if (!is_temp && !table->data_dir_path && table->space) { + if (!table->data_dir_path && table->space) { char* path = fil_space_get_first_path(table->space); if (!dict_mutex_own) { @@ -2610,6 +2609,8 @@ dict_load_tablespace( mem_heap_t* heap, dict_err_ignore_t ignore_err) { + ut_ad(!dict_table_is_temporary(table)); + /* The system tablespace is always available. */ if (is_system_tablespace(table->space)) { return; @@ -2622,12 +2623,6 @@ dict_load_tablespace( return; } - if (dict_table_is_temporary(table)) { - /* Do not bother to retry opening temporary tables. */ - table->ibd_file_missing = TRUE; - return; - } - char* space_name = table->name.m_name; /* The tablespace may already be open. */ @@ -2662,7 +2657,7 @@ dict_load_tablespace( /* Try to open the tablespace. We set the 2nd param (fix_dict) to false because we do not have an x-lock on dict_operation_lock */ - ulint fsp_flags = dict_tf_to_fsp_flags(table->flags, false); + ulint fsp_flags = dict_tf_to_fsp_flags(table->flags); dberr_t err = fil_ibd_open( true, false, FIL_TYPE_TABLESPACE, table->space, fsp_flags, space_name, filepath, table); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 331fc34e603..bfae83af3df 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -215,12 +215,13 @@ fil_space_belongs_in_lru( const fil_space_t* space) /*!< in: file space */ { switch (space->purpose) { + case FIL_TYPE_TEMPORARY: case FIL_TYPE_LOG: return(false); case FIL_TYPE_TABLESPACE: - case FIL_TYPE_TEMPORARY: - case FIL_TYPE_IMPORT: return(fil_is_user_tablespace_id(space->id)); + case FIL_TYPE_IMPORT: + return(true); } ut_ad(0); @@ -3711,7 +3712,7 @@ func_exit: return(success); } -/** Create a new General or Single-Table tablespace +/** Create a tablespace file. @param[in] space_id Tablespace ID @param[in] name Tablespace name in dbname/tablename format. @param[in] path Path and filename of the datafile to create. @@ -3736,7 +3737,6 @@ fil_ibd_create( byte* buf2; byte* page; bool success; - bool is_temp = FSP_FLAGS_GET_TEMPORARY(flags); bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags); fil_space_t* space = NULL; fil_space_crypt_t *crypt_data = NULL; @@ -3926,21 +3926,16 @@ fil_ibd_create( crypt_data = fil_space_create_crypt_data(mode, key_id); } - space = fil_space_create(name, space_id, flags, is_temp - ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, + space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE, crypt_data, true); if (!fil_node_create_low(path, size, space, false, true)) { - if (crypt_data) { free(crypt_data); } err = DB_ERROR; - goto error_exit_1; - } - - if (!is_temp) { + } else { mtr_t mtr; const fil_node_t* file = UT_LIST_GET_FIRST(space->chain); @@ -3950,20 +3945,14 @@ fil_ibd_create( NULL, space->flags, &mtr); fil_name_write(space, 0, file, &mtr); mtr_commit(&mtr); - } - - err = DB_SUCCESS; - - /* Error code is set. Cleanup the various variables used. - These labels reflect the order in which variables are assigned or - actions are done. */ -error_exit_1: - if (err != DB_SUCCESS && has_data_dir) { - RemoteDatafile::delete_link_file(name); + err = DB_SUCCESS; } os_file_close(file); if (err != DB_SUCCESS) { + if (has_data_dir) { + RemoteDatafile::delete_link_file(name); + } os_file_delete(innodb_data_file_key, path); } @@ -4596,10 +4585,8 @@ fil_ibd_load( ut_ad(space == NULL); - bool is_temp = FSP_FLAGS_GET_TEMPORARY(file.flags()); space = fil_space_create( - file.name(), space_id, file.flags(), - is_temp ? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE, + file.name(), space_id, file.flags(), FIL_TYPE_TABLESPACE, file.get_crypt_info(), false); if (space == NULL) { @@ -4668,10 +4655,7 @@ fil_report_missing_tablespace( << " in the InnoDB data dictionary has tablespace id " << space_id << "," " but tablespace with that id or name does not exist. Have" - " you deleted or moved .ibd files? This may also be a table" - " created with CREATE TEMPORARY TABLE whose .ibd and .frm" - " files MySQL automatically removed, but the table still" - " exists in the InnoDB internal data dictionary."; + " you deleted or moved .ibd files?"; } /** Returns true if a matching tablespace exists in the InnoDB tablespace diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 00b5c37cec4..afd4ba9dddc 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -550,7 +550,10 @@ Datafile::validate_first_page(lsn_t* flush_lsn, free_first_page(); return(DB_ERROR); - + } else if (!fsp_flags_is_valid(m_flags) + || FSP_FLAGS_GET_TEMPORARY(m_flags)) { + /* Tablespace flags must be valid. */ + error_txt = "Tablespace flags are invalid"; } else if (page_get_page_no(m_first_page) != 0) { /* First page must be number 0 */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 56b1f968244..db1d90c06fe 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4098,7 +4098,7 @@ innobase_init( /* Create the filespace flags. */ fsp_flags = fsp_flags_init( - univ_page_size, false, false, false, false, 0, 0); + univ_page_size, false, false, false, 0, 0); srv_sys_space.set_flags(fsp_flags); srv_sys_space.set_name("innodb_system"); @@ -4124,7 +4124,7 @@ innobase_init( /* Create the filespace flags with the temp flag set. */ fsp_flags = fsp_flags_init( - univ_page_size, false, false, true, false, 0, 0); + univ_page_size, false, false, false, 0, 0); srv_tmp_space.set_flags(fsp_flags); if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) { @@ -11755,11 +11755,6 @@ create_table_info_t::create_table_def() ? doc_id_col : n_cols - num_v; } - if (strlen(m_temp_path) != 0) { - table->dir_path_of_temp_table = - mem_heap_strdup(table->heap, m_temp_path); - } - if (DICT_TF_HAS_DATA_DIR(m_flags)) { ut_a(strlen(m_remote_path)); @@ -12271,9 +12266,10 @@ create_table_info_t::create_options_are_invalid() const char* ret = NULL; enum row_type row_format = m_create_info->row_type; + const bool is_temp + = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; ut_ad(m_thd != NULL); - ut_ad(m_create_info != NULL); /* If innodb_strict_mode is not set don't do any more validation. */ if (!THDVAR(m_thd, strict_mode)) { @@ -12282,6 +12278,12 @@ create_table_info_t::create_options_are_invalid() /* Check if a non-zero KEY_BLOCK_SIZE was specified. */ if (has_key_block_size) { + if (is_temp) { + my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, + MYF(0)); + return("KEY_BLOCK_SIZE"); + } + switch (m_create_info->key_block_size) { ulint kbs_max; case 1: @@ -12341,6 +12343,11 @@ create_table_info_t::create_options_are_invalid() other incompatibilities. */ switch (row_format) { case ROW_TYPE_COMPRESSED: + if (is_temp) { + my_error(ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE, + MYF(0)); + return("ROW_FORMAT"); + } if (!m_allow_file_per_table) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, @@ -12361,7 +12368,7 @@ create_table_info_t::create_options_are_invalid() } break; case ROW_TYPE_DYNAMIC: - if (!m_allow_file_per_table) { + if (!m_allow_file_per_table && !is_temp) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -12370,7 +12377,7 @@ create_table_info_t::create_options_are_invalid() get_row_format_name(row_format)); ret = "ROW_FORMAT"; } - if (srv_file_format < UNIV_FORMAT_B) { + if (!is_temp && srv_file_format < UNIV_FORMAT_B) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -12595,6 +12602,10 @@ ha_innobase::update_create_info( create_info->auto_increment_value = stats.auto_increment_value; } + if (dict_table_is_temporary(m_prebuilt->table)) { + return; + } + /* Update the DATA DIRECTORY name from SYS_DATAFILES. */ dict_get_and_save_data_dir_path(m_prebuilt->table, false); @@ -12619,8 +12630,7 @@ innobase_fts_load_stopword( THDVAR(thd, ft_enable_stopword), FALSE)); } -/** Parse the table name into normal name and either temp path or remote path -if needed. +/** Parse the table name into normal name and remote path if needed. @param[in] name Table name (db/table or full path). @return 0 if successful, otherwise, error number */ int @@ -12653,17 +12663,8 @@ create_table_info_t::parse_table_name( } #endif - m_temp_path[0] = '\0'; m_remote_path[0] = '\0'; - /* A full path is provided by the server for TEMPORARY tables not - targeted for a tablespace or when DATA DIRECTORY is given. - So these two are not compatible. Likewise, DATA DIRECTORY is not - compatible with a TABLESPACE assignment. */ - if ((m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - strncpy(m_temp_path, name, FN_REFLEN - 1); - } - /* Make sure DATA DIRECTORY is compatible with other options and set the remote path. In the case of either; CREATE TEMPORARY TABLE ... DATA DIRECTORY={path} ... ; @@ -12703,11 +12704,14 @@ create_table_info_t::innobase_table_flags() DBUG_ENTER("innobase_table_flags"); const char* fts_doc_id_index_bad = NULL; - bool zip_allowed = true; ulint zip_ssize = 0; enum row_type row_type; rec_format_t innodb_row_format = get_row_format(innodb_default_row_format); + const bool is_temp + = m_create_info->options & HA_LEX_CREATE_TMP_TABLE; + bool zip_allowed + = !is_temp; const ulint zip_ssize_max = ut_min(static_cast(UNIV_PAGE_SSIZE_MAX), @@ -12735,8 +12739,7 @@ create_table_info_t::innobase_table_flags() /* We don't support FTS indexes in temporary tables. */ - if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { - + if (is_temp) { my_error(ER_INNODB_NO_FT_TEMP_TABLE, MYF(0)); DBUG_RETURN(false); } @@ -12744,12 +12747,6 @@ create_table_info_t::innobase_table_flags() if (fts_doc_id_index_bad) { goto index_bad; } - } else if (key->flags & HA_SPATIAL) { - if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE - && !m_use_file_per_table) { - my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0)); - DBUG_RETURN(false); - } } if (innobase_strcasecmp(key->name, FTS_DOC_ID_INDEX_NAME)) { @@ -12789,7 +12786,14 @@ index_bad: } /* Make sure compressed row format is allowed. */ - if (!m_allow_file_per_table) { + if (is_temp) { + push_warning( + m_thd, Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: KEY_BLOCK_SIZE is ignored" + " for TEMPORARY TABLE."); + zip_allowed = false; + } else if (!m_allow_file_per_table) { push_warning( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -12859,9 +12863,14 @@ index_bad: innodb_row_format = REC_FORMAT_COMPACT; break; case ROW_TYPE_COMPRESSED: - /* ROW_FORMAT=COMPRESSED requires file_per_table and - file_format=Barracuda unless there is a target tablespace. */ - if (!m_allow_file_per_table) { + if (is_temp) { + push_warning_printf( + m_thd, Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s is ignored for" + " TEMPORARY TABLE.", + get_row_format_name(row_type)); + } else if (!m_allow_file_per_table) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, @@ -12874,20 +12883,9 @@ index_bad: ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: ROW_FORMAT=COMPRESSED requires" " innodb_file_format > Antelope."); - } else { - switch(row_type) { - case ROW_TYPE_COMPRESSED: - innodb_row_format = REC_FORMAT_COMPRESSED; - break; - case ROW_TYPE_DYNAMIC: - innodb_row_format = REC_FORMAT_DYNAMIC; - break; - default: - /* Not possible, avoid compiler warning */ - break; - } - break; /* Correct row_format */ + innodb_row_format = REC_FORMAT_COMPRESSED; + break; } zip_allowed = false; /* fall through to set row_type = DYNAMIC */ @@ -12915,13 +12913,18 @@ index_bad: zip_allowed = false; } + ut_ad(!is_temp || !zip_allowed); + ut_ad(!is_temp || innodb_row_format != REC_FORMAT_COMPRESSED); + /* Set the table flags */ if (!zip_allowed) { zip_ssize = 0; } - if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) { + if (is_temp) { m_flags2 |= DICT_TF2_TEMPORARY; + } else if (m_use_file_per_table) { + m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE; } /* Set the table flags */ @@ -12932,10 +12935,6 @@ index_bad: default_compression_level : options->page_compression_level, 0); - if (m_use_file_per_table) { - m_flags2 |= DICT_TF2_USE_FILE_PER_TABLE; - } - /* Set the flags2 when create table or alter tables */ m_flags2 |= DICT_TF2_FTS_AUX_HEX_NAME; DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", @@ -13125,24 +13124,16 @@ create_table_info_t::set_tablespace_type( m_innodb_file_per_table || table_being_altered_is_file_per_table; - /* All noncompresed temporary tables will be put into the - system temporary tablespace. */ - bool is_noncompressed_temporary = - m_create_info->options & HA_LEX_CREATE_TMP_TABLE - && !(m_create_info->row_type == ROW_TYPE_COMPRESSED - || m_create_info->key_block_size > 0); - /* Ignore the current innodb-file-per-table setting if we are - creating a temporary, non-compressed table. */ + creating a temporary table. */ m_use_file_per_table = m_allow_file_per_table - && !is_noncompressed_temporary; + && !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE); /* DATA DIRECTORY must have m_use_file_per_table but cannot be used with TEMPORARY tables. */ m_use_data_dir = m_use_file_per_table - && !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE) && (m_create_info->data_file_name != NULL) && (m_create_info->data_file_name[0] != '\0'); } @@ -13570,7 +13561,6 @@ ha_innobase::create( { int error; char norm_name[FN_REFLEN]; /* {database}/{tablename} */ - char temp_path[FN_REFLEN]; /* Absolute path of temp frm */ char remote_path[FN_REFLEN]; /* Absolute path of table */ trx_t* trx; DBUG_ENTER("ha_innobase::create"); @@ -13579,7 +13569,6 @@ ha_innobase::create( form, create_info, norm_name, - temp_path, remote_path); /* Initialize the object. */ diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 066eff12ca9..d11d5913f34 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 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 @@ -688,13 +688,11 @@ public: TABLE* form, HA_CREATE_INFO* create_info, char* table_name, - char* temp_path, char* remote_path) :m_thd(thd), m_form(form), m_create_info(create_info), m_table_name(table_name), - m_temp_path(temp_path), m_remote_path(remote_path), m_innodb_file_per_table(srv_file_per_table) {} @@ -804,12 +802,6 @@ private: /** Table name */ char* m_table_name; - /** If this is a table explicitly created by the user with the - TEMPORARY keyword, then this parameter is the dir path where the - table should be placed if we create an .ibd file for it - (no .ibd extension in the path, though). - Otherwise this is a zero length-string */ - char* m_temp_path; /** Remote path (DATA DIRECTORY) or zero length-string */ char* m_remote_path; diff --git a/storage/innobase/handler/ha_innopart.cc b/storage/innobase/handler/ha_innopart.cc index 80f3b410ee7..6cdbd226b24 100644 --- a/storage/innobase/handler/ha_innopart.cc +++ b/storage/innobase/handler/ha_innopart.cc @@ -2607,8 +2607,6 @@ ha_innopart::create( int error; /** {database}/{tablename} */ char table_name[FN_REFLEN]; - /** absolute path of temp frm */ - char temp_path[FN_REFLEN]; /** absolute path of table */ char remote_path[FN_REFLEN]; char partition_name[FN_REFLEN]; @@ -2623,7 +2621,6 @@ ha_innopart::create( form, create_info, table_name, - temp_path, remote_path); DBUG_ENTER("ha_innopart::create"); @@ -2649,7 +2646,6 @@ ha_innopart::create( if (error != 0) { DBUG_RETURN(error); } - ut_ad(temp_path[0] == '\0'); strcpy(partition_name, table_name); partition_name_start = partition_name + strlen(partition_name); table_name_len = strlen(table_name); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 8ba9f6cb175..341c341f112 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -5588,7 +5588,6 @@ ha_innobase::prepare_inplace_alter_table( altered_table, ha_alter_info->create_info, NULL, - NULL, NULL); info.set_tablespace_type(indexed_table->space != TRX_SYS_SPACE); diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index a7fe80e447d..349b105be6a 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1036,12 +1036,9 @@ dict_table_t::flags | 0 | 1 | 1 | 1 fil_space_t::flags | 0 | 0 | 1 | 1 ================================================================== @param[in] table_flags dict_table_t::flags -@param[in] is_temp whether the tablespace is temporary @return tablespace flags (fil_space_t::flags) */ ulint -dict_tf_to_fsp_flags( - ulint table_flags, - bool is_temp) +dict_tf_to_fsp_flags(ulint table_flags) MY_ATTRIBUTE((const)); /** Extract the page size from table flags. diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 6717e7085c2..ccfc46f7941 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -1375,12 +1375,6 @@ struct dict_table_t { /** Table name. */ table_name_t name; - /** NULL or the directory path where a TEMPORARY table that was - explicitly created by a user should be placed if innodb_file_per_table - is defined in my.cnf. In Unix this is usually "/tmp/...", - in Windows "temp\...". */ - const char* dir_path_of_temp_table; - /** NULL or the directory path specified by DATA DIRECTORY. */ char* data_dir_path; diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index eebe21d85bf..3d786764148 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -956,13 +956,15 @@ fil_make_filepath( ib_extention suffix, bool strip_name); -/** Creates a new General or Single-Table tablespace +/** Create a tablespace file. @param[in] space_id Tablespace ID @param[in] name Tablespace name in dbname/tablename format. @param[in] path Path and filename of the datafile to create. @param[in] flags Tablespace flags @param[in] size Initial size of the tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE +@param[in] mode MariaDB encryption mode +@param[in] key_id MariaDB encryption key_id @return DB_SUCCESS or error code */ dberr_t fil_ibd_create( @@ -971,8 +973,8 @@ fil_ibd_create( const char* path, ulint flags, ulint size, - fil_encryption_t mode, /*!< in: encryption mode */ - ulint key_id) /*!< in: encryption key_id */ + fil_encryption_t mode, + ulint key_id) MY_ATTRIBUTE((warn_unused_result)); /********************************************************************//** diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 129842982a3..878929c085c 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -648,7 +648,9 @@ fsp_flags_is_compressed( @param[in] page_size page sizes in bytes and compression flag. @param[in] atomic_blobs Used by Dynammic and Compressed. @param[in] has_data_dir This tablespace is in a remote location. -@param[in] is_temporary This tablespace is temporary. +@param[in] page_compressed Table uses page compression +@param[in] page_compression_level Page compression level +@param[in] not_used For future @return tablespace flags after initialization */ UNIV_INLINE ulint @@ -656,7 +658,6 @@ fsp_flags_init( const page_size_t& page_size, bool atomic_blobs, bool has_data_dir, - bool is_temporary, bool page_compression, ulint page_compression_level, ulint not_used); diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index 9ff2dab75d4..6d0d6f05a9f 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -145,7 +145,6 @@ fsp_flags_set_page_size( @param[in] page_size page sizes in bytes and compression flag. @param[in] atomic_blobs Used by Dynammic and Compressed. @param[in] has_data_dir This tablespace is in a remote location. -@param[in] is_temporary This tablespace is temporary. @param[in] page_compressed Table uses page compression @param[in] page_compression_level Page compression level @param[in] not_used For future @@ -156,7 +155,6 @@ fsp_flags_init( const page_size_t& page_size, bool atomic_blobs, bool has_data_dir, - bool is_temporary, bool page_compression, ulint page_compression_level, ulint not_used) @@ -181,11 +179,6 @@ fsp_flags_init( flags |= FSP_FLAGS_MASK_DATA_DIR; } - if (is_temporary) { - ut_ad(!has_data_dir); - flags |= FSP_FLAGS_MASK_TEMPORARY; - } - /* In addition, tablespace flags also contain if the page compression is used for this table. */ if (page_compression) { diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 67482db160a..4c272d96a39 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -481,11 +481,6 @@ row_drop_table_for_mysql( bool nonatomic = true); /*!< in: whether it is permitted to release and reacquire dict_operation_lock */ -/*********************************************************************//** -Drop all temporary tables during crash recovery. */ -void -row_mysql_drop_temp_tables(void); -/*============================*/ /*********************************************************************//** Discards the tablespace of a table which stored in an .ibd file. Discarding diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index e2f5265261b..e5aab543f5d 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3535,8 +3535,6 @@ recv_recovery_rollback_active(void) /* Drop partially created indexes. */ row_merge_drop_temp_indexes(); - /* Drop temporary tables. */ - row_mysql_drop_temp_tables(); /* Drop any auxiliary tables that were not dropped when the parent table was dropped. This can happen if the parent table diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index 704ed55f2b3..e2d2dd40fd8 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -550,6 +550,7 @@ page_create_empty( } if (page_zip) { + ut_ad(!dict_table_is_temporary(index->table)); page_create_zip(block, index, page_header_get_field(page, PAGE_LEVEL), max_trx_id, NULL, mtr); diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index c47a1905b4b..35ef24c16a6 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -4688,6 +4688,7 @@ page_zip_reorganize( ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); ut_ad(page_is_comp(page)); ut_ad(!dict_index_is_ibuf(index)); + ut_ad(!dict_table_is_temporary(index->table)); /* Note that page_zip_validate(page_zip, page, index) may fail here. */ UNIV_MEM_ASSERT_RW(page, UNIV_PAGE_SIZE); UNIV_MEM_ASSERT_RW(page_zip->data, page_zip_get_size(page_zip)); @@ -4719,7 +4720,6 @@ page_zip_reorganize( temp_page + (PAGE_HEADER + PAGE_MAX_TRX_ID), 8); /* PAGE_MAX_TRX_ID must be set on secondary index leaf pages. */ ut_ad(dict_index_is_clust(index) || !page_is_leaf(temp_page) - || dict_table_is_temporary(index->table) || page_get_max_trx_id(page) != 0); /* PAGE_MAX_TRX_ID must be zero on non-leaf pages other than clustered index root pages. */ @@ -4764,6 +4764,7 @@ page_zip_copy_recs( ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr_memo_contains_page(mtr, src, MTR_MEMO_PAGE_X_FIX)); ut_ad(!dict_index_is_ibuf(index)); + ut_ad(!dict_table_is_temporary(index->table)); #ifdef UNIV_ZIP_DEBUG /* The B-tree operations that call this function may set FIL_PAGE_PREV or PAGE_LEVEL, causing a temporary min_rec_flag @@ -4807,8 +4808,7 @@ page_zip_copy_recs( } else { /* The PAGE_MAX_TRX_ID must be nonzero on leaf pages of secondary indexes, and 0 on others. */ - ut_ad(dict_table_is_temporary(index->table) - || !page_is_leaf(src) == !page_get_max_trx_id(src)); + ut_ad(!page_is_leaf(src) == !page_get_max_trx_id(src)); } /* Copy all fields of src_zip to page_zip, except the pointer diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 88a4ce8b7d7..554455509a7 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -3604,7 +3604,7 @@ row_import_for_mysql( we will not be writing any redo log for it before we have invoked fil_space_set_imported() to declare it a persistent tablespace. */ - ulint fsp_flags = dict_tf_to_fsp_flags(table->flags, false); + ulint fsp_flags = dict_tf_to_fsp_flags(table->flags); err = fil_ibd_open( true, true, FIL_TYPE_IMPORT, table->space, diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 0bc4fe4def9..187dd06acf1 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3546,36 +3546,25 @@ This deletes the fil_space_t if found and the file on disk. @param[in] space_id Tablespace ID @param[in] tablename Table name, same as the tablespace name @param[in] filepath File path of tablespace to delete -@param[in] is_temp Is this a temporary table/tablespace -@param[in] trx Transaction handle @return error code or DB_SUCCESS */ UNIV_INLINE dberr_t row_drop_single_table_tablespace( ulint space_id, const char* tablename, - const char* filepath, - bool is_temp, - trx_t* trx) + const char* filepath) { dberr_t err = DB_SUCCESS; - /* This might be a temporary single-table tablespace if the table - is compressed and temporary. If so, don't spam the log when we - delete one of these or if we can't find the tablespace. */ - bool print_msg = !is_temp; - /* If the tablespace is not in the cache, just delete the file. */ if (!fil_space_for_table_exists_in_mem( - space_id, tablename, print_msg, false, NULL, 0, NULL)) { + space_id, tablename, true, false, NULL, 0, NULL)) { /* Force a delete of any discarded or temporary files. */ fil_delete_file(filepath); - if (print_msg) { - ib::info() << "Removed datafile " << filepath - << " for table " << tablename; - } + ib::info() << "Removed datafile " << filepath + << " for table " << tablename; } else if (fil_delete_tablespace(space_id, BUF_REMOVE_FLUSH_NO_WRITE) != DB_SUCCESS) { @@ -4042,12 +4031,12 @@ row_drop_table_for_mysql( /* remove the index object associated. */ dict_drop_index_tree_in_mem(index, *page_no++); } - err = DB_SUCCESS; + err = row_drop_table_from_cache(tablename, table, trx); + goto funct_exit; } switch (err) { ulint space_id; - bool is_temp; bool ibd_file_missing; bool is_discarded; @@ -4055,18 +4044,7 @@ row_drop_table_for_mysql( space_id = table->space; ibd_file_missing = table->ibd_file_missing; is_discarded = dict_table_is_discarded(table); - is_temp = dict_table_is_temporary(table); - - /* If there is a temp path then the temp flag is set. - However, during recovery, we might have a temp flag but - not know the temp path */ - ut_a(table->dir_path_of_temp_table == NULL || is_temp); - - /* We do not allow temporary tables with a remote path. */ - ut_a(!(is_temp && DICT_TF_HAS_DATA_DIR(table->flags))); - - /* Make sure the data_dir_path is set if needed. */ - dict_get_and_save_data_dir_path(table, true); + ut_ad(!dict_table_is_temporary(table)); err = row_drop_ancillary_fts_tables(table, trx); if (err != DB_SUCCESS) { @@ -4076,14 +4054,11 @@ row_drop_table_for_mysql( /* Determine the tablespace filename before we drop dict_table_t. Free this memory before returning. */ if (DICT_TF_HAS_DATA_DIR(table->flags)) { + dict_get_and_save_data_dir_path(table, true); ut_a(table->data_dir_path); filepath = fil_make_filepath( table->data_dir_path, table->name.m_name, IBD, true); - } else if (table->dir_path_of_temp_table) { - filepath = fil_make_filepath( - table->dir_path_of_temp_table, - NULL, IBD, false); } else { filepath = fil_make_filepath( NULL, table->name.m_name, IBD, false); @@ -4104,8 +4079,7 @@ row_drop_table_for_mysql( /* We can now drop the single-table tablespace. */ err = row_drop_single_table_tablespace( - space_id, tablename, filepath, - is_temp, trx); + space_id, tablename, filepath); break; case DB_OUT_OF_FILE_SPACE: @@ -4187,99 +4161,6 @@ funct_exit: DBUG_RETURN(err); } -/*********************************************************************//** -Drop all temporary tables during crash recovery. */ -void -row_mysql_drop_temp_tables(void) -/*============================*/ -{ - trx_t* trx; - btr_pcur_t pcur; - mtr_t mtr; - mem_heap_t* heap; - - trx = trx_allocate_for_background(); - trx->op_info = "dropping temporary tables"; - row_mysql_lock_data_dictionary(trx); - - heap = mem_heap_create(200); - - mtr_start(&mtr); - - btr_pcur_open_at_index_side( - true, - dict_table_get_first_index(dict_sys->sys_tables), - BTR_SEARCH_LEAF, &pcur, true, 0, &mtr); - - for (;;) { - const rec_t* rec; - const byte* field; - ulint len; - const char* table_name; - dict_table_t* table; - - btr_pcur_move_to_next_user_rec(&pcur, &mtr); - - if (!btr_pcur_is_on_user_rec(&pcur)) { - break; - } - - /* The high order bit of N_COLS is set unless - ROW_FORMAT=REDUNDANT. */ - rec = btr_pcur_get_rec(&pcur); - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_TABLES__NAME, &len); - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_TABLES__N_COLS, &len); - if (len != 4 - || !(mach_read_from_4(field) & DICT_N_COLS_COMPACT)) { - continue; - } - - /* Older versions of InnoDB, which only supported tables - in ROW_FORMAT=REDUNDANT could write garbage to - SYS_TABLES.MIX_LEN, where we now store the is_temp flag. - Above, we assumed is_temp=0 if ROW_FORMAT=REDUNDANT. */ - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_TABLES__MIX_LEN, &len); - if (len != 4 - || !(mach_read_from_4(field) & DICT_TF2_TEMPORARY)) { - continue; - } - - /* This is a temporary table. */ - field = rec_get_nth_field_old( - rec, DICT_FLD__SYS_TABLES__NAME, &len); - if (len == UNIV_SQL_NULL || len == 0) { - /* Corrupted SYS_TABLES.NAME */ - continue; - } - - table_name = mem_heap_strdupl(heap, (const char*) field, len); - - btr_pcur_store_position(&pcur, &mtr); - btr_pcur_commit_specify_mtr(&pcur, &mtr); - - table = dict_load_table(table_name, true, - DICT_ERR_IGNORE_NONE); - - if (table) { - row_drop_table_for_mysql(table_name, trx, FALSE, FALSE); - trx_commit_for_mysql(trx); - } - - mtr_start(&mtr); - btr_pcur_restore_position(BTR_SEARCH_LEAF, - &pcur, &mtr); - } - - btr_pcur_close(&pcur); - mtr_commit(&mtr); - mem_heap_free(heap); - row_mysql_unlock_data_dictionary(trx); - trx_free_for_background(trx); -} - /*******************************************************************//** Drop all foreign keys in a database, see Bug#18942. Called at the end of row_drop_database_for_mysql(). diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index b372da4b939..094c0b45e6d 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -1993,9 +1993,9 @@ row_truncate_table_for_mysql( return(row_truncate_complete( table, trx, fsp_flags, logger, err)); } - } else { /* For temporary tables we don't have entries in SYSTEM TABLES*/ + ut_ad(fsp_is_system_temporary(table->space)); for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); index != NULL; index = UT_LIST_GET_NEXT(indexes, index)) { @@ -2018,10 +2018,7 @@ row_truncate_table_for_mysql( } } - if (is_file_per_table - && !dict_table_is_temporary(table) - && fsp_flags != ULINT_UNDEFINED) { - + if (is_file_per_table && fsp_flags != ULINT_UNDEFINED) { fil_reinit_space_header( table->space, table->indexes.count + FIL_IBD_FILE_INITIAL_SIZE + 1); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index ddc766accd4..d0b7ddc0449 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -692,7 +692,7 @@ srv_undo_tablespace_open( /* Set the compressed page size to 0 (non-compressed) */ flags = fsp_flags_init( - univ_page_size, false, false, false, false, 0, 0); + univ_page_size, false, false, false, 0, 0); space = fil_space_create( undo_name, space_id, flags, FIL_TYPE_TABLESPACE, NULL, true); From 085b292a47ee8a6fb141c575e7d8f5ed3b4206bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 17 Jan 2017 17:08:00 +0200 Subject: [PATCH 088/167] MDEV-11824 Allow ROW_FORMAT=DYNAMIC in the InnoDB system tablespace When MySQL 5.7.9 (and MariaDB Server 10.2) introduced innodb_default_row_format and made ROW_FORMAT=DYNAMIC the default, it became possible to create any ROW_FORMAT tables in the InnoDB system tablespace, except ROW_FORMAT=COMPRESSED. In MySQL 5.7, it is possible to create ROW_FORMAT=DYNAMIC tables when TABLESPACE=innodb_system is explicitly specified. Because MariaDB Server 10.2 does not support the MySQL 5.7 TABLESPACE=innodb_system attribute for tables, we should allow ROW_FORMAT=DYNAMIC when innodb_file_per_table=0. Also, remove the test innodb_zip.innodb-create-options, which was an outdated copy of innodb_zip.create_options. --- .../suite/innodb_zip/r/create_options.result | 24 +- .../innodb_zip/r/innodb-create-options.result | 870 ------------------ .../suite/innodb_zip/r/innodb-zip.result | 9 +- .../suite/innodb_zip/t/create_options.test | 18 +- .../innodb_zip/t/innodb-create-options.test | 561 ----------- mysql-test/suite/innodb_zip/t/innodb-zip.test | 17 +- storage/innobase/handler/ha_innodb.cc | 9 - 7 files changed, 37 insertions(+), 1471 deletions(-) delete mode 100644 mysql-test/suite/innodb_zip/r/innodb-create-options.result delete mode 100644 mysql-test/suite/innodb_zip/t/innodb-create-options.test diff --git a/mysql-test/suite/innodb_zip/r/create_options.result b/mysql-test/suite/innodb_zip/r/create_options.result index 2d80894c8cd..1c152229b3c 100644 --- a/mysql-test/suite/innodb_zip/r/create_options.result +++ b/mysql-test/suite/innodb_zip/r/create_options.result @@ -1,4 +1,7 @@ SET default_storage_engine=InnoDB; +SET GLOBAL innodb_file_format=`Barracuda`; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET GLOBAL innodb_file_per_table=ON; SET SESSION innodb_strict_mode = ON; # Test 1) StrictMode=ON, CREATE and ALTER with each ROW_FORMAT & KEY_BLOCK_SIZE=0 @@ -309,6 +312,10 @@ Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelop Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' ALTER TABLE t1 ROW_FORMAT=DYNAMIC; ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' SET GLOBAL innodb_file_format=Barracuda; Warnings: Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html @@ -340,7 +347,7 @@ Level Code Message SET GLOBAL innodb_file_format=Barracuda; Warnings: Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -# Test 8) StrictMode=ON, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and +# Test 8) StrictMode=ON, Make sure ROW_FORMAT=COMPRESSED # and a valid non-zero KEY_BLOCK_SIZE are rejected with # innodb_file_per_table=OFF and that they can be set to default # values during strict mode. @@ -361,7 +368,12 @@ Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") +SHOW WARNINGS; +Level Code Message +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +t1 Dynamic row_format=DYNAMIC +DROP TABLE t1; CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT; SHOW WARNINGS; Level Code Message @@ -392,7 +404,11 @@ Level Code Message Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +t1 Dynamic row_format=DYNAMIC +SHOW WARNINGS; +Level Code Message ALTER TABLE t1 ROW_FORMAT=COMPACT; SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; TABLE_NAME ROW_FORMAT CREATE_OPTIONS @@ -837,3 +853,5 @@ TABLE_NAME ROW_FORMAT CREATE_OPTIONS t1 Dynamic row_format=DYNAMIC # Cleanup DROP TABLE t1; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb_zip/r/innodb-create-options.result b/mysql-test/suite/innodb_zip/r/innodb-create-options.result deleted file mode 100644 index 1b92eb71fba..00000000000 --- a/mysql-test/suite/innodb_zip/r/innodb-create-options.result +++ /dev/null @@ -1,870 +0,0 @@ -SET default_storage_engine=InnoDB; -SET GLOBAL innodb_file_format=`Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=ON; -SET SESSION innodb_strict_mode = ON; -# Test 1) StrictMode=ON, CREATE and ALTER with each ROW_FORMAT & KEY_BLOCK_SIZE=0 -# KEY_BLOCK_SIZE=0 means 'no KEY_BLOCK_SIZE is specified' -DROP TABLE IF EXISTS t1; -Warnings: -Note 1051 Unknown table 'test.t1' -# 'FIXED' is sent to InnoDB since it is used by MyISAM. -# But it is an invalid mode in InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=FIXED; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: invalid ROW_FORMAT specifier. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=0; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: invalid ROW_FORMAT specifier. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE' -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic -# Test 2) StrictMode=ON, CREATE with each ROW_FORMAT & a valid non-zero KEY_BLOCK_SIZE -# KEY_BLOCK_SIZE is incompatible with COMPACT, REDUNDANT, & DYNAMIC -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=1 -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=1 -# Test 3) StrictMode=ON, ALTER with each ROW_FORMAT & a valid non-zero KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: invalid ROW_FORMAT specifier. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_TYPE' -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=2; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=1 -ALTER TABLE t1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=1 -# Test 4) StrictMode=ON, CREATE with ROW_FORMAT=COMPACT, ALTER with a valid non-zero KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT -ALTER TABLE t1 KEY_BLOCK_SIZE=4; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED -ALTER TABLE t1 KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=1 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=1 -# Test 5) StrictMode=ON, CREATE with a valid KEY_BLOCK_SIZE -# ALTER with each ROW_FORMAT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=2; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2 -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) DEFAULT NULL, - `f1` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2 -ALTER TABLE t1 ROW_FORMAT=COMPACT; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -# Test 6) StrictMode=ON, CREATE with an invalid KEY_BLOCK_SIZE. -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=9; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16] -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -# Test 7) StrictMode=ON, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and -# and a valid non-zero KEY_BLOCK_SIZE are rejected with Antelope -# and that they can be set to default values during strict mode. -SET GLOBAL innodb_file_format=Antelope; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -DROP TABLE IF EXISTS t1; -Warnings: -Note 1051 Unknown table 'test.t1' -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=4; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT; -SHOW WARNINGS; -Level Code Message -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; -SET GLOBAL innodb_file_format=Antelope; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -ALTER TABLE t1 ADD COLUMN f1 INT; -Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4. -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) DEFAULT NULL, - `f1` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 -SHOW WARNINGS; -Level Code Message -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -Level Code Message -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -# Test 8) StrictMode=ON, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and -# and a valid non-zero KEY_BLOCK_SIZE are rejected with -# innodb_file_per_table=OFF and that they can be set to default -# values during strict mode. -SET GLOBAL innodb_file_per_table=OFF; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=1; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; -ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. -Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT; -SHOW WARNINGS; -Level Code Message -ALTER TABLE t1 KEY_BLOCK_SIZE=1; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'KEY_BLOCK_SIZE' -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. -Error 1478 Table storage engine 'InnoDB' does not support the create option 'ROW_FORMAT' -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT -ALTER TABLE t1 ROW_FORMAT=DEFAULT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic -SET GLOBAL innodb_file_per_table=ON; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; -SET GLOBAL innodb_file_per_table=OFF; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -Level Code Message -SET GLOBAL innodb_file_per_table=ON; -################################################## -SET SESSION innodb_strict_mode = OFF; -# Test 9) StrictMode=OFF, CREATE and ALTER with each ROW_FORMAT & KEY_BLOCK_SIZE=0 -# KEY_BLOCK_SIZE=0 means 'no KEY_BLOCK_SIZE is specified' -# 'FIXED' is sent to InnoDB since it is used by MyISAM. -# It is an invalid mode in InnoDB, use COMPACT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=FIXED; -Warnings: -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=FIXED -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=0; -Warnings: -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=FIXED -# Test 10) StrictMode=OFF, CREATE with each ROW_FORMAT & a valid KEY_BLOCK_SIZE -# KEY_BLOCK_SIZE is ignored with COMPACT, REDUNDANT, & DYNAMIC -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT key_block_size=1 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT key_block_size=2 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC key_block_size=4 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=1 -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=1 -# Test 11) StrictMode=OFF, ALTER with each ROW_FORMAT & a valid KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=FIXED key_block_size=1 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=2; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT key_block_size=2 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC key_block_size=4 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT key_block_size=2 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=1 -ALTER TABLE t1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=1 -# Test 12) StrictMode=OFF, CREATE with ROW_FORMAT=COMPACT, ALTER with a valid KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT key_block_size=2 -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT key_block_size=2 -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=2 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC key_block_size=2 -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -ALTER TABLE t1 KEY_BLOCK_SIZE=4; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=4 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed key_block_size=2 -# Test 13) StrictMode=OFF, CREATE with a valid KEY_BLOCK_SIZE -# ALTER with each ROW_FORMAT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1 -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `i` int(11) DEFAULT NULL, - `f1` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1 -ALTER TABLE t1 ROW_FORMAT=COMPACT; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT key_block_size=1 -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Redundant row_format=REDUNDANT key_block_size=1 -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC key_block_size=1 -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=1 -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compact row_format=COMPACT -# Test 14) StrictMode=OFF, CREATE with an invalid KEY_BLOCK_SIZE, -# it defaults to half of the page size. -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=15; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=15. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=15. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic key_block_size=15 -# Test 15) StrictMode=OFF, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and a -valid KEY_BLOCK_SIZE are remembered but not used when ROW_FORMAT -is reverted to Antelope and then used again when ROW_FORMAT=Barracuda. -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=1 -SET GLOBAL innodb_file_format=Antelope; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -ALTER TABLE t1 ADD COLUMN f1 INT; -Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1. -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SHOW WARNINGS; -Level Code Message -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1. -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=COMPRESSED key_block_size=1 -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=1 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -SET GLOBAL innodb_file_format=Antelope; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -# Test 16) StrictMode=OFF, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and a -valid KEY_BLOCK_SIZE are remembered but not used when innodb_file_per_table=OFF -and then used again when innodb_file_per_table=ON. -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -SET GLOBAL innodb_file_per_table=OFF; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -SET GLOBAL innodb_file_per_table=ON; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Compressed row_format=COMPRESSED key_block_size=2 -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -SET GLOBAL innodb_file_per_table=OFF; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -SET GLOBAL innodb_file_per_table=ON; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -Level Code Message -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -TABLE_NAME ROW_FORMAT CREATE_OPTIONS -t1 Dynamic row_format=DYNAMIC -# Cleanup -DROP TABLE IF EXISTS t1; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb_zip/r/innodb-zip.result b/mysql-test/suite/innodb_zip/r/innodb-zip.result index 47215a1e077..c715f77b9ba 100644 --- a/mysql-test/suite/innodb_zip/r/innodb-zip.result +++ b/mysql-test/suite/innodb_zip/r/innodb-zip.result @@ -1,4 +1,3 @@ -DROP DATABASE IF EXISTS mysqltest_innodb_zip; CREATE DATABASE mysqltest_innodb_zip; USE mysqltest_innodb_zip; SELECT table_name, row_format, data_length, index_length @@ -316,19 +315,16 @@ Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. Error 1005 Can't create table `mysqltest_innodb_zip`.`t6` (errno: 140 "Wrong create options") Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB create table t7 (id int primary key) engine = innodb row_format = dynamic; -ERROR HY000: Can't create table `mysqltest_innodb_zip`.`t7` (errno: 140 "Wrong create options") show warnings; Level Code Message -Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. -Error 1005 Can't create table `mysqltest_innodb_zip`.`t7` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; SELECT table_schema, table_name, row_format, data_length, index_length FROM information_schema.tables WHERE engine='innodb' AND table_schema != 'mysql'; table_schema table_name row_format data_length index_length +mysqltest_innodb_zip t7 Dynamic {valid} 0 mysqltest_innodb_zip t8 Compact {valid} 0 mysqltest_innodb_zip t9 Redundant {valid} 0 -drop table t8, t9; +drop table t7, t8, t9; set global innodb_file_per_table = on; set global innodb_file_format = `0`; Warnings: @@ -409,5 +405,4 @@ select @@innodb_file_format_max; @@innodb_file_format_max Barracuda drop table normal_table, zip_table; -USE test; DROP DATABASE mysqltest_innodb_zip; diff --git a/mysql-test/suite/innodb_zip/t/create_options.test b/mysql-test/suite/innodb_zip/t/create_options.test index 1a3dbdff90a..86ef141cae8 100644 --- a/mysql-test/suite/innodb_zip/t/create_options.test +++ b/mysql-test/suite/innodb_zip/t/create_options.test @@ -63,10 +63,11 @@ SET default_storage_engine=InnoDB; --disable_query_log # These values can change during the test +LET $innodb_file_format_orig=`select @@innodb_file_format`; LET $innodb_file_per_table_orig=`select @@innodb_file_per_table`; -LET $innodb_strict_mode_orig=`select @@session.innodb_strict_mode`; --enable_query_log +SET GLOBAL innodb_file_format=`Barracuda`; SET GLOBAL innodb_file_per_table=ON; # The first half of these tests are with strict mode ON. @@ -242,8 +243,9 @@ SHOW WARNINGS; --error ER_ILLEGAL_HA_CREATE_OPTION ALTER TABLE t1 ROW_FORMAT=COMPRESSED; SHOW WARNINGS; ---error 1478 +--error ER_ILLEGAL_HA_CREATE_OPTION ALTER TABLE t1 ROW_FORMAT=DYNAMIC; +SHOW WARNINGS; SET GLOBAL innodb_file_format=Barracuda; DROP TABLE t1; CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; @@ -257,7 +259,7 @@ ALTER TABLE t1 ADD COLUMN f2 INT; SHOW WARNINGS; SET GLOBAL innodb_file_format=Barracuda; ---echo # Test 8) StrictMode=ON, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and +--echo # Test 8) StrictMode=ON, Make sure ROW_FORMAT=COMPRESSED --echo # and a valid non-zero KEY_BLOCK_SIZE are rejected with --echo # innodb_file_per_table=OFF and that they can be set to default --echo # values during strict mode. @@ -269,8 +271,10 @@ SHOW WARNINGS; --error ER_ILLEGAL_HA,1005 CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED; SHOW WARNINGS; ---error 1005 CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; +SHOW WARNINGS; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; +DROP TABLE t1; CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT; SHOW WARNINGS; SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; @@ -287,8 +291,9 @@ SHOW WARNINGS; --error ER_ILLEGAL_HA_CREATE_OPTION ALTER TABLE t1 ROW_FORMAT=COMPRESSED; SHOW WARNINGS; ---error 1478 ALTER TABLE t1 ROW_FORMAT=DYNAMIC; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; +SHOW WARNINGS; ALTER TABLE t1 ROW_FORMAT=COMPACT; SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; ALTER TABLE t1 ROW_FORMAT=REDUNDANT; @@ -522,7 +527,6 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE DROP TABLE t1; --disable_query_log +EVAL SET GLOBAL innodb_file_format=$innodb_file_format_orig; EVAL SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig; -EVAL SET SESSION innodb_strict_mode=$innodb_strict_mode_orig; --enable_query_log - diff --git a/mysql-test/suite/innodb_zip/t/innodb-create-options.test b/mysql-test/suite/innodb_zip/t/innodb-create-options.test deleted file mode 100644 index aeb22514bf6..00000000000 --- a/mysql-test/suite/innodb_zip/t/innodb-create-options.test +++ /dev/null @@ -1,561 +0,0 @@ ---source include/have_innodb.inc -# Tests for various combinations of ROW_FORMAT and KEY_BLOCK_SIZE -# Related bugs; -# Bug#54679: ALTER TABLE causes compressed row_format to revert to compact -# Bug#56628: ALTER TABLE .. KEY_BLOCK_SIZE=0 produces untrue warning or unnecessary error -# Bug#56632: ALTER TABLE implicitly changes ROW_FORMAT to COMPRESSED -# Rules for interpreting CREATE_OPTIONS -# 1) Create options on an ALTER are added to the options on the -# previous CREATE or ALTER statements. -# 2) KEY_BLOCK_SIZE=0 is considered a unspecified value. -# If the current ROW_FORMAT has explicitly been set to COMPRESSED, -# InnoDB will use a default value of 8. Otherwise KEY_BLOCK_SIZE -# will not be used. -# 3) ROW_FORMAT=DEFAULT allows InnoDB to choose its own default, COMPACT. -# 4) ROW_FORMAT=DEFAULT and KEY_BLOCK_SIZE=0 can be used at any time to -# unset or erase the values persisted in the MySQL dictionary and -# by SHOW CTREATE TABLE. -# 5) When incompatible values for ROW_FORMAT and KEY_BLOCK_SIZE are -# both explicitly given, the ROW_FORMAT is always used in non-strict -# mode. -# 6) InnoDB will automatically convert a table to COMPRESSED only if a -# valid non-zero KEY_BLOCK_SIZE has been given and ROW_FORMAT=DEFAULT -# or has not been used on a previous CREATE TABLE or ALTER TABLE. -# 7) InnoDB strict mode is designed to prevent incompatible create -# options from being used together. -# 8) The non-strict behavior is intended to permit you to import a -# mysqldump file into a database that does not support compressed -# tables, even if the source database contained compressed tables. -# All invalid values and/or incompatible combinations of ROW_FORMAT -# and KEY_BLOCK_SIZE are automatically corrected -# -# *** innodb_strict_mode=ON *** -# 1) Valid ROW_FORMATs are COMPRESSED, COMPACT, DEFAULT, DYNAMIC -# & REDUNDANT. All others are rejected. -# 2) Valid KEY_BLOCK_SIZEs are 0,1,2,4,8,16. All others are rejected. -# 3) KEY_BLOCK_SIZE=0 can be used to set it to 'unspecified'. -# 4) KEY_BLOCK_SIZE=1,2,4,8 & 16 are incompatible with COMPACT, DYNAMIC & -# REDUNDANT. -# 5) KEY_BLOCK_SIZE=1,2,4,8 & 16 as well as ROW_FORMAT=COMPRESSED and -# ROW_FORMAT=DYNAMIC are incompatible with innodb_file_format=Antelope -# and innodb_file_per_table=OFF -# 6) KEY_BLOCK_SIZE on an ALTER must occur with ROW_FORMAT=COMPRESSED -# or ROW_FORMAT=DEFAULT if the ROW_FORMAT was previously specified -# as COMPACT, DYNAMIC or REDUNDANT. -# 7) KEY_BLOCK_SIZE on an ALTER can occur without a ROW_FORMAT if the -# previous ROW_FORMAT was DEFAULT, COMPRESSED, or unspecified. -# -# *** innodb_strict_mode=OFF *** -# 1. Ignore a bad KEY_BLOCK_SIZE, defaulting it to 8. -# 2. Ignore a bad ROW_FORMAT, defaulting to COMPACT. -# 3. Ignore a valid KEY_BLOCK_SIZE when an incompatible but valid -# ROW_FORMAT is specified. -# 4. If innodb_file_format=Antelope or innodb_file_per_table=OFF -# it will ignore ROW_FORMAT=COMPRESSED or DYNAMIC and it will -# ignore all non-zero KEY_BLOCK_SIZEs. -# -# See InnoDB documentation page "SQL Compression Syntax Warnings and Errors" -# This test case does not try to create tables with KEY_BLOCK_SIZE > 4 -# since they are rejected for InnoDB page sizes of 8k and 16k. -# See innodb_16k and innodb_8k for those tests. - --- source include/have_innodb.inc -SET default_storage_engine=InnoDB; - ---disable_query_log -# These values can change during the test -LET $innodb_file_format_orig=`select @@innodb_file_format`; -LET $innodb_file_per_table_orig=`select @@innodb_file_per_table`; -LET $innodb_strict_mode_orig=`select @@session.innodb_strict_mode`; ---enable_query_log - -SET GLOBAL innodb_file_format=`Barracuda`; -SET GLOBAL innodb_file_per_table=ON; - -# The first half of these tests are with strict mode ON. -SET SESSION innodb_strict_mode = ON; - ---echo # Test 1) StrictMode=ON, CREATE and ALTER with each ROW_FORMAT & KEY_BLOCK_SIZE=0 ---echo # KEY_BLOCK_SIZE=0 means 'no KEY_BLOCK_SIZE is specified' -DROP TABLE IF EXISTS t1; ---echo # 'FIXED' is sent to InnoDB since it is used by MyISAM. ---echo # But it is an invalid mode in InnoDB ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=FIXED; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - - - ---echo # Test 2) StrictMode=ON, CREATE with each ROW_FORMAT & a valid non-zero KEY_BLOCK_SIZE ---echo # KEY_BLOCK_SIZE is incompatible with COMPACT, REDUNDANT, & DYNAMIC -DROP TABLE IF EXISTS t1; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - - ---echo # Test 3) StrictMode=ON, ALTER with each ROW_FORMAT & a valid non-zero KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=2; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - - ---echo # Test 4) StrictMode=ON, CREATE with ROW_FORMAT=COMPACT, ALTER with a valid non-zero KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 KEY_BLOCK_SIZE=4; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - ---echo # Test 5) StrictMode=ON, CREATE with a valid KEY_BLOCK_SIZE ---echo # ALTER with each ROW_FORMAT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=2; -SHOW CREATE TABLE t1; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW CREATE TABLE t1; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - ---echo # Test 6) StrictMode=ON, CREATE with an invalid KEY_BLOCK_SIZE. -DROP TABLE IF EXISTS t1; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=9; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; - ---echo # Test 7) StrictMode=ON, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and ---echo # and a valid non-zero KEY_BLOCK_SIZE are rejected with Antelope ---echo # and that they can be set to default values during strict mode. -SET GLOBAL innodb_file_format=Antelope; -DROP TABLE IF EXISTS t1; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=4; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -SET GLOBAL innodb_file_format=Barracuda; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; -SET GLOBAL innodb_file_format=Antelope; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW CREATE TABLE t1; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -SET GLOBAL innodb_file_format=Barracuda; - ---echo # Test 8) StrictMode=ON, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and ---echo # and a valid non-zero KEY_BLOCK_SIZE are rejected with ---echo # innodb_file_per_table=OFF and that they can be set to default ---echo # values during strict mode. -SET GLOBAL innodb_file_per_table=OFF; -DROP TABLE IF EXISTS t1; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=1; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; ---replace_regex / - .*[0-9]*[)]/)/ -SHOW WARNINGS; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 KEY_BLOCK_SIZE=1; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; ---error ER_ILLEGAL_HA_CREATE_OPTION -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DEFAULT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_per_table=ON; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4; -SET GLOBAL innodb_file_per_table=OFF; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -SET GLOBAL innodb_file_per_table=ON; - ---echo ################################################## -SET SESSION innodb_strict_mode = OFF; - ---echo # Test 9) StrictMode=OFF, CREATE and ALTER with each ROW_FORMAT & KEY_BLOCK_SIZE=0 ---echo # KEY_BLOCK_SIZE=0 means 'no KEY_BLOCK_SIZE is specified' ---echo # 'FIXED' is sent to InnoDB since it is used by MyISAM. ---echo # It is an invalid mode in InnoDB, use COMPACT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=FIXED; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - ---echo # Test 10) StrictMode=OFF, CREATE with each ROW_FORMAT & a valid KEY_BLOCK_SIZE ---echo # KEY_BLOCK_SIZE is ignored with COMPACT, REDUNDANT, & DYNAMIC -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - - ---echo # Test 11) StrictMode=OFF, ALTER with each ROW_FORMAT & a valid KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ); -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - - ---echo # Test 12) StrictMode=OFF, CREATE with ROW_FORMAT=COMPACT, ALTER with a valid KEY_BLOCK_SIZE -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 KEY_BLOCK_SIZE=4; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - ---echo # Test 13) StrictMode=OFF, CREATE with a valid KEY_BLOCK_SIZE ---echo # ALTER with each ROW_FORMAT -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SHOW CREATE TABLE t1; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SHOW CREATE TABLE t1; -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=REDUNDANT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPRESSED; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -ALTER TABLE t1 ROW_FORMAT=COMPACT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - ---echo # Test 14) StrictMode=OFF, CREATE with an invalid KEY_BLOCK_SIZE, ---echo # it defaults to half of the page size. -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE=15; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - ---echo # Test 15) StrictMode=OFF, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and a ---echo valid KEY_BLOCK_SIZE are remembered but not used when ROW_FORMAT ---echo is reverted to Antelope and then used again when ROW_FORMAT=Barracuda. -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_format=Antelope; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_format=Barracuda; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_format=Antelope; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_format=Barracuda; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - ---echo # Test 16) StrictMode=OFF, Make sure ROW_FORMAT= COMPRESSED & DYNAMIC and a ---echo valid KEY_BLOCK_SIZE are remembered but not used when innodb_file_per_table=OFF ---echo and then used again when innodb_file_per_table=ON. -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_per_table=OFF; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_per_table=ON; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 ( i INT ) ROW_FORMAT=DYNAMIC; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_per_table=OFF; -ALTER TABLE t1 ADD COLUMN f1 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; -SET GLOBAL innodb_file_per_table=ON; -ALTER TABLE t1 ADD COLUMN f2 INT; -SHOW WARNINGS; -SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1'; - - ---echo # Cleanup -DROP TABLE IF EXISTS t1; - ---disable_query_log -EVAL SET GLOBAL innodb_file_format=$innodb_file_format_orig; -EVAL SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig; -EVAL SET SESSION innodb_strict_mode=$innodb_strict_mode_orig; ---enable_query_log - diff --git a/mysql-test/suite/innodb_zip/t/innodb-zip.test b/mysql-test/suite/innodb_zip/t/innodb-zip.test index 1c7c7c8c419..8a201cb37ae 100644 --- a/mysql-test/suite/innodb_zip/t/innodb-zip.test +++ b/mysql-test/suite/innodb_zip/t/innodb-zip.test @@ -1,10 +1,5 @@ -- source include/have_innodb.inc - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest_innodb_zip; ---enable_warnings - CREATE DATABASE mysqltest_innodb_zip; USE mysqltest_innodb_zip; SELECT table_name, row_format, data_length, index_length @@ -18,14 +13,13 @@ let $innodb_file_format_orig=`select @@innodb_file_format`; let $innodb_file_format_max_orig=`select @@innodb_file_format_max`; SET @save_innodb_stats_on_metadata=@@global.innodb_stats_on_metadata; - --let $query_i_s = SELECT table_schema, table_name, row_format, data_length, index_length FROM information_schema.tables WHERE engine='innodb' AND table_schema != 'mysql' set session innodb_strict_mode=0; set global innodb_file_per_table=off; set global innodb_file_format=`0`; SET @@global.innodb_stats_on_metadata=ON; - + create table t0(a int primary key) engine=innodb row_format=compressed; create table t00(a int primary key) engine=innodb key_block_size=4 row_format=compressed; @@ -280,21 +274,18 @@ show warnings; create table t6 (id int primary key) engine = innodb row_format = compressed; --replace_regex / - .*[0-9]*[)]/)/ show warnings; ---replace_regex / - .*[0-9]*[)]/)/ ---error ER_CANT_CREATE_TABLE create table t7 (id int primary key) engine = innodb row_format = dynamic; ---replace_regex / - .*[0-9]*[)]/)/ show warnings; create table t8 (id int primary key) engine = innodb row_format = compact; create table t9 (id int primary key) engine = innodb row_format = redundant; --replace_result 16384 {valid} 8192 {valid} 4096 {valid} --eval $query_i_s -drop table t8, t9; +drop table t7, t8, t9; #test valid values with innodb_file_format unset set global innodb_file_per_table = on; -set global innodb_file_format = `0`; +set global innodb_file_format = `0`; --replace_regex / - .*[0-9]*[)]/)/ --error ER_CANT_CREATE_TABLE @@ -369,6 +360,4 @@ eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig; SET @@global.innodb_stats_on_metadata=@save_innodb_stats_on_metadata; --enable_query_log -USE test; DROP DATABASE mysqltest_innodb_zip; - diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index db1d90c06fe..93f5c936915 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12368,15 +12368,6 @@ create_table_info_t::create_options_are_invalid() } break; case ROW_TYPE_DYNAMIC: - if (!m_allow_file_per_table && !is_temp) { - push_warning_printf( - m_thd, Sql_condition::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ROW_FORMAT=%s requires" - " innodb_file_per_table.", - get_row_format_name(row_format)); - ret = "ROW_FORMAT"; - } if (!is_temp && srv_file_format < UNIV_FORMAT_B) { push_warning_printf( m_thd, Sql_condition::WARN_LEVEL_WARN, From 08413254b7ad952d9cd97c2faf1f6898ea73d387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 17 Jan 2017 18:49:34 +0200 Subject: [PATCH 089/167] Remove references to innodb_file_format. innodb_file_format=Barracuda is the default in MariaDB 10.2. Do not set it, because the option will be removed in MariaDB 10.3. Also, do not set innodb_file_per_table=1 because it is the default. Note that MDEV-11828 should fix the test innodb.innodb-64k already in 10.1. --- mysql-test/r/partition_innodb_plugin.result | 10 +- .../suite/encryption/r/innochecksum.result | 6 - .../encryption/r/innodb-bad-key-change.result | 4 - .../r/innodb-bad-key-change3.result | 4 - .../r/innodb-bad-key-change4.result | 10 - .../r/innodb-bad-key-change5.result | 10 - .../r/innodb-discard-import-change.result | 2 - .../encryption/r/innodb-discard-import.result | 2 - .../r/innodb-encryption-alter.result | 6 - .../r/innodb-encryption-disable.result | 6 - .../r/innodb-page_encryption-32k.result | 14 +- .../r/innodb-page_encryption.result | 14 - .../innodb-page_encryption_compression.result | 14 - ...nodb-page_encryption_log_encryption.result | 14 - .../innodb_encryption-page-compression.result | 6 - .../r/innodb_encryption_discard_import.result | 2 - .../r/innodb_encryption_filekeys.result | 6 - .../encryption/r/innodb_encryption_is.result | 6 - .../r/innodb_encryption_row_compressed.result | 10 - .../r/innodb_encryption_tables.result | 10 - .../r/innodb_onlinealter_encryption.result | 6 - .../innodb_page_encryption_key_change.result | 10 - .../suite/encryption/t/innochecksum.test | 6 - .../encryption/t/innodb-bad-key-change.test | 8 - .../encryption/t/innodb-bad-key-change3.test | 20 - .../encryption/t/innodb-bad-key-change4.test | 17 - .../encryption/t/innodb-bad-key-change5.test | 17 - .../t/innodb-discard-import-change.test | 13 - .../encryption/t/innodb-discard-import.test | 13 - .../encryption/t/innodb-encryption-alter.test | 8 - .../t/innodb-encryption-disable.test | 13 - .../t/innodb-page_encryption-32k.test | 18 +- .../encryption/t/innodb-page_encryption.test | 20 - .../t/innodb-page_encryption_compression.test | 13 - ...innodb-page_encryption_log_encryption.test | 20 - .../t/innodb_encryption-page-compression.test | 9 - .../t/innodb_encryption_discard_import.test | 18 - .../t/innodb_encryption_filekeys.test | 9 - .../encryption/t/innodb_encryption_is.test | 14 - .../t/innodb_encryption_row_compressed.test | 17 - .../t/innodb_encryption_tables.test | 17 - .../t/innodb_onlinealter_encryption.test | 14 - .../t/innodb_page_encryption_key_change.test | 17 - .../suite/encryption/t/innodb_scrub.opt | 2 - .../encryption/t/innodb_scrub_background.opt | 2 - .../include/innodb_simulate_comp_failures.inc | 12 - .../innodb/include/innodb_wl6501_crash.inc | 14 - .../include/innodb_wl6501_crash_temp.inc | 4 - mysql-test/suite/innodb/r/innodb-16k.result | 17 - .../suite/innodb/r/innodb-32k-crash.result | 210 +++++---- mysql-test/suite/innodb/r/innodb-32k.result | 442 +++++++++--------- .../suite/innodb/r/innodb-64k-crash.result | 418 +++++++++-------- mysql-test/suite/innodb/r/innodb-64k.result | 2 - .../suite/innodb/r/innodb-bug-14068765.result | 9 - .../suite/innodb/r/innodb-bug-14084530.result | 11 - mysql-test/suite/innodb/r/innodb-index.result | 15 - .../r/innodb-page_compression_bzip2.result | 6 - .../r/innodb-page_compression_lz4.result | 6 - .../r/innodb-page_compression_lzma.result | 6 - .../r/innodb-page_compression_lzo.result | 6 - .../r/innodb-page_compression_snappy.result | 7 - .../r/innodb-page_compression_tables.result | 10 - .../r/innodb-page_compression_zip.result | 6 - .../suite/innodb/r/innodb-wl5522-1.result | 67 +-- .../innodb/r/innodb-wl5522-debug-zip.result | 34 -- .../suite/innodb/r/innodb-wl5522-zip.result | 34 +- .../suite/innodb/r/innodb-wl5522.result | 25 - .../innodb/r/innodb_blob_truncate.result | 6 - .../innodb_prefix_index_restart_server.result | 9 - ...innodb_simulate_comp_failures_small.result | 1 + mysql-test/suite/innodb/t/innochecksum.opt | 2 - mysql-test/suite/innodb/t/innodb-16k.test | 16 - .../suite/innodb/t/innodb-32k-crash.test | 19 - mysql-test/suite/innodb/t/innodb-32k.test | 35 +- .../suite/innodb/t/innodb-64k-crash.test | 19 - mysql-test/suite/innodb/t/innodb-64k.test | 27 +- .../suite/innodb/t/innodb-bug-14068765.test | 14 - .../suite/innodb/t/innodb-bug-14084530.test | 13 - mysql-test/suite/innodb/t/innodb-index.test | 17 - .../t/innodb-page_compression_bzip2.test | 9 - .../innodb/t/innodb-page_compression_lz4.test | 9 - .../t/innodb-page_compression_lzma.test | 9 - .../innodb/t/innodb-page_compression_lzo.test | 10 - .../t/innodb-page_compression_snappy.test | 9 - .../t/innodb-page_compression_tables.test | 10 - .../innodb/t/innodb-page_compression_zip.test | 9 - .../suite/innodb/t/innodb-wl5522-1.test | 76 ++- .../innodb/t/innodb-wl5522-debug-zip.test | 24 - .../suite/innodb/t/innodb-wl5522-zip.test | 28 +- mysql-test/suite/innodb/t/innodb-wl5522.test | 22 - .../suite/innodb/t/innodb_blob_truncate.test | 13 - .../t/innodb_prefix_index_restart_server.test | 12 - .../include/innodb_wl6501_crash_stripped.inc | 144 ------ .../include/innodb_wl6501_error.inc | 8 - .../include/innodb_wl6501_scale.inc | 1 - .../suite/innodb_zip/r/innodb_bug36169.result | 4 - .../suite/innodb_zip/r/innodb_bug52745.result | 8 - .../suite/innodb_zip/r/innodb_bug53591.result | 8 - .../suite/innodb_zip/r/innodb_bug56680.result | 6 - .../r/innodb_index_large_prefix.result | 15 +- .../suite/innodb_zip/r/wl6501_crash_3.result | 39 -- .../suite/innodb_zip/r/wl6501_crash_4.result | 95 ++-- .../suite/innodb_zip/r/wl6501_crash_5.result | 75 +-- .../suite/innodb_zip/r/wl6501_scale_1.result | 33 +- .../suite/innodb_zip/t/innodb_bug36169.test | 8 - .../suite/innodb_zip/t/innodb_bug36172.test | 8 - .../suite/innodb_zip/t/innodb_bug52745.test | 8 - .../suite/innodb_zip/t/innodb_bug53591.test | 7 - .../suite/innodb_zip/t/innodb_bug56680.test | 6 - .../t/innodb_index_large_prefix.test | 17 +- .../suite/innodb_zip/t/wl6501_crash_3.test | 1 - .../suite/innodb_zip/t/wl6501_crash_4.test | 2 - .../suite/innodb_zip/t/wl6501_crash_5.test | 1 - mysql-test/t/partition_innodb_plugin.test | 6 +- .../storage_engine/tbl_opt_key_block_size.opt | 3 - .../storage_engine/tbl_opt_row_format.opt | 3 - 116 files changed, 683 insertions(+), 2079 deletions(-) delete mode 100644 mysql-test/suite/innodb/t/innochecksum.opt delete mode 100644 mysql-test/suite/innodb_zip/include/innodb_wl6501_crash_stripped.inc delete mode 100644 storage/innobase/mysql-test/storage_engine/tbl_opt_key_block_size.opt delete mode 100644 storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.opt diff --git a/mysql-test/r/partition_innodb_plugin.result b/mysql-test/r/partition_innodb_plugin.result index cd5dfade0ab..28f5a1303ea 100644 --- a/mysql-test/r/partition_innodb_plugin.result +++ b/mysql-test/r/partition_innodb_plugin.result @@ -37,14 +37,10 @@ call mtr.add_suppression("InnoDB: Error: table `test`.`t1` .* InnoDB internal"); # # Bug#55091: Server crashes on ADD PARTITION after a failed attempt # -SET @old_innodb_file_format = @@global.innodb_file_format; SET @old_innodb_file_per_table = @@global.innodb_file_per_table; SET @old_innodb_strict_mode = @@global.innodb_strict_mode; -SET @@global.innodb_file_format = Barracuda, -@@global.innodb_file_per_table = ON, +SET @@global.innodb_file_per_table = ON, @@global.innodb_strict_mode = ON; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html connect con1,localhost,root,,; CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, @@ -106,9 +102,6 @@ DROP TABLE t1; disconnect con2; connection default; SET @@global.innodb_strict_mode = @old_innodb_strict_mode; -SET @@global.innodb_file_format = @old_innodb_file_format; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET @@global.innodb_file_per_table = @old_innodb_file_per_table; SET NAMES utf8; CREATE TABLE `t``\""e` (a INT, PRIMARY KEY (a)) @@ -160,4 +153,3 @@ ROLLBACK; disconnect con1; connection default; DROP TABLE `t``\""e`; -SET NAMES DEFAULT; diff --git a/mysql-test/suite/encryption/r/innochecksum.result b/mysql-test/suite/encryption/r/innochecksum.result index 50eafbf9f5e..7cd7af7b93b 100644 --- a/mysql-test/suite/encryption/r/innochecksum.result +++ b/mysql-test/suite/encryption/r/innochecksum.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 1; # Create and populate a tables CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=4; @@ -23,5 +19,3 @@ CREATE TABLE t5 (a INT AUTO_INCREMENT PRIMARY KEY, b TEXT) ENGINE=InnoDB PAGE_CO # Write file to make mysql-test-run.pl start up the server again # Cleanup DROP TABLE t1, t2, t3, t4, t5; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change.result b/mysql-test/suite/encryption/r/innodb-bad-key-change.result index 7c6a9d2ba83..dc5be714f66 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change.result @@ -11,10 +11,6 @@ call mtr.add_suppression("InnoDB: Tablespace id .* is encrypted but encryption s call mtr.add_suppression("InnoDB: InnoDB: Page may be an index page where index id is .*"); # Start server with keys2.txt -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=2; INSERT INTO t1 VALUES ('foobar'); ALTER TABLE t1 ADD COLUMN c2 INT; diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change3.result b/mysql-test/suite/encryption/r/innodb-bad-key-change3.result index 6f4a46b4c44..79155bf43b9 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change3.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change3.result @@ -1,7 +1,5 @@ call mtr.add_suppression("InnoDB: Tablespace for table .* is set as discarded."); call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .* for how to resolve the issue."); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 1; CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1 ENCRYPTED=YES ENCRYPTION_KEY_ID=4; SHOW WARNINGS; @@ -23,8 +21,6 @@ backup: t1 UNLOCK TABLES; ALTER TABLE t1 DISCARD TABLESPACE; restore: t1 .ibd and .cfg files -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; ALTER TABLE t1 IMPORT TABLESPACE; ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB SHOW CREATE TABLE t1; diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result index 369a8c7989c..d6c2706e8bf 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change4.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change4.result @@ -4,16 +4,8 @@ call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop th call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem."); call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*"); call mtr.add_suppression("Couldn't load plugins from 'file_key_management*"); -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB ENCRYPTION_KEY_ID=4; INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check Warning Table test/t1 in tablespace # is encrypted but encryption service or used key_id is not available. Can't continue reading table. @@ -22,5 +14,3 @@ test.t1 check error Corrupt SHOW WARNINGS; Level Code Message DROP TABLE t1; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb-bad-key-change5.result b/mysql-test/suite/encryption/r/innodb-bad-key-change5.result index 9d8b1ddd23b..75a0587d35d 100644 --- a/mysql-test/suite/encryption/r/innodb-bad-key-change5.result +++ b/mysql-test/suite/encryption/r/innodb-bad-key-change5.result @@ -4,16 +4,8 @@ call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop th call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem."); call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*"); call mtr.add_suppression("Couldn't load plugins from 'file_key_management*"); -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB ENCRYPTION_KEY_ID=4; INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; OPTIMIZE TABLE t1; Table Op Msg_type Msg_text test.t1 optimize Warning Table test/t1 is encrypted but encryption service or used key_id is not available. Can't continue checking table. @@ -30,5 +22,3 @@ Level Code Message Warning 192 Table test/t1 is encrypted but encryption service or used key_id is not available. Can't continue reading table. Error 1296 Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB DROP TABLE t1; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb-discard-import-change.result b/mysql-test/suite/encryption/r/innodb-discard-import-change.result index 2505780b70c..b0b01b7cf7b 100644 --- a/mysql-test/suite/encryption/r/innodb-discard-import-change.result +++ b/mysql-test/suite/encryption/r/innodb-discard-import-change.result @@ -1,6 +1,4 @@ call mtr.add_suppression("InnoDB: Table .* tablespace is set as discarded"); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_compression_algorithm = 1; create table t1(c1 bigint not null primary key auto_increment, b char(200)) engine=innodb encrypted=yes encryption_key_id=4; create table t2(c1 bigint not null primary key auto_increment, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; diff --git a/mysql-test/suite/encryption/r/innodb-discard-import.result b/mysql-test/suite/encryption/r/innodb-discard-import.result index 06f4abab9f4..91314a77177 100644 --- a/mysql-test/suite/encryption/r/innodb-discard-import.result +++ b/mysql-test/suite/encryption/r/innodb-discard-import.result @@ -1,7 +1,5 @@ call mtr.add_suppression("InnoDB: Tablespace for table .* is set as discarded."); call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .* for how to resolve the issue."); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_compression_algorithm = 1; create table t1(c1 bigint not null, b char(200)) engine=innodb encrypted=yes encryption_key_id=4; show warnings; diff --git a/mysql-test/suite/encryption/r/innodb-encryption-alter.result b/mysql-test/suite/encryption/r/innodb-encryption-alter.result index 2003df0f4f4..06e4172bbae 100644 --- a/mysql-test/suite/encryption/r/innodb-encryption-alter.result +++ b/mysql-test/suite/encryption/r/innodb-encryption-alter.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_encrypt_tables = ON; SET GLOBAL innodb_encryption_threads = 4; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=4; @@ -53,5 +49,3 @@ Error 1005 Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB set innodb_default_encryption_key_id = 1; drop table t1,t2; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb-encryption-disable.result b/mysql-test/suite/encryption/r/innodb-encryption-disable.result index 62b233c1c93..63ad0cf13fb 100644 --- a/mysql-test/suite/encryption/r/innodb-encryption-disable.result +++ b/mysql-test/suite/encryption/r/innodb-encryption-disable.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; call mtr.add_suppression("InnoDB: Block in space_id .* in file test/.* encrypted"); call mtr.add_suppression("InnoDB: However key management plugin or used key_id 1 is not found or used encryption algorithm or method does not match."); call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file."); @@ -44,5 +40,3 @@ select * from t5; ERROR HY000: Got error 192 'Table encrypted but decryption failed. This could be because correct encryption management plugin is not loaded, used encryption key is not available or encryption method does not match.' from InnoDB drop table t1; drop table t5; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result b/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result index 6aa98a2fc68..fdebf23ce8f 100644 --- a/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result +++ b/mysql-test/suite/encryption/r/innodb-page_encryption-32k.result @@ -1,9 +1,14 @@ call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact encrypted=yes encryption_key_id=1; create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic encrypted=yes encryption_key_id=3; +ERROR HY000: Can't create table `test`.`innodb_dynamic` (errno: 140 "Wrong create options") +show warnings; +Level Code Message +Warning 140 InnoDB: ENCRYPTION_KEY_ID 3 not available +Error 1005 Can't create table `test`.`innodb_dynamic` (errno: 140 "Wrong create options") +Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB +create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic encrypted=yes encryption_key_id=33; create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant encrypted=yes encryption_key_id=4; show create table innodb_compact; Table Create Table @@ -16,7 +21,7 @@ Table Create Table innodb_dynamic CREATE TABLE `innodb_dynamic` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC `encrypted`=yes `encryption_key_id`=3 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC `encrypted`=yes `encryption_key_id`=33 show create table innodb_redundant; Table Create Table innodb_redundant CREATE TABLE `innodb_redundant` ( @@ -72,9 +77,6 @@ innodb_compact CREATE TABLE `innodb_compact` ( `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT alter table innodb_dynamic engine=innodb encrypted=DEFAULT encryption_key_id=DEFAULT; -Warnings: -Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. -Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT. show create table innodb_dynamic; Table Create Table innodb_dynamic CREATE TABLE `innodb_dynamic` ( diff --git a/mysql-test/suite/encryption/r/innodb-page_encryption.result b/mysql-test/suite/encryption/r/innodb-page_encryption.result index 051fd602db5..1069b8652da 100644 --- a/mysql-test/suite/encryption/r/innodb-page_encryption.result +++ b/mysql-test/suite/encryption/r/innodb-page_encryption.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; show warnings; Level Code Message @@ -122,10 +118,6 @@ variable_value >= 0 SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted'; variable_value >= 0 1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; update innodb_normal set c1 = c1 +1; update innodb_compact set c1 = c1 + 1; update innodb_compressed set c1 = c1 + 1; @@ -201,10 +193,6 @@ innodb_redundant CREATE TABLE `innodb_redundant` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; show create table innodb_compact; Table Create Table innodb_compact CREATE TABLE `innodb_compact` ( @@ -281,5 +269,3 @@ drop table innodb_compressed; drop table innodb_dynamic; drop table innodb_redundant; drop table innodb_defkey; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb-page_encryption_compression.result b/mysql-test/suite/encryption/r/innodb-page_encryption_compression.result index 6efefb23b87..a5bd7da8421 100644 --- a/mysql-test/suite/encryption/r/innodb-page_encryption_compression.result +++ b/mysql-test/suite/encryption/r/innodb-page_encryption_compression.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 1; create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb page_compressed=1; show warnings; @@ -76,10 +72,6 @@ SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_ variable_value >= 0 SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decompressed'; variable_value >= 0 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 1; update innodb_normal set c1 = c1 + 1; update innodb_compact set c1 = c1 + 1; @@ -132,10 +124,6 @@ innodb_dynamic CREATE TABLE `innodb_dynamic` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; show create table innodb_normal; Table Create Table innodb_normal CREATE TABLE `innodb_normal` ( @@ -188,5 +176,3 @@ drop procedure innodb_insert_proc; drop table innodb_normal; drop table innodb_compact; drop table innodb_dynamic; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb-page_encryption_log_encryption.result b/mysql-test/suite/encryption/r/innodb-page_encryption_log_encryption.result index 672202de774..ce74ac52537 100644 --- a/mysql-test/suite/encryption/r/innodb-page_encryption_log_encryption.result +++ b/mysql-test/suite/encryption/r/innodb-page_encryption_log_encryption.result @@ -1,10 +1,6 @@ call mtr.add_suppression("KeyID 0 not found or with error. Check the key and the log*"); call mtr.add_suppression("Disabling redo log encryp*"); call mtr.add_suppression("InnoDB: Redo log crypto: Can't initialize to key version*"); -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; show warnings; Level Code Message @@ -101,10 +97,6 @@ variable_value >= 0 SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted'; variable_value >= 0 1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; update innodb_normal set c1 = c1 +1; update innodb_compact set c1 = c1 + 1; update innodb_compressed set c1 = c1 + 1; @@ -172,10 +164,6 @@ innodb_redundant CREATE TABLE `innodb_redundant` ( `c1` bigint(20) NOT NULL, `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; show create table innodb_compact; Table Create Table innodb_compact CREATE TABLE `innodb_compact` ( @@ -253,5 +241,3 @@ pk 1 2 DROP TABLE t1; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb_encryption-page-compression.result b/mysql-test/suite/encryption/r/innodb_encryption-page-compression.result index 9523c7c3982..60b9ff57605 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption-page-compression.result +++ b/mysql-test/suite/encryption/r/innodb_encryption-page-compression.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_encryption_threads = 4; SET GLOBAL innodb_encrypt_tables = on; set global innodb_compression_algorithm = 1; @@ -264,5 +260,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result b/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result index ae1fbdebcb3..91581eb8837 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result +++ b/mysql-test/suite/encryption/r/innodb_encryption_discard_import.result @@ -1,7 +1,5 @@ call mtr.add_suppression("InnoDB: Tablespace for table .* is set as discarded."); call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .* for how to resolve the issue."); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB encrypted=yes; CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB; CREATE TABLE t3 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB row_format=compressed encrypted=yes; diff --git a/mysql-test/suite/encryption/r/innodb_encryption_filekeys.result b/mysql-test/suite/encryption/r/innodb_encryption_filekeys.result index 576b44fe897..54cdf842b20 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption_filekeys.result +++ b/mysql-test/suite/encryption/r/innodb_encryption_filekeys.result @@ -1,8 +1,4 @@ call mtr.add_suppression("trying to do an operation on a dropped tablespace .*"); -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_encrypt_tables = OFF; SET GLOBAL innodb_encryption_threads = 4; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB; @@ -65,7 +61,5 @@ COUNT(1) SELECT COUNT(1) FROM t5; COUNT(1) 400 -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html drop table t1,t2,t3,t4, t5; set GLOBAL innodb_default_encryption_key_id=1; diff --git a/mysql-test/suite/encryption/r/innodb_encryption_is.result b/mysql-test/suite/encryption/r/innodb_encryption_is.result index 591c5a84ccc..0ce4a11f1ea 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption_is.result +++ b/mysql-test/suite/encryption/r/innodb_encryption_is.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; CREATE TABLE t2 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=2; INSERT INTO t1 VALUES ('foobar'); @@ -14,5 +10,3 @@ NAME ENCRYPTION_SCHEME MIN_KEY_VERSION CURRENT_KEY_VERSION CURRENT_KEY_ID test/t1 1 1 1 1 test/t2 1 1 1 2 DROP TABLE t1, t2; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb_encryption_row_compressed.result b/mysql-test/suite/encryption/r/innodb_encryption_row_compressed.result index e49e38a8f3f..3d616ee71e3 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption_row_compressed.result +++ b/mysql-test/suite/encryption/r/innodb_encryption_row_compressed.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; create table innodb_compressed1(c1 bigint not null primary key, d int, a varchar(20), b char(200)) engine=innodb row_format=compressed encrypted=yes; create table innodb_compressed2(c1 bigint not null primary key, d int, a varchar(20), b char(200)) engine=innodb row_format=compressed key_block_size=1 encrypted=yes; create table innodb_compressed3(c1 bigint not null primary key, d int, a varchar(20), b char(200)) engine=innodb row_format=compressed key_block_size=2 encrypted=yes; @@ -27,10 +23,6 @@ NOT FOUND /private/ in innodb_compressed2.ibd NOT FOUND /private/ in innodb_compressed3.ibd # t4 yes on expecting NOT FOUND NOT FOUND /private/ in innodb_compressed4.ibd -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; select * from innodb_compressed1 where d = 20; c1 d a b 1 20 private evenmoreprivate @@ -155,5 +147,3 @@ drop table innodb_compressed1; drop table innodb_compressed2; drop table innodb_compressed3; drop table innodb_compressed4; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb_encryption_tables.result b/mysql-test/suite/encryption/r/innodb_encryption_tables.result index da62c0a2f0e..e7bcc207612 100644 --- a/mysql-test/suite/encryption/r/innodb_encryption_tables.result +++ b/mysql-test/suite/encryption/r/innodb_encryption_tables.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact; create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic; @@ -105,10 +101,6 @@ variable_value >= 0 SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_page_decompressed'; variable_value >= 0 1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; update innodb_normal set c1 = c1 + 1; update innodb_compact set c1 = c1 + 1; update innodb_dynamic set c1 = c1 + 1; @@ -163,5 +155,3 @@ drop table innodb_compact; drop table innodb_dynamic; drop table innodb_compressed; drop table innodb_redundant; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb_onlinealter_encryption.result b/mysql-test/suite/encryption/r/innodb_onlinealter_encryption.result index 798e0ca4357..d04525b0d5a 100644 --- a/mysql-test/suite/encryption/r/innodb_onlinealter_encryption.result +++ b/mysql-test/suite/encryption/r/innodb_onlinealter_encryption.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB encrypted=yes; CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB; CREATE TABLE t3 (id INT, a VARCHAR(255)) ENGINE=InnoDB encrypted=yes; @@ -176,5 +172,3 @@ NOT FOUND /mangled/ in t6.ibd NOT FOUND /mysql/ in t7.ibd DROP PROCEDURE innodb_insert_proc; DROP TABLE t1, t2, t3, t4, t5, t6, t7; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/r/innodb_page_encryption_key_change.result b/mysql-test/suite/encryption/r/innodb_page_encryption_key_change.result index 22038c0e933..d3406e67f18 100644 --- a/mysql-test/suite/encryption/r/innodb_page_encryption_key_change.result +++ b/mysql-test/suite/encryption/r/innodb_page_encryption_key_change.result @@ -1,8 +1,4 @@ # Restart mysqld --loose-file-key-management-filename=keys2.txt -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; show warnings; Level Code Message @@ -106,10 +102,6 @@ variable_value >= 0 SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted'; variable_value >= 0 1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; alter table innodb_compact engine=innodb encryption_key_id = 2; alter table innodb_compressed engine=innodb encryption_key_id = 3; alter table innodb_dynamic engine=innodb encryption_key_id = 4; @@ -155,5 +147,3 @@ drop table innodb_compact; drop table innodb_compressed; drop table innodb_dynamic; drop table innodb_redundant; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/encryption/t/innochecksum.test b/mysql-test/suite/encryption/t/innochecksum.test index 7b41b2c5413..39e86d49674 100644 --- a/mysql-test/suite/encryption/t/innochecksum.test +++ b/mysql-test/suite/encryption/t/innochecksum.test @@ -15,13 +15,9 @@ if (!$INNOCHECKSUM) { --disable_query_log let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let MYSQLD_DATADIR= `SELECT @@datadir`; --enable_query_log -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; # zlib set global innodb_compression_algorithm = 1; @@ -97,6 +93,4 @@ DROP TABLE t1, t2, t3, t4, t5; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change.test b/mysql-test/suite/encryption/t/innodb-bad-key-change.test index 3bcce90b01a..cc5e6b36ac3 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change.test @@ -29,14 +29,6 @@ call mtr.add_suppression("InnoDB: InnoDB: Page may be an index page where index -- let $restart_parameters=--file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt -- source include/restart_mysqld.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - CREATE TABLE t1 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=2; INSERT INTO t1 VALUES ('foobar'); ALTER TABLE t1 ADD COLUMN c2 INT; diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change3.test b/mysql-test/suite/encryption/t/innodb-bad-key-change3.test index b3ebe1c4aa5..dbd04748143 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change3.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change3.test @@ -12,11 +12,6 @@ call mtr.add_suppression("InnoDB: Tablespace for table .* is set as discarded."); call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .* for how to resolve the issue."); ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - --let $MYSQLD_TMPDIR = `SELECT @@tmpdir` --let $MYSQLD_DATADIR = `SELECT @@datadir` --let SEARCH_RANGE = 10000000 @@ -34,11 +29,7 @@ EOF --enable_reconnect --source include/wait_until_connected_again.inc ---disable_warnings -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 1; ---enable_warnings CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(255)) ENGINE=InnoDB PAGE_COMPRESSED=1 ENCRYPTED=YES ENCRYPTION_KEY_ID=4; SHOW WARNINGS; @@ -76,11 +67,6 @@ EOF --source include/wait_until_connected_again.inc --source include/restart_mysqld.inc ---disable_warnings -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; ---enable_warnings - --error ER_GET_ERRMSG ALTER TABLE t1 IMPORT TABLESPACE; SHOW CREATE TABLE t1; @@ -109,12 +95,6 @@ EOF DROP TABLE t1; # reset system ---disable_warnings ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log ---enable_warnings --remove_file $MYSQLTEST_VARDIR/keys1.txt --remove_file $MYSQLTEST_VARDIR/keys2.txt diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test b/mysql-test/suite/encryption/t/innodb-bad-key-change4.test index 82da3bbcf70..0b1db40b866 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change4.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change4.test @@ -32,14 +32,6 @@ EOF --let $MYSQLD_TMPDIR = `SELECT @@tmpdir` --let $MYSQLD_DATADIR = `SELECT @@datadir` ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB ENCRYPTION_KEY_ID=4; INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); @@ -56,9 +48,6 @@ EOF --enable_reconnect --source include/wait_until_connected_again.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - --replace_regex /tablespace [0-9]*/tablespace #/ CHECK TABLE t1; SHOW WARNINGS; @@ -82,9 +71,3 @@ EOF DROP TABLE t1; --remove_file $MYSQLTEST_VARDIR/keys1.txt - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-bad-key-change5.test b/mysql-test/suite/encryption/t/innodb-bad-key-change5.test index c6c0c963818..5f63eebe034 100644 --- a/mysql-test/suite/encryption/t/innodb-bad-key-change5.test +++ b/mysql-test/suite/encryption/t/innodb-bad-key-change5.test @@ -32,14 +32,6 @@ EOF --let $MYSQLD_TMPDIR = `SELECT @@tmpdir` --let $MYSQLD_DATADIR = `SELECT @@datadir` ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB ENCRYPTION_KEY_ID=4; INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); @@ -56,9 +48,6 @@ EOF --enable_reconnect --source include/wait_until_connected_again.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - OPTIMIZE TABLE t1; SHOW WARNINGS; @@ -80,9 +69,3 @@ EOF DROP TABLE t1; --remove_file $MYSQLTEST_VARDIR/keys1.txt - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-discard-import-change.test b/mysql-test/suite/encryption/t/innodb-discard-import-change.test index a278a8fba29..2cb6865ed95 100644 --- a/mysql-test/suite/encryption/t/innodb-discard-import-change.test +++ b/mysql-test/suite/encryption/t/innodb-discard-import-change.test @@ -6,17 +6,9 @@ call mtr.add_suppression("InnoDB: Table .* tablespace is set as discarded"); ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let $innodb_compression_algo = `SELECT @@innodb_compression_algorithm`; ---enable_query_log ---disable_warnings -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_compression_algorithm = 1; ---enable_warnings create table t1(c1 bigint not null primary key auto_increment, b char(200)) engine=innodb encrypted=yes encryption_key_id=4; create table t2(c1 bigint not null primary key auto_increment, b char(200)) engine=innodb encrypted=yes encryption_key_id=1; @@ -121,11 +113,6 @@ SELECT COUNT(*) FROM t5; DROP TABLE t1,t2,t3,t4,t5,t6; # reset system ---disable_warnings --disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algo; --enable_query_log ---enable_warnings - diff --git a/mysql-test/suite/encryption/t/innodb-discard-import.test b/mysql-test/suite/encryption/t/innodb-discard-import.test index 9feaacc41e5..e105cf82b67 100644 --- a/mysql-test/suite/encryption/t/innodb-discard-import.test +++ b/mysql-test/suite/encryption/t/innodb-discard-import.test @@ -13,17 +13,8 @@ call mtr.add_suppression("InnoDB: Tablespace for table .* is set as discarded."); call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .* for how to resolve the issue."); ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let $innodb_compression_algo = `SELECT @@innodb_compression_algorithm`; ---enable_query_log - ---disable_warnings -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_compression_algorithm = 1; ---enable_warnings --let $MYSQLD_TMPDIR = `SELECT @@tmpdir` --let $MYSQLD_DATADIR = `SELECT @@datadir` @@ -126,10 +117,6 @@ DROP PROCEDURE innodb_insert_proc; DROP TABLE t1,t2,t3,t4; # reset system ---disable_warnings --disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algo; --enable_query_log ---enable_warnings diff --git a/mysql-test/suite/encryption/t/innodb-encryption-alter.test b/mysql-test/suite/encryption/t/innodb-encryption-alter.test index 316ece1c16b..cb7d5a47975 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-alter.test +++ b/mysql-test/suite/encryption/t/innodb-encryption-alter.test @@ -5,15 +5,9 @@ # MDEV-8817: Failing assertion: new_state->key_version != ENCRYPTION_KEY_VERSION_INVALID # ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let $encrypt_tables = `SELECT @@innodb_encrypt_tables`; let $threads = `SELECT @@innodb_encryption_threads`; ---enable_query_log -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_encrypt_tables = ON; SET GLOBAL innodb_encryption_threads = 4; @@ -91,8 +85,6 @@ drop table t1,t2; # reset system --disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; EVAL SET GLOBAL innodb_encrypt_tables = $encrypt_tables; EVAL SET GLOBAL innodb_encryption_threads = $threads; --enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-encryption-disable.test b/mysql-test/suite/encryption/t/innodb-encryption-disable.test index e8e2ba02402..8a8b451f5b1 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-disable.test +++ b/mysql-test/suite/encryption/t/innodb-encryption-disable.test @@ -6,14 +6,6 @@ -- source include/not_crashrep.inc -- source filekeys_plugin_exists.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - # # MDEV-9559: Server without encryption configs crashes if selecting from an implicitly encrypted table # @@ -93,9 +85,4 @@ select * from t5; drop table t1; drop table t5; ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log - --remove_file $MYSQLTEST_VARDIR/encryption-disable-keys1.txt diff --git a/mysql-test/suite/encryption/t/innodb-page_encryption-32k.test b/mysql-test/suite/encryption/t/innodb-page_encryption-32k.test index 325f0a86521..29d821d1fc1 100644 --- a/mysql-test/suite/encryption/t/innodb-page_encryption-32k.test +++ b/mysql-test/suite/encryption/t/innodb-page_encryption-32k.test @@ -7,18 +7,12 @@ call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); ---disable_query_log -# These values can change during the test -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact encrypted=yes encryption_key_id=1; +--error ER_CANT_CREATE_TABLE create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic encrypted=yes encryption_key_id=3; +show warnings; +create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic encrypted=yes encryption_key_id=33; create table innodb_redundant(c1 bigint not null, b char(200)) engine=innodb row_format=redundant encrypted=yes encryption_key_id=4; show create table innodb_compact; @@ -88,9 +82,3 @@ drop table innodb_normal; drop table innodb_compact; drop table innodb_dynamic; drop table innodb_redundant; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-page_encryption.test b/mysql-test/suite/encryption/t/innodb-page_encryption.test index 463df756933..df2d1d52aaa 100644 --- a/mysql-test/suite/encryption/t/innodb-page_encryption.test +++ b/mysql-test/suite/encryption/t/innodb-page_encryption.test @@ -1,14 +1,6 @@ -- source include/have_innodb.inc -- source include/have_file_key_management_plugin.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; show warnings; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact encrypted=yes encryption_key_id=1; @@ -85,9 +77,6 @@ SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_ --source include/restart_mysqld.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - update innodb_normal set c1 = c1 +1; update innodb_compact set c1 = c1 + 1; update innodb_compressed set c1 = c1 + 1; @@ -124,9 +113,6 @@ show create table innodb_redundant; --source include/restart_mysqld.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - show create table innodb_compact; show create table innodb_compressed; show create table innodb_dynamic; @@ -161,9 +147,3 @@ drop table innodb_compressed; drop table innodb_dynamic; drop table innodb_redundant; drop table innodb_defkey; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-page_encryption_compression.test b/mysql-test/suite/encryption/t/innodb-page_encryption_compression.test index eb293e97693..2fe29e0cb5c 100644 --- a/mysql-test/suite/encryption/t/innodb-page_encryption_compression.test +++ b/mysql-test/suite/encryption/t/innodb-page_encryption_compression.test @@ -5,15 +5,9 @@ # Test heavy not tested on valgrind -- source include/not_valgrind.inc ---disable_query_log let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let $encryption = `SELECT @@innodb_encrypt_tables`; ---enable_query_log -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; # zlib set global innodb_compression_algorithm = 1; @@ -67,8 +61,6 @@ SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_ --source include/restart_mysqld.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; # zlib set global innodb_compression_algorithm = 1; @@ -97,9 +89,6 @@ show create table innodb_dynamic; --source include/restart_mysqld.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - show create table innodb_normal; show create table innodb_compact; show create table innodb_dynamic; @@ -128,7 +117,5 @@ drop table innodb_dynamic; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; EVAL SET GLOBAL innodb_encrypt_tables = $encryption; --enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb-page_encryption_log_encryption.test b/mysql-test/suite/encryption/t/innodb-page_encryption_log_encryption.test index b6fe0d10b65..f7eab67154d 100644 --- a/mysql-test/suite/encryption/t/innodb-page_encryption_log_encryption.test +++ b/mysql-test/suite/encryption/t/innodb-page_encryption_log_encryption.test @@ -2,18 +2,10 @@ -- source include/not_embedded.inc -- source include/have_file_key_management_plugin.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - call mtr.add_suppression("KeyID 0 not found or with error. Check the key and the log*"); call mtr.add_suppression("Disabling redo log encryp*"); call mtr.add_suppression("InnoDB: Redo log crypto: Can't initialize to key version*"); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; show warnings; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact encrypted=yes encryption_key_id=1; @@ -77,9 +69,6 @@ SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_ --source include/restart_mysqld.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - update innodb_normal set c1 = c1 +1; update innodb_compact set c1 = c1 + 1; update innodb_compressed set c1 = c1 + 1; @@ -112,9 +101,6 @@ show create table innodb_redundant; --source include/restart_mysqld.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - show create table innodb_compact; show create table innodb_compressed; show create table innodb_dynamic; @@ -160,9 +146,3 @@ INSERT INTO t1 VALUES (1),(2); SELECT * FROM t1; DROP TABLE t1; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb_encryption-page-compression.test b/mysql-test/suite/encryption/t/innodb_encryption-page-compression.test index c2c7bd96d3e..606662e44e6 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption-page-compression.test +++ b/mysql-test/suite/encryption/t/innodb_encryption-page-compression.test @@ -4,16 +4,10 @@ # embedded does not support restart -- source include/not_embedded.inc ---disable_query_log let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let $innodb_encrypt_tables_orig = `SELECT @@innodb_encrypt_tables`; let $innodb_encryption_threads_orig = `SELECT @@innodb_encryption_threads`; ---enable_query_log -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_encryption_threads = 4; SET GLOBAL innodb_encrypt_tables = on; @@ -161,9 +155,6 @@ drop table innodb_page_compressed9; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; EVAL SET GLOBAL innodb_encrypt_tables = $innodb_encrypt_tables_orig; EVAL SET GLOBAL innodb_encryption_threads = $innodb_encryption_threads_orig; --enable_query_log - diff --git a/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test b/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test index 32ba5d306f4..075cb1cf77e 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test +++ b/mysql-test/suite/encryption/t/innodb_encryption_discard_import.test @@ -15,16 +15,6 @@ let $MYSQLD_DATADIR = `SELECT @@datadir`; --let t2_IBD = $MYSQLD_DATADIR/test/t2.ibd --let t3_IBD = $MYSQLD_DATADIR/test/t3.ibd ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - ---disable_warnings -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; ---enable_warnings - CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB encrypted=yes; CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB; CREATE TABLE t3 (id INT NOT NULL PRIMARY KEY, a VARCHAR(255)) ENGINE=InnoDB row_format=compressed encrypted=yes; @@ -154,11 +144,3 @@ SELECT COUNT(1) FROM t3; DROP PROCEDURE innodb_insert_proc; DROP TABLE t1, t2, t3; - -# reset system ---disable_warnings ---disable_query_log -eval SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -eval SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log ---enable_warnings diff --git a/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test b/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test index 8f0986071f1..47d546ae698 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test +++ b/mysql-test/suite/encryption/t/innodb_encryption_filekeys.test @@ -5,15 +5,9 @@ call mtr.add_suppression("trying to do an operation on a dropped tablespace .*"); ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; let $encrypt_tables = `SELECT @@innodb_encrypt_tables`; let $threads = `SELECT @@innodb_encryption_threads`; ---enable_query_log -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_encrypt_tables = OFF; SET GLOBAL innodb_encryption_threads = 4; @@ -133,8 +127,6 @@ SELECT COUNT(1) FROM t5; # reset system --disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; EVAL SET GLOBAL innodb_encrypt_tables = $encrypt_tables; EVAL SET GLOBAL innodb_encryption_threads = $threads; --enable_query_log @@ -142,4 +134,3 @@ EVAL SET GLOBAL innodb_encryption_threads = $threads; drop table t1,t2,t3,t4, t5; set GLOBAL innodb_default_encryption_key_id=1; - diff --git a/mysql-test/suite/encryption/t/innodb_encryption_is.test b/mysql-test/suite/encryption/t/innodb_encryption_is.test index 333bb84c634..52574aa2b9d 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption_is.test +++ b/mysql-test/suite/encryption/t/innodb_encryption_is.test @@ -1,14 +1,6 @@ -- source include/have_innodb.inc -- source include/have_file_key_management_plugin.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - CREATE TABLE t1 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=1; CREATE TABLE t2 (c VARCHAR(8)) ENGINE=InnoDB ENCRYPTED=YES ENCRYPTION_KEY_ID=2; INSERT INTO t1 VALUES ('foobar'); @@ -23,9 +15,3 @@ FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE NAME LIKE '%t1' OR NAME LIKE '%t2'; DROP TABLE t1, t2; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb_encryption_row_compressed.test b/mysql-test/suite/encryption/t/innodb_encryption_row_compressed.test index 0a28c1690a2..d6319164c35 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption_row_compressed.test +++ b/mysql-test/suite/encryption/t/innodb_encryption_row_compressed.test @@ -2,14 +2,6 @@ -- source include/have_file_key_management_plugin.inc -- source include/not_embedded.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - create table innodb_compressed1(c1 bigint not null primary key, d int, a varchar(20), b char(200)) engine=innodb row_format=compressed encrypted=yes; create table innodb_compressed2(c1 bigint not null primary key, d int, a varchar(20), b char(200)) engine=innodb row_format=compressed key_block_size=1 encrypted=yes; create table innodb_compressed3(c1 bigint not null primary key, d int, a varchar(20), b char(200)) engine=innodb row_format=compressed key_block_size=2 encrypted=yes; @@ -52,9 +44,6 @@ insert into innodb_compressed4 select * from innodb_compressed1; -- let SEARCH_FILE=$t4_IBD -- source include/search_pattern_in_file.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - select * from innodb_compressed1 where d = 20; select * from innodb_compressed1 where d = 30; select * from innodb_compressed2 where d = 20; @@ -117,9 +106,3 @@ drop table innodb_compressed1; drop table innodb_compressed2; drop table innodb_compressed3; drop table innodb_compressed4; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb_encryption_tables.test b/mysql-test/suite/encryption/t/innodb_encryption_tables.test index f806b776800..bc762faf12e 100644 --- a/mysql-test/suite/encryption/t/innodb_encryption_tables.test +++ b/mysql-test/suite/encryption/t/innodb_encryption_tables.test @@ -2,14 +2,6 @@ -- source include/have_example_key_management_plugin.inc -- source include/not_embedded.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact; create table innodb_dynamic(c1 bigint not null, b char(200)) engine=innodb row_format=dynamic; @@ -73,9 +65,6 @@ SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_ --source include/restart_mysqld.inc -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - update innodb_normal set c1 = c1 + 1; update innodb_compact set c1 = c1 + 1; update innodb_dynamic set c1 = c1 + 1; @@ -106,9 +95,3 @@ drop table innodb_compact; drop table innodb_dynamic; drop table innodb_compressed; drop table innodb_redundant; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb_onlinealter_encryption.test b/mysql-test/suite/encryption/t/innodb_onlinealter_encryption.test index 40beb10bcdb..eb90c446a81 100644 --- a/mysql-test/suite/encryption/t/innodb_onlinealter_encryption.test +++ b/mysql-test/suite/encryption/t/innodb_onlinealter_encryption.test @@ -4,14 +4,6 @@ -- source include/not_embedded.inc -- source include/not_windows.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - --let $MYSQLD_DATADIR=`select @@datadir` --let SEARCH_RANGE = 10000000 --let t1_IBD = $MYSQLD_DATADIR/test/t1.ibd @@ -183,9 +175,3 @@ select count(1) from t7; DROP PROCEDURE innodb_insert_proc; DROP TABLE t1, t2, t3, t4, t5, t6, t7; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb_page_encryption_key_change.test b/mysql-test/suite/encryption/t/innodb_page_encryption_key_change.test index 7cbf005ed32..1babf577473 100644 --- a/mysql-test/suite/encryption/t/innodb_page_encryption_key_change.test +++ b/mysql-test/suite/encryption/t/innodb_page_encryption_key_change.test @@ -7,14 +7,6 @@ -- let $restart_parameters=--loose-file-key-management-filename=$MYSQL_TEST_DIR/std_data/keys2.txt -- source include/restart_mysqld.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; show warnings; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact encrypted=yes encryption_key_id=2; @@ -65,9 +57,6 @@ select * from innodb_redundant; SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_encrypted'; SELECT variable_value >= 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted'; -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - alter table innodb_compact engine=innodb encryption_key_id = 2; alter table innodb_compressed engine=innodb encryption_key_id = 3; alter table innodb_dynamic engine=innodb encryption_key_id = 4; @@ -88,9 +77,3 @@ drop table innodb_compact; drop table innodb_compressed; drop table innodb_dynamic; drop table innodb_redundant; - -# reset system ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/encryption/t/innodb_scrub.opt b/mysql-test/suite/encryption/t/innodb_scrub.opt index 3adb645c589..ef43b2a20a8 100644 --- a/mysql-test/suite/encryption/t/innodb_scrub.opt +++ b/mysql-test/suite/encryption/t/innodb_scrub.opt @@ -2,8 +2,6 @@ --innodb-background-scrub-data-uncompressed=OFF --innodb-encrypt-tables=OFF --innodb-encryption-threads=0 ---innodb-file-format=Barracuda ---innodb-file-per-table=1 --innodb-immediate-scrub-data-uncompressed=ON --loose-innodb-debug-force-scrubbing=ON --innodb-tablespaces-scrubbing diff --git a/mysql-test/suite/encryption/t/innodb_scrub_background.opt b/mysql-test/suite/encryption/t/innodb_scrub_background.opt index 1cc525b2402..04987f4a3ad 100644 --- a/mysql-test/suite/encryption/t/innodb_scrub_background.opt +++ b/mysql-test/suite/encryption/t/innodb_scrub_background.opt @@ -1,5 +1,3 @@ ---innodb-file-per-table=1 ---innodb-file-format=Barracuda --innodb-immediate-scrub-data-uncompressed=OFF --innodb-background-scrub-data-uncompressed=ON --innodb-background-scrub-data-compressed=ON diff --git a/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc index 75cab775528..28f2b7d1000 100644 --- a/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc +++ b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc @@ -5,17 +5,8 @@ --source include/not_embedded.inc --source include/have_innodb.inc ---disable_query_log -# record the file format in order to restore in the end. ---let $file_format_save = `SELECT @@innodb_file_format` ---let $file_format_max_save = `SELECT @@innodb_file_format_max` --let $simulate_comp_failures_save = `SELECT @@innodb_simulate_comp_failures` ---disable_warnings -DROP TABLE IF EXISTS t1; -SET GLOBAL INNODB_FILE_FORMAT='Barracuda'; ---enable_warnings - # since this test generates lot of errors in log, suppress checking errors call mtr.add_suppression(".*"); --enable_query_log @@ -156,9 +147,6 @@ COMMIT; # final cleanup DROP TABLE t1; -# restore innodb_file_format and innodb_file_format_max -eval SET GLOBAL innodb_file_format = \"$file_format_save\"; -eval SET GLOBAL innodb_file_format_max = \"$file_format_max_save\"; eval SET GLOBAL innodb_simulate_comp_failures = $simulate_comp_failures_save; --enable_query_log diff --git a/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc b/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc index 047be4dba34..93eca7ec060 100644 --- a/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc +++ b/mysql-test/suite/innodb/include/innodb_wl6501_crash.inc @@ -37,7 +37,6 @@ call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); # create test-bed # let $per_table = `select @@innodb_file_per_table`; -let $format = `select @@innodb_file_format`; eval set global innodb_file_per_table = on; let $WL6501_TMP_DIR = `select @@tmpdir`; @@ -51,7 +50,6 @@ let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; --echo "1. Hit crash point while writing redo log." use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -82,7 +80,6 @@ drop table t; --echo "2. Hit crash point on completion of redo log write." use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -115,7 +112,6 @@ drop table t; --echo "3. Hit crash point while dropping indexes." use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -144,7 +140,6 @@ drop table t; # use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -174,7 +169,6 @@ drop table t; # use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -209,7 +203,6 @@ drop table t; --echo " of index is commenced." use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -242,7 +235,6 @@ drop table t; --echo "5. Hit crash point while creating indexes." use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -271,7 +263,6 @@ drop table t; # use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -300,7 +291,6 @@ drop table t; # use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -334,7 +324,6 @@ drop table t; --echo " in-memory dict." use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -367,7 +356,6 @@ drop table t; --echo "7. Hit crash point before/after log checkpoint is done." use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -395,7 +383,6 @@ drop table t; # use test; eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; SET innodb_strict_mode=OFF; --disable_warnings eval create $wl6501_temp table t ( @@ -426,5 +413,4 @@ drop table t; # # remove test-bed # -eval set global innodb_file_format = $format; eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc b/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc index 76b7b5d59b5..edec93b875c 100644 --- a/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc +++ b/mysql-test/suite/innodb/include/innodb_wl6501_crash_temp.inc @@ -30,7 +30,6 @@ call mtr.add_suppression("does not exist in the InnoDB internal"); # create test-bed # let $per_table = `select @@innodb_file_per_table`; -let $format = `select @@innodb_file_format`; eval set global innodb_file_per_table = on; let $WL6501_TMP_DIR = `select @@tmpdir`; @@ -45,7 +44,6 @@ let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; --echo "1. Hit crash point on completing drop of all indexes before creation" --echo " of index is commenced." eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; set innodb_strict_mode=off; --disable_warnings eval create $wl6501_temp table t ( @@ -73,7 +71,6 @@ check table t; --echo "2. Hit crash point after data is updated to system-table and" --echo " in-memory dict." eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; set innodb_strict_mode=off; --disable_warnings eval create $wl6501_temp table t ( @@ -98,5 +95,4 @@ check table t; # # remove test-bed # -eval set global innodb_file_format = $format; eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb/r/innodb-16k.result b/mysql-test/suite/innodb/r/innodb-16k.result index 63637c6428f..206abe45887 100644 --- a/mysql-test/suite/innodb/r/innodb-16k.result +++ b/mysql-test/suite/innodb/r/innodb-16k.result @@ -1,8 +1,4 @@ call mtr.add_suppression("InnoDB: Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size (.*) for a record on index leaf page."); -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_large_prefix = OFF; Warnings: Warning 131 Using innodb_large_prefix is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html @@ -229,9 +225,6 @@ FROM information_schema.tables WHERE table_name = 't1'; table_name row_format create_options t1 Compressed row_format=COMPRESSED DROP TABLE t1; -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html CREATE TABLE t2(d varchar(17) PRIMARY KEY) ENGINE=innodb DEFAULT CHARSET=utf8; CREATE TABLE t3(a int PRIMARY KEY) ENGINE=innodb; INSERT INTO t3 VALUES (22),(44),(33),(55),(66); @@ -422,10 +415,6 @@ t1 CREATE TABLE `t1` ( KEY `t1t` (`t`(767)) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC DROP TABLE t1; -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; Test an assertion failure on purge. CREATE TABLE t1_purge ( A int, @@ -466,10 +455,6 @@ DELETE FROM t1_purge; DELETE FROM t2_purge; DELETE FROM t3_purge; DELETE FROM t4_purge; -SET GLOBAL innodb_file_per_table=on; -SET GLOBAL innodb_file_format='Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET @r=REPEAT('a',500); CREATE TABLE tlong(a int, v1 varchar(500), v2 varchar(500), v3 varchar(500), @@ -984,6 +969,4 @@ COL197 TEXT) row_format=compact,ENGINE=INNODB; ERROR 42000: Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline. Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -Warnings: Warning 131 Using innodb_large_prefix is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-32k-crash.result b/mysql-test/suite/innodb/r/innodb-32k-crash.result index c9b21bf414a..1fd5cd9b521 100644 --- a/mysql-test/suite/innodb/r/innodb-32k-crash.result +++ b/mysql-test/suite/innodb/r/innodb-32k-crash.result @@ -1,6 +1,4 @@ call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob, h blob,i blob,j blob,k blob,l blob,m blob,n blob, o blob,p blob,q blob,r blob,s blob,t blob,u blob, @@ -161,58 +159,58 @@ COMMIT; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` blob, - `b` blob, - `c` blob, - `d` blob, - `e` blob, - `f` blob, - `g` blob, - `h` blob, - `i` blob, - `j` blob, - `k` blob, - `l` blob, - `m` blob, - `n` blob, - `o` blob, - `p` blob, - `q` blob, - `r` blob, - `s` blob, - `t` blob, - `u` blob, - `v` blob, - `w` blob, - `x` blob, - `y` blob, - `z` blob, - `aa` blob, - `ba` blob, - `ca` blob, - `da` blob, - `ea` blob, - `fa` blob, - `ga` blob, - `ha` blob, - `ia` blob, - `ja` blob, - `ka` blob, - `la` blob, - `ma` blob, - `na` blob, - `oa` blob, - `pa` blob, - `qa` blob, - `ra` blob, - `sa` blob, - `ta` blob, - `ua` blob, - `va` blob, - `wa` blob, - `xa` blob, - `ya` blob, - `za` blob, + `a` blob DEFAULT NULL, + `b` blob DEFAULT NULL, + `c` blob DEFAULT NULL, + `d` blob DEFAULT NULL, + `e` blob DEFAULT NULL, + `f` blob DEFAULT NULL, + `g` blob DEFAULT NULL, + `h` blob DEFAULT NULL, + `i` blob DEFAULT NULL, + `j` blob DEFAULT NULL, + `k` blob DEFAULT NULL, + `l` blob DEFAULT NULL, + `m` blob DEFAULT NULL, + `n` blob DEFAULT NULL, + `o` blob DEFAULT NULL, + `p` blob DEFAULT NULL, + `q` blob DEFAULT NULL, + `r` blob DEFAULT NULL, + `s` blob DEFAULT NULL, + `t` blob DEFAULT NULL, + `u` blob DEFAULT NULL, + `v` blob DEFAULT NULL, + `w` blob DEFAULT NULL, + `x` blob DEFAULT NULL, + `y` blob DEFAULT NULL, + `z` blob DEFAULT NULL, + `aa` blob DEFAULT NULL, + `ba` blob DEFAULT NULL, + `ca` blob DEFAULT NULL, + `da` blob DEFAULT NULL, + `ea` blob DEFAULT NULL, + `fa` blob DEFAULT NULL, + `ga` blob DEFAULT NULL, + `ha` blob DEFAULT NULL, + `ia` blob DEFAULT NULL, + `ja` blob DEFAULT NULL, + `ka` blob DEFAULT NULL, + `la` blob DEFAULT NULL, + `ma` blob DEFAULT NULL, + `na` blob DEFAULT NULL, + `oa` blob DEFAULT NULL, + `pa` blob DEFAULT NULL, + `qa` blob DEFAULT NULL, + `ra` blob DEFAULT NULL, + `sa` blob DEFAULT NULL, + `ta` blob DEFAULT NULL, + `ua` blob DEFAULT NULL, + `va` blob DEFAULT NULL, + `wa` blob DEFAULT NULL, + `xa` blob DEFAULT NULL, + `ya` blob DEFAULT NULL, + `za` blob DEFAULT NULL, KEY `t1a` (`a`(767)), KEY `t1b` (`b`(767)), KEY `t1c` (`c`(767)), @@ -227,58 +225,58 @@ t1 CREATE TABLE `t1` ( show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `a` blob, - `b` blob, - `c` blob, - `d` blob, - `e` blob, - `f` blob, - `g` blob, - `h` blob, - `i` blob, - `j` blob, - `k` blob, - `l` blob, - `m` blob, - `n` blob, - `o` blob, - `p` blob, - `q` blob, - `r` blob, - `s` blob, - `t` blob, - `u` blob, - `v` blob, - `w` blob, - `x` blob, - `y` blob, - `z` blob, - `aa` blob, - `ba` blob, - `ca` blob, - `da` blob, - `ea` blob, - `fa` blob, - `ga` blob, - `ha` blob, - `ia` blob, - `ja` blob, - `ka` blob, - `la` blob, - `ma` blob, - `na` blob, - `oa` blob, - `pa` blob, - `qa` blob, - `ra` blob, - `sa` blob, - `ta` blob, - `ua` blob, - `va` blob, - `wa` blob, - `xa` blob, - `ya` blob, - `za` blob, + `a` blob DEFAULT NULL, + `b` blob DEFAULT NULL, + `c` blob DEFAULT NULL, + `d` blob DEFAULT NULL, + `e` blob DEFAULT NULL, + `f` blob DEFAULT NULL, + `g` blob DEFAULT NULL, + `h` blob DEFAULT NULL, + `i` blob DEFAULT NULL, + `j` blob DEFAULT NULL, + `k` blob DEFAULT NULL, + `l` blob DEFAULT NULL, + `m` blob DEFAULT NULL, + `n` blob DEFAULT NULL, + `o` blob DEFAULT NULL, + `p` blob DEFAULT NULL, + `q` blob DEFAULT NULL, + `r` blob DEFAULT NULL, + `s` blob DEFAULT NULL, + `t` blob DEFAULT NULL, + `u` blob DEFAULT NULL, + `v` blob DEFAULT NULL, + `w` blob DEFAULT NULL, + `x` blob DEFAULT NULL, + `y` blob DEFAULT NULL, + `z` blob DEFAULT NULL, + `aa` blob DEFAULT NULL, + `ba` blob DEFAULT NULL, + `ca` blob DEFAULT NULL, + `da` blob DEFAULT NULL, + `ea` blob DEFAULT NULL, + `fa` blob DEFAULT NULL, + `ga` blob DEFAULT NULL, + `ha` blob DEFAULT NULL, + `ia` blob DEFAULT NULL, + `ja` blob DEFAULT NULL, + `ka` blob DEFAULT NULL, + `la` blob DEFAULT NULL, + `ma` blob DEFAULT NULL, + `na` blob DEFAULT NULL, + `oa` blob DEFAULT NULL, + `pa` blob DEFAULT NULL, + `qa` blob DEFAULT NULL, + `ra` blob DEFAULT NULL, + `sa` blob DEFAULT NULL, + `ta` blob DEFAULT NULL, + `ua` blob DEFAULT NULL, + `va` blob DEFAULT NULL, + `wa` blob DEFAULT NULL, + `xa` blob DEFAULT NULL, + `ya` blob DEFAULT NULL, + `za` blob DEFAULT NULL, KEY `t1a` (`a`(767)), KEY `t1b` (`b`(767)), KEY `t1c` (`c`(767)), diff --git a/mysql-test/suite/innodb/r/innodb-32k.result b/mysql-test/suite/innodb/r/innodb-32k.result index 2253ba5588f..29374689a3b 100644 --- a/mysql-test/suite/innodb/r/innodb-32k.result +++ b/mysql-test/suite/innodb/r/innodb-32k.result @@ -1,9 +1,8 @@ -call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); -call mtr.add_suppression("InnoDB: Resizing redo log from *"); -call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files."); -call mtr.add_suppression("InnoDB: New log files created, LSN=*"); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; +call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value "); +call mtr.add_suppression("InnoDB: Resizing redo log from "); +call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files"); +call mtr.add_suppression("InnoDB: New log files created, LSN="); +call mtr.add_suppression("Innodb: Cannot add field.*row size is"); # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; @@ -234,7 +233,7 @@ v=@d,w=@d,x=@d,y=@d,z=@d, aa=@d,ba=@d,ca=@d,da=@d,ea=@d,fa=@d,ga=@d,ha=@d,ia=@d,ja=@d, ka=@d,la=@d,ma=@d,na=@d,oa=@d,pa=@d,qa=@d,ra=@d,sa=@d,ta=@d,ua=@d, va=@d,wa=@d,xa=@d,ya=@d,za=@d; -ERROR HY000: Undo log record is too big. +ERROR HY000: Undo log record is too big BEGIN; UPDATE t1 SET a=@d,b=@d,c=@d,d=@d,e=@d; UPDATE t1 SET f=@d,g=@d,h=@d,i=@d,j=@d; @@ -278,7 +277,6 @@ CREATE INDEX tn1f9 ON t1 (oa(767)); CREATE INDEX to1f11 ON t1 (pa(767)); UPDATE t1 SET t=@e; CREATE INDEX t1f6 ON t1 (l(767)); -ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 16318. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs drop table t1; Test an assertion failure on purge. CREATE TABLE t1_purge ( @@ -320,8 +318,6 @@ DELETE FROM t1_purge; DELETE FROM t2_purge; DELETE FROM t3_purge; DELETE FROM t4_purge; -SET GLOBAL innodb_file_per_table=on; -SET GLOBAL innodb_file_format='Barracuda'; SET @r=REPEAT('a',500); CREATE TABLE tlong(a int, v1 varchar(500), v2 varchar(500), v3 varchar(500), @@ -366,22 +362,22 @@ CREATE INDEX ndx_p ON tlong2 (p(500)); SHOW CREATE TABLE tlong2; Table Create Table tlong2 CREATE TABLE `tlong2` ( - `a` blob, - `b` blob, - `c` blob, - `d` blob, - `e` blob, - `f` blob, - `g` blob, - `h` blob, - `i` blob, - `j` blob, - `k` blob, - `l` blob, - `m` blob, - `n` blob, - `o` blob, - `p` blob, + `a` blob DEFAULT NULL, + `b` blob DEFAULT NULL, + `c` blob DEFAULT NULL, + `d` blob DEFAULT NULL, + `e` blob DEFAULT NULL, + `f` blob DEFAULT NULL, + `g` blob DEFAULT NULL, + `h` blob DEFAULT NULL, + `i` blob DEFAULT NULL, + `j` blob DEFAULT NULL, + `k` blob DEFAULT NULL, + `l` blob DEFAULT NULL, + `m` blob DEFAULT NULL, + `n` blob DEFAULT NULL, + `o` blob DEFAULT NULL, + `p` blob DEFAULT NULL, KEY `ndx_c` (`c`(500)), KEY `ndx_d` (`d`(500)), KEY `ndx_e` (`e`(500)), @@ -665,203 +661,203 @@ set @b = repeat('zyxwvutsrqponmlkjihgfedcba', 2000); show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `COL1` text, - `COL2` text, - `COL3` text, - `COL4` text, - `COL5` text, - `COL6` text, - `COL7` text, - `COL8` text, - `COL9` text, - `COL10` text, - `COL11` text, - `COL12` text, - `COL13` text, - `COL14` text, - `COL15` text, - `COL16` text, - `COL17` text, - `COL18` text, - `COL19` text, - `COL20` text, - `COL21` text, - `COL22` text, - `COL23` text, - `COL24` text, - `COL25` text, - `COL26` text, - `COL27` text, - `COL28` text, - `COL29` text, - `COL30` text, - `COL31` text, - `COL32` text, - `COL33` text, - `COL34` text, - `COL35` text, - `COL36` text, - `COL37` text, - `COL38` text, - `COL39` text, - `COL40` text, - `COL41` text, - `COL42` text, - `COL43` text, - `COL44` text, - `COL45` text, - `COL46` text, - `COL47` text, - `COL48` text, - `COL49` text, - `COL50` text, - `COL51` text, - `COL52` text, - `COL53` text, - `COL54` text, - `COL55` text, - `COL56` text, - `COL57` text, - `COL58` text, - `COL59` text, - `COL60` text, - `COL61` text, - `COL62` text, - `COL63` text, - `COL64` text, - `COL65` text, - `COL66` text, - `COL67` text, - `COL68` text, - `COL69` text, - `COL70` text, - `COL71` text, - `COL72` text, - `COL73` text, - `COL74` text, - `COL75` text, - `COL76` text, - `COL77` text, - `COL78` text, - `COL79` text, - `COL80` text, - `COL81` text, - `COL82` text, - `COL83` text, - `COL84` text, - `COL85` text, - `COL86` text, - `COL87` text, - `COL88` text, - `COL89` text, - `COL90` text, - `COL91` text, - `COL92` text, - `COL93` text, - `COL94` text, - `COL95` text, - `COL96` text, - `COL97` text, - `COL98` text, - `COL99` text, - `COL100` text, - `COL101` text, - `COL102` text, - `COL103` text, - `COL104` text, - `COL105` text, - `COL106` text, - `COL107` text, - `COL108` text, - `COL109` text, - `COL110` text, - `COL111` text, - `COL112` text, - `COL113` text, - `COL114` text, - `COL115` text, - `COL116` text, - `COL117` text, - `COL118` text, - `COL119` text, - `COL120` text, - `COL121` text, - `COL122` text, - `COL123` text, - `COL124` text, - `COL125` text, - `COL126` text, - `COL127` text, - `COL128` text, - `COL129` text, - `COL130` text, - `COL131` text, - `COL132` text, - `COL133` text, - `COL134` text, - `COL135` text, - `COL136` text, - `COL137` text, - `COL138` text, - `COL139` text, - `COL140` text, - `COL141` text, - `COL142` text, - `COL143` text, - `COL144` text, - `COL145` text, - `COL146` text, - `COL147` text, - `COL148` text, - `COL149` text, - `COL150` text, - `COL151` text, - `COL152` text, - `COL153` text, - `COL154` text, - `COL155` text, - `COL156` text, - `COL157` text, - `COL158` text, - `COL159` text, - `COL160` text, - `COL161` text, - `COL162` text, - `COL163` text, - `COL164` text, - `COL165` text, - `COL166` text, - `COL167` text, - `COL168` text, - `COL169` text, - `COL170` text, - `COL171` text, - `COL172` text, - `COL173` text, - `COL174` text, - `COL175` text, - `COL176` text, - `COL177` text, - `COL178` text, - `COL179` text, - `COL180` text, - `COL181` text, - `COL182` text, - `COL183` text, - `COL184` text, - `COL185` text, - `COL186` text, - `COL187` text, - `COL188` text, - `COL189` text, - `COL190` text, - `COL191` text, - `COL192` text, - `COL193` text, - `COL194` text, - `COL195` text, - `COL196` text, - `COL197` text + `COL1` text DEFAULT NULL, + `COL2` text DEFAULT NULL, + `COL3` text DEFAULT NULL, + `COL4` text DEFAULT NULL, + `COL5` text DEFAULT NULL, + `COL6` text DEFAULT NULL, + `COL7` text DEFAULT NULL, + `COL8` text DEFAULT NULL, + `COL9` text DEFAULT NULL, + `COL10` text DEFAULT NULL, + `COL11` text DEFAULT NULL, + `COL12` text DEFAULT NULL, + `COL13` text DEFAULT NULL, + `COL14` text DEFAULT NULL, + `COL15` text DEFAULT NULL, + `COL16` text DEFAULT NULL, + `COL17` text DEFAULT NULL, + `COL18` text DEFAULT NULL, + `COL19` text DEFAULT NULL, + `COL20` text DEFAULT NULL, + `COL21` text DEFAULT NULL, + `COL22` text DEFAULT NULL, + `COL23` text DEFAULT NULL, + `COL24` text DEFAULT NULL, + `COL25` text DEFAULT NULL, + `COL26` text DEFAULT NULL, + `COL27` text DEFAULT NULL, + `COL28` text DEFAULT NULL, + `COL29` text DEFAULT NULL, + `COL30` text DEFAULT NULL, + `COL31` text DEFAULT NULL, + `COL32` text DEFAULT NULL, + `COL33` text DEFAULT NULL, + `COL34` text DEFAULT NULL, + `COL35` text DEFAULT NULL, + `COL36` text DEFAULT NULL, + `COL37` text DEFAULT NULL, + `COL38` text DEFAULT NULL, + `COL39` text DEFAULT NULL, + `COL40` text DEFAULT NULL, + `COL41` text DEFAULT NULL, + `COL42` text DEFAULT NULL, + `COL43` text DEFAULT NULL, + `COL44` text DEFAULT NULL, + `COL45` text DEFAULT NULL, + `COL46` text DEFAULT NULL, + `COL47` text DEFAULT NULL, + `COL48` text DEFAULT NULL, + `COL49` text DEFAULT NULL, + `COL50` text DEFAULT NULL, + `COL51` text DEFAULT NULL, + `COL52` text DEFAULT NULL, + `COL53` text DEFAULT NULL, + `COL54` text DEFAULT NULL, + `COL55` text DEFAULT NULL, + `COL56` text DEFAULT NULL, + `COL57` text DEFAULT NULL, + `COL58` text DEFAULT NULL, + `COL59` text DEFAULT NULL, + `COL60` text DEFAULT NULL, + `COL61` text DEFAULT NULL, + `COL62` text DEFAULT NULL, + `COL63` text DEFAULT NULL, + `COL64` text DEFAULT NULL, + `COL65` text DEFAULT NULL, + `COL66` text DEFAULT NULL, + `COL67` text DEFAULT NULL, + `COL68` text DEFAULT NULL, + `COL69` text DEFAULT NULL, + `COL70` text DEFAULT NULL, + `COL71` text DEFAULT NULL, + `COL72` text DEFAULT NULL, + `COL73` text DEFAULT NULL, + `COL74` text DEFAULT NULL, + `COL75` text DEFAULT NULL, + `COL76` text DEFAULT NULL, + `COL77` text DEFAULT NULL, + `COL78` text DEFAULT NULL, + `COL79` text DEFAULT NULL, + `COL80` text DEFAULT NULL, + `COL81` text DEFAULT NULL, + `COL82` text DEFAULT NULL, + `COL83` text DEFAULT NULL, + `COL84` text DEFAULT NULL, + `COL85` text DEFAULT NULL, + `COL86` text DEFAULT NULL, + `COL87` text DEFAULT NULL, + `COL88` text DEFAULT NULL, + `COL89` text DEFAULT NULL, + `COL90` text DEFAULT NULL, + `COL91` text DEFAULT NULL, + `COL92` text DEFAULT NULL, + `COL93` text DEFAULT NULL, + `COL94` text DEFAULT NULL, + `COL95` text DEFAULT NULL, + `COL96` text DEFAULT NULL, + `COL97` text DEFAULT NULL, + `COL98` text DEFAULT NULL, + `COL99` text DEFAULT NULL, + `COL100` text DEFAULT NULL, + `COL101` text DEFAULT NULL, + `COL102` text DEFAULT NULL, + `COL103` text DEFAULT NULL, + `COL104` text DEFAULT NULL, + `COL105` text DEFAULT NULL, + `COL106` text DEFAULT NULL, + `COL107` text DEFAULT NULL, + `COL108` text DEFAULT NULL, + `COL109` text DEFAULT NULL, + `COL110` text DEFAULT NULL, + `COL111` text DEFAULT NULL, + `COL112` text DEFAULT NULL, + `COL113` text DEFAULT NULL, + `COL114` text DEFAULT NULL, + `COL115` text DEFAULT NULL, + `COL116` text DEFAULT NULL, + `COL117` text DEFAULT NULL, + `COL118` text DEFAULT NULL, + `COL119` text DEFAULT NULL, + `COL120` text DEFAULT NULL, + `COL121` text DEFAULT NULL, + `COL122` text DEFAULT NULL, + `COL123` text DEFAULT NULL, + `COL124` text DEFAULT NULL, + `COL125` text DEFAULT NULL, + `COL126` text DEFAULT NULL, + `COL127` text DEFAULT NULL, + `COL128` text DEFAULT NULL, + `COL129` text DEFAULT NULL, + `COL130` text DEFAULT NULL, + `COL131` text DEFAULT NULL, + `COL132` text DEFAULT NULL, + `COL133` text DEFAULT NULL, + `COL134` text DEFAULT NULL, + `COL135` text DEFAULT NULL, + `COL136` text DEFAULT NULL, + `COL137` text DEFAULT NULL, + `COL138` text DEFAULT NULL, + `COL139` text DEFAULT NULL, + `COL140` text DEFAULT NULL, + `COL141` text DEFAULT NULL, + `COL142` text DEFAULT NULL, + `COL143` text DEFAULT NULL, + `COL144` text DEFAULT NULL, + `COL145` text DEFAULT NULL, + `COL146` text DEFAULT NULL, + `COL147` text DEFAULT NULL, + `COL148` text DEFAULT NULL, + `COL149` text DEFAULT NULL, + `COL150` text DEFAULT NULL, + `COL151` text DEFAULT NULL, + `COL152` text DEFAULT NULL, + `COL153` text DEFAULT NULL, + `COL154` text DEFAULT NULL, + `COL155` text DEFAULT NULL, + `COL156` text DEFAULT NULL, + `COL157` text DEFAULT NULL, + `COL158` text DEFAULT NULL, + `COL159` text DEFAULT NULL, + `COL160` text DEFAULT NULL, + `COL161` text DEFAULT NULL, + `COL162` text DEFAULT NULL, + `COL163` text DEFAULT NULL, + `COL164` text DEFAULT NULL, + `COL165` text DEFAULT NULL, + `COL166` text DEFAULT NULL, + `COL167` text DEFAULT NULL, + `COL168` text DEFAULT NULL, + `COL169` text DEFAULT NULL, + `COL170` text DEFAULT NULL, + `COL171` text DEFAULT NULL, + `COL172` text DEFAULT NULL, + `COL173` text DEFAULT NULL, + `COL174` text DEFAULT NULL, + `COL175` text DEFAULT NULL, + `COL176` text DEFAULT NULL, + `COL177` text DEFAULT NULL, + `COL178` text DEFAULT NULL, + `COL179` text DEFAULT NULL, + `COL180` text DEFAULT NULL, + `COL181` text DEFAULT NULL, + `COL182` text DEFAULT NULL, + `COL183` text DEFAULT NULL, + `COL184` text DEFAULT NULL, + `COL185` text DEFAULT NULL, + `COL186` text DEFAULT NULL, + `COL187` text DEFAULT NULL, + `COL188` text DEFAULT NULL, + `COL189` text DEFAULT NULL, + `COL190` text DEFAULT NULL, + `COL191` text DEFAULT NULL, + `COL192` text DEFAULT NULL, + `COL193` text DEFAULT NULL, + `COL194` text DEFAULT NULL, + `COL195` text DEFAULT NULL, + `COL196` text DEFAULT NULL, + `COL197` text DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC update t2 set col150=@a; update t2 set col145=@b; diff --git a/mysql-test/suite/innodb/r/innodb-64k-crash.result b/mysql-test/suite/innodb/r/innodb-64k-crash.result index 9371c4a09e5..7e2941b8e3b 100644 --- a/mysql-test/suite/innodb/r/innodb-64k-crash.result +++ b/mysql-test/suite/innodb/r/innodb-64k-crash.result @@ -1,6 +1,4 @@ call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob, h blob,i blob,j blob,k blob,l blob,m blob,n blob, o blob,p blob,q blob,r blob,s blob,t blob,u blob, @@ -347,110 +345,110 @@ COMMIT; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` blob, - `b` blob, - `c` blob, - `d` blob, - `e` blob, - `f` blob, - `g` blob, - `h` blob, - `i` blob, - `j` blob, - `k` blob, - `l` blob, - `m` blob, - `n` blob, - `o` blob, - `p` blob, - `q` blob, - `r` blob, - `s` blob, - `t` blob, - `u` blob, - `v` blob, - `w` blob, - `x` blob, - `y` blob, - `z` blob, - `aa` blob, - `ba` blob, - `ca` blob, - `da` blob, - `ea` blob, - `fa` blob, - `ga` blob, - `ha` blob, - `ia` blob, - `ja` blob, - `ka` blob, - `la` blob, - `ma` blob, - `na` blob, - `oa` blob, - `pa` blob, - `qa` blob, - `ra` blob, - `sa` blob, - `ta` blob, - `ua` blob, - `va` blob, - `wa` blob, - `xa` blob, - `ya` blob, - `za` blob, - `ab` blob, - `bb` blob, - `cb` blob, - `db` blob, - `eb` blob, - `fb` blob, - `gb` blob, - `hb` blob, - `ib` blob, - `jb` blob, - `kb` blob, - `lb` blob, - `mb` blob, - `nb` blob, - `ob` blob, - `pb` blob, - `qb` blob, - `rb` blob, - `sb` blob, - `tb` blob, - `ub` blob, - `vb` blob, - `wb` blob, - `xb` blob, - `yb` blob, - `zb` blob, - `ac` blob, - `bc` blob, - `cc` blob, - `dc` blob, - `ec` blob, - `fc` blob, - `gc` blob, - `hc` blob, - `ic` blob, - `jc` blob, - `kc` blob, - `lc` blob, - `mc` blob, - `nc` blob, - `oc` blob, - `pc` blob, - `qc` blob, - `rc` blob, - `sc` blob, - `tc` blob, - `uc` blob, - `vc` blob, - `wc` blob, - `xc` blob, - `yc` blob, - `zc` blob, + `a` blob DEFAULT NULL, + `b` blob DEFAULT NULL, + `c` blob DEFAULT NULL, + `d` blob DEFAULT NULL, + `e` blob DEFAULT NULL, + `f` blob DEFAULT NULL, + `g` blob DEFAULT NULL, + `h` blob DEFAULT NULL, + `i` blob DEFAULT NULL, + `j` blob DEFAULT NULL, + `k` blob DEFAULT NULL, + `l` blob DEFAULT NULL, + `m` blob DEFAULT NULL, + `n` blob DEFAULT NULL, + `o` blob DEFAULT NULL, + `p` blob DEFAULT NULL, + `q` blob DEFAULT NULL, + `r` blob DEFAULT NULL, + `s` blob DEFAULT NULL, + `t` blob DEFAULT NULL, + `u` blob DEFAULT NULL, + `v` blob DEFAULT NULL, + `w` blob DEFAULT NULL, + `x` blob DEFAULT NULL, + `y` blob DEFAULT NULL, + `z` blob DEFAULT NULL, + `aa` blob DEFAULT NULL, + `ba` blob DEFAULT NULL, + `ca` blob DEFAULT NULL, + `da` blob DEFAULT NULL, + `ea` blob DEFAULT NULL, + `fa` blob DEFAULT NULL, + `ga` blob DEFAULT NULL, + `ha` blob DEFAULT NULL, + `ia` blob DEFAULT NULL, + `ja` blob DEFAULT NULL, + `ka` blob DEFAULT NULL, + `la` blob DEFAULT NULL, + `ma` blob DEFAULT NULL, + `na` blob DEFAULT NULL, + `oa` blob DEFAULT NULL, + `pa` blob DEFAULT NULL, + `qa` blob DEFAULT NULL, + `ra` blob DEFAULT NULL, + `sa` blob DEFAULT NULL, + `ta` blob DEFAULT NULL, + `ua` blob DEFAULT NULL, + `va` blob DEFAULT NULL, + `wa` blob DEFAULT NULL, + `xa` blob DEFAULT NULL, + `ya` blob DEFAULT NULL, + `za` blob DEFAULT NULL, + `ab` blob DEFAULT NULL, + `bb` blob DEFAULT NULL, + `cb` blob DEFAULT NULL, + `db` blob DEFAULT NULL, + `eb` blob DEFAULT NULL, + `fb` blob DEFAULT NULL, + `gb` blob DEFAULT NULL, + `hb` blob DEFAULT NULL, + `ib` blob DEFAULT NULL, + `jb` blob DEFAULT NULL, + `kb` blob DEFAULT NULL, + `lb` blob DEFAULT NULL, + `mb` blob DEFAULT NULL, + `nb` blob DEFAULT NULL, + `ob` blob DEFAULT NULL, + `pb` blob DEFAULT NULL, + `qb` blob DEFAULT NULL, + `rb` blob DEFAULT NULL, + `sb` blob DEFAULT NULL, + `tb` blob DEFAULT NULL, + `ub` blob DEFAULT NULL, + `vb` blob DEFAULT NULL, + `wb` blob DEFAULT NULL, + `xb` blob DEFAULT NULL, + `yb` blob DEFAULT NULL, + `zb` blob DEFAULT NULL, + `ac` blob DEFAULT NULL, + `bc` blob DEFAULT NULL, + `cc` blob DEFAULT NULL, + `dc` blob DEFAULT NULL, + `ec` blob DEFAULT NULL, + `fc` blob DEFAULT NULL, + `gc` blob DEFAULT NULL, + `hc` blob DEFAULT NULL, + `ic` blob DEFAULT NULL, + `jc` blob DEFAULT NULL, + `kc` blob DEFAULT NULL, + `lc` blob DEFAULT NULL, + `mc` blob DEFAULT NULL, + `nc` blob DEFAULT NULL, + `oc` blob DEFAULT NULL, + `pc` blob DEFAULT NULL, + `qc` blob DEFAULT NULL, + `rc` blob DEFAULT NULL, + `sc` blob DEFAULT NULL, + `tc` blob DEFAULT NULL, + `uc` blob DEFAULT NULL, + `vc` blob DEFAULT NULL, + `wc` blob DEFAULT NULL, + `xc` blob DEFAULT NULL, + `yc` blob DEFAULT NULL, + `zc` blob DEFAULT NULL, KEY `t1a` (`a`(767),`b`(767)), KEY `t1c` (`c`(767),`d`(767)), KEY `t1e` (`e`(767),`f`(767)), @@ -470,110 +468,110 @@ t1 CREATE TABLE `t1` ( show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `a` blob, - `b` blob, - `c` blob, - `d` blob, - `e` blob, - `f` blob, - `g` blob, - `h` blob, - `i` blob, - `j` blob, - `k` blob, - `l` blob, - `m` blob, - `n` blob, - `o` blob, - `p` blob, - `q` blob, - `r` blob, - `s` blob, - `t` blob, - `u` blob, - `v` blob, - `w` blob, - `x` blob, - `y` blob, - `z` blob, - `aa` blob, - `ba` blob, - `ca` blob, - `da` blob, - `ea` blob, - `fa` blob, - `ga` blob, - `ha` blob, - `ia` blob, - `ja` blob, - `ka` blob, - `la` blob, - `ma` blob, - `na` blob, - `oa` blob, - `pa` blob, - `qa` blob, - `ra` blob, - `sa` blob, - `ta` blob, - `ua` blob, - `va` blob, - `wa` blob, - `xa` blob, - `ya` blob, - `za` blob, - `ab` blob, - `bb` blob, - `cb` blob, - `db` blob, - `eb` blob, - `fb` blob, - `gb` blob, - `hb` blob, - `ib` blob, - `jb` blob, - `kb` blob, - `lb` blob, - `mb` blob, - `nb` blob, - `ob` blob, - `pb` blob, - `qb` blob, - `rb` blob, - `sb` blob, - `tb` blob, - `ub` blob, - `vb` blob, - `wb` blob, - `xb` blob, - `yb` blob, - `zb` blob, - `ac` blob, - `bc` blob, - `cc` blob, - `dc` blob, - `ec` blob, - `fc` blob, - `gc` blob, - `hc` blob, - `ic` blob, - `jc` blob, - `kc` blob, - `lc` blob, - `mc` blob, - `nc` blob, - `oc` blob, - `pc` blob, - `qc` blob, - `rc` blob, - `sc` blob, - `tc` blob, - `uc` blob, - `vc` blob, - `wc` blob, - `xc` blob, - `yc` blob, - `zc` blob, + `a` blob DEFAULT NULL, + `b` blob DEFAULT NULL, + `c` blob DEFAULT NULL, + `d` blob DEFAULT NULL, + `e` blob DEFAULT NULL, + `f` blob DEFAULT NULL, + `g` blob DEFAULT NULL, + `h` blob DEFAULT NULL, + `i` blob DEFAULT NULL, + `j` blob DEFAULT NULL, + `k` blob DEFAULT NULL, + `l` blob DEFAULT NULL, + `m` blob DEFAULT NULL, + `n` blob DEFAULT NULL, + `o` blob DEFAULT NULL, + `p` blob DEFAULT NULL, + `q` blob DEFAULT NULL, + `r` blob DEFAULT NULL, + `s` blob DEFAULT NULL, + `t` blob DEFAULT NULL, + `u` blob DEFAULT NULL, + `v` blob DEFAULT NULL, + `w` blob DEFAULT NULL, + `x` blob DEFAULT NULL, + `y` blob DEFAULT NULL, + `z` blob DEFAULT NULL, + `aa` blob DEFAULT NULL, + `ba` blob DEFAULT NULL, + `ca` blob DEFAULT NULL, + `da` blob DEFAULT NULL, + `ea` blob DEFAULT NULL, + `fa` blob DEFAULT NULL, + `ga` blob DEFAULT NULL, + `ha` blob DEFAULT NULL, + `ia` blob DEFAULT NULL, + `ja` blob DEFAULT NULL, + `ka` blob DEFAULT NULL, + `la` blob DEFAULT NULL, + `ma` blob DEFAULT NULL, + `na` blob DEFAULT NULL, + `oa` blob DEFAULT NULL, + `pa` blob DEFAULT NULL, + `qa` blob DEFAULT NULL, + `ra` blob DEFAULT NULL, + `sa` blob DEFAULT NULL, + `ta` blob DEFAULT NULL, + `ua` blob DEFAULT NULL, + `va` blob DEFAULT NULL, + `wa` blob DEFAULT NULL, + `xa` blob DEFAULT NULL, + `ya` blob DEFAULT NULL, + `za` blob DEFAULT NULL, + `ab` blob DEFAULT NULL, + `bb` blob DEFAULT NULL, + `cb` blob DEFAULT NULL, + `db` blob DEFAULT NULL, + `eb` blob DEFAULT NULL, + `fb` blob DEFAULT NULL, + `gb` blob DEFAULT NULL, + `hb` blob DEFAULT NULL, + `ib` blob DEFAULT NULL, + `jb` blob DEFAULT NULL, + `kb` blob DEFAULT NULL, + `lb` blob DEFAULT NULL, + `mb` blob DEFAULT NULL, + `nb` blob DEFAULT NULL, + `ob` blob DEFAULT NULL, + `pb` blob DEFAULT NULL, + `qb` blob DEFAULT NULL, + `rb` blob DEFAULT NULL, + `sb` blob DEFAULT NULL, + `tb` blob DEFAULT NULL, + `ub` blob DEFAULT NULL, + `vb` blob DEFAULT NULL, + `wb` blob DEFAULT NULL, + `xb` blob DEFAULT NULL, + `yb` blob DEFAULT NULL, + `zb` blob DEFAULT NULL, + `ac` blob DEFAULT NULL, + `bc` blob DEFAULT NULL, + `cc` blob DEFAULT NULL, + `dc` blob DEFAULT NULL, + `ec` blob DEFAULT NULL, + `fc` blob DEFAULT NULL, + `gc` blob DEFAULT NULL, + `hc` blob DEFAULT NULL, + `ic` blob DEFAULT NULL, + `jc` blob DEFAULT NULL, + `kc` blob DEFAULT NULL, + `lc` blob DEFAULT NULL, + `mc` blob DEFAULT NULL, + `nc` blob DEFAULT NULL, + `oc` blob DEFAULT NULL, + `pc` blob DEFAULT NULL, + `qc` blob DEFAULT NULL, + `rc` blob DEFAULT NULL, + `sc` blob DEFAULT NULL, + `tc` blob DEFAULT NULL, + `uc` blob DEFAULT NULL, + `vc` blob DEFAULT NULL, + `wc` blob DEFAULT NULL, + `xc` blob DEFAULT NULL, + `yc` blob DEFAULT NULL, + `zc` blob DEFAULT NULL, KEY `t2a` (`a`(767),`b`(767)), KEY `t2c` (`c`(767),`d`(767)), KEY `t2e` (`e`(767),`f`(767)), diff --git a/mysql-test/suite/innodb/r/innodb-64k.result b/mysql-test/suite/innodb/r/innodb-64k.result index c84ad8caf88..9271ad70fb4 100644 --- a/mysql-test/suite/innodb/r/innodb-64k.result +++ b/mysql-test/suite/innodb/r/innodb-64k.result @@ -2,8 +2,6 @@ call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed fro call mtr.add_suppression("InnoDB: Resizing redo log from *"); call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files."); call mtr.add_suppression("InnoDB: New log files created, LSN=*"); -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; diff --git a/mysql-test/suite/innodb/r/innodb-bug-14068765.result b/mysql-test/suite/innodb/r/innodb-bug-14068765.result index f6d37b23114..f7a2644cbf9 100644 --- a/mysql-test/suite/innodb/r/innodb-bug-14068765.result +++ b/mysql-test/suite/innodb/r/innodb-bug-14068765.result @@ -1,8 +1,3 @@ -DROP TABLE IF EXISTS t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 CREATE DATABASE testdb_wl5522; CREATE TABLE testdb_wl5522.t1(col1 bit(1) , col2 boolean,col3 tinyint , col4 smallint , col5 mediumint ,col6 int , col7 bigint , col8 float (14,3) ,col9 double (14,3), col10 VARCHAR(20) CHARACTER SET utf8 , col11 TEXT CHARACTER SET binary , col12 ENUM('a','b','c') CHARACTER SET binary ,col13 TEXT CHARACTER SET latin1 COLLATE latin1_general_cs ,col14 CHAR(20) , col15 VARBINARY (400) , col16 BINARY(40), col17 BLOB (400) , col18 int not null primary key,col19 DATE ,col20 DATETIME , col21 TIMESTAMP ,col22 TIME , col23 YEAR ) ENGINE = Innodb; CREATE INDEX idx1 ON testdb_wl5522.t1(col18); @@ -38,7 +33,3 @@ COUNT(*) 2 DROP TABLE testdb_wl5522.t1; DROP DATABASE testdb_wl5522; -SET GLOBAL INNODB_FILE_FORMAT=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL INNODB_FILE_PER_TABLE=1; diff --git a/mysql-test/suite/innodb/r/innodb-bug-14084530.result b/mysql-test/suite/innodb/r/innodb-bug-14084530.result index 3ba8e0e8440..b8e0e3a579d 100644 --- a/mysql-test/suite/innodb/r/innodb-bug-14084530.result +++ b/mysql-test/suite/innodb/r/innodb-bug-14084530.result @@ -1,8 +1,3 @@ -DROP TABLE IF EXISTS t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 SET AUTOCOMMIT = 0; CREATE DATABASE testdb_wl5522; CREATE TABLE testdb_wl5522.t1 (c1 int ) engine = Innodb; @@ -24,10 +19,4 @@ Table Op Msg_type Msg_text testdb_wl5522.t1 check status OK SELECT c1 FROM testdb_wl5522.t1; c1 -SET AUTOCOMMIT = 1; -DROP TABLE testdb_wl5522.t1; DROP DATABASE testdb_wl5522; -SET GLOBAL INNODB_FILE_FORMAT=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL INNODB_FILE_PER_TABLE=1; diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index 2b5e7bf214d..1b7f44fa8c4 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -1,7 +1,3 @@ -set global innodb_file_per_table=on; -set global innodb_file_format='Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS; create table t1(a varchar(2) primary key) engine=innodb; insert into t1 values(''); @@ -858,13 +854,6 @@ explain select * from t1 order by a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index drop table t1; -set global innodb_file_per_table=1; -set global innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_format_max=Barracuda; -Warnings: -Warning 131 Using innodb_file_format_max is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET FOREIGN_KEY_CHECKS=0; CREATE TABLE t1( @@ -1195,7 +1184,3 @@ t2c CREATE TABLE `t2c` ( KEY `t2a` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t1,t2,t2c,t2i; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -Warnings: -Warning 131 Using innodb_file_format_max is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result b/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result index a566c94bd3b..61507ddbe5c 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_bzip2.result @@ -1,7 +1,3 @@ -set global innodb_file_format = `barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table = on; set global innodb_compression_algorithm = 5; create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; show warnings; @@ -437,5 +433,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result b/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result index 76cd5b16f28..6cef1978ca0 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_lz4.result @@ -1,7 +1,3 @@ -set global innodb_file_format = `barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table = on; set global innodb_compression_algorithm = 2; create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; show warnings; @@ -438,5 +434,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result b/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result index cceff820ee0..c7ab859e102 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_lzma.result @@ -1,7 +1,3 @@ -set global innodb_file_format = `barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table = on; set global innodb_compression_algorithm = 4; create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; show warnings; @@ -437,5 +433,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result b/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result index 1a9235fab62..379abcc9968 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_lzo.result @@ -1,7 +1,3 @@ -set global innodb_file_format = `barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table = on; set global innodb_compression_algorithm = 3; create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; show warnings; @@ -351,5 +347,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result b/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result index e1d46b04a7f..6b1ddd64e6c 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result @@ -1,8 +1,3 @@ -call mtr.add_suppression("Compression failed for space*"); -set global innodb_file_format = `barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table = on; set global innodb_compression_algorithm = 6; create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; show warnings; @@ -438,5 +433,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_tables.result b/mysql-test/suite/innodb/r/innodb-page_compression_tables.result index 7d825e73aa4..94420e5397d 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_tables.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_tables.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 1; create table innodb_normal(c1 bigint not null, b char(200)) engine=innodb; create table innodb_compact(c1 bigint not null, b char(200)) engine=innodb row_format=compact page_compressed=1; @@ -92,10 +88,6 @@ count(*) select count(*) from innodb_dynamic where c1 < 1500000; count(*) 5000 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 0; alter table innodb_compact engine=innodb page_compressed=DEFAULT; alter table innodb_dynamic engine=innodb page_compressed=DEFAULT; @@ -149,5 +141,3 @@ DROP TABLE no_compression; DROP TABLE default_compression; DROP TABLE explicit_no_compression; SET SESSION innodb_compression_default = 0; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_zip.result b/mysql-test/suite/innodb/r/innodb-page_compression_zip.result index a8078c02e13..bb9ceb29e17 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_zip.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_zip.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; set global innodb_compression_algorithm = 1; create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; show warnings; @@ -351,5 +347,3 @@ drop table innodb_page_compressed6; drop table innodb_page_compressed7; drop table innodb_page_compressed8; drop table innodb_page_compressed9; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-1.result b/mysql-test/suite/innodb/r/innodb-wl5522-1.result index 0660ee1fae2..b2a5f49a9ad 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-1.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-1.result @@ -1,18 +1,4 @@ call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); -DROP TABLE IF EXISTS t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SELECT @@innodb_file_format; -@@innodb_file_format -Barracuda -DROP DATABASE IF EXISTS testdb_wl5522; -Warnings: -Note 1008 Can't drop database 'testdb_wl5522'; database doesn't exist CREATE DATABASE testdb_wl5522; CREATE TABLE testdb_wl5522.t1 (c1 INT ) ENGINE = Innodb; INSERT INTO testdb_wl5522.t1 VALUES (1),(123),(331); @@ -44,37 +30,37 @@ CREATE TABLE testdb_wl5522.t1 ( col1 BIT(1), col2 BOOLEAN, col3 TINYINT, -col4 SMALLINT, +col4 SMALLINT, col5 MEDIUMINT, col6 INT, -col7 BIGINT, +col7 BIGINT, col8 FLOAT (14,3) , -col9 DOUBLE (14,3), -col10 VARCHAR(20), +col9 DOUBLE (14,3), +col10 VARCHAR(20), col11 TEXT , col12 ENUM('a','b','c'), col13 TEXT, -col14 CHAR(20) , -col15 VARBINARY (400) , -col16 BINARY(40), -col17 BLOB (400) , +col14 CHAR(20), +col15 VARBINARY (400), +col16 BINARY(40), +col17 BLOB (400), col18 INT NOT NULL PRIMARY KEY, -col19 DATE , -col20 DATETIME , -col21 TIMESTAMP , -col22 TIME , +col19 DATE, +col20 DATETIME, +col21 TIMESTAMP, +col22 TIME, col23 YEAR ) ENGINE = Innodb; CREATE INDEX idx1 ON testdb_wl5522.t1(col18); CREATE INDEX prefix_idx ON testdb_wl5522.t1(col14 (10)); CREATE UNIQUE INDEX idx2 ON testdb_wl5522.t1(col12); CREATE UNIQUE INDEX idx3 ON testdb_wl5522.t1(col8); -INSERT INTO testdb_wl5522.t1 VALUES +INSERT INTO testdb_wl5522.t1 VALUES (1,1,-128,32767,-8388608,2147483647,-9223372036854775808, 92233720368.222, -92233720368.222,'aaa', + 'aaaaaaaaaa','b','bbbbb','ccccc', REPEAT('d',40),REPEAT('d',40),REPEAT('d',40),1,'1000-01-01', '3000-12-31 23:59:59.99','1990-01-01 00:00:01.00', '01:59:59.00','1901'); -INSERT INTO testdb_wl5522.t1 VALUES +INSERT INTO testdb_wl5522.t1 VALUES (NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,3,NULL,NULL,NULL,NULL,NULL); INSERT INTO testdb_wl5522.t1 VALUES (NULL,NULL,NULL,NULL,NULL,NULL,NULL, @@ -112,7 +98,7 @@ col18 INT NOT NULL PRIMARY KEY, col19 DATE , col20 DATETIME , col21 TIMESTAMP , -col22 TIME , +col22 TIME, col23 YEAR ) ENGINE = Innodb; CREATE INDEX idx1 ON testdb_wl5522.t1(col18); CREATE INDEX prefix_idx ON testdb_wl5522.t1(col14 (10)); @@ -128,9 +114,6 @@ SELECT COUNT(*) FROM testdb_wl5522.t1; COUNT(*) 2 DROP TABLE testdb_wl5522.t1; -SET GLOBAL innodb_file_format='Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html CREATE TABLE testdb_wl5522.t1 ( col_1_varbinary VARBINARY (4000) , col_2_varchar VARCHAR (4000), @@ -143,13 +126,13 @@ col_7_binary BINARY (255) INSERT INTO testdb_wl5522.t1 VALUES( REPEAT('a', 4000),REPEAT('o', 4000),REPEAT('a', 4000), REPEAT('o', 4000), REPEAT('a', 4000),REPEAT('a', 4000),REPEAT('a', 255)); -SELECT col_1_varbinary = REPEAT("a", 4000) , +SELECT col_1_varbinary = REPEAT("a", 4000), col_2_varchar = REPEAT("o", 4000) , col_3_text = REPEAT("a", 4000) , col_4_blob = REPEAT("o", 4000) , col_5_text = REPEAT("a", 4000) , col_6_varchar = REPEAT("a", 4000) , -col_7_binary = REPEAT("a", 255) +col_7_binary = REPEAT("a", 255) FROM testdb_wl5522.t1; col_1_varbinary = REPEAT("a", 4000) col_2_varchar = REPEAT("o", 4000) col_3_text = REPEAT("a", 4000) col_4_blob = REPEAT("o", 4000) col_5_text = REPEAT("a", 4000) col_6_varchar = REPEAT("a", 4000) col_7_binary = REPEAT("a", 255) 1 1 1 1 1 1 1 @@ -175,14 +158,14 @@ col_3_text = REPEAT("a", 4000) , col_4_blob = REPEAT("o", 4000) , col_5_text = REPEAT("a", 4000) , col_6_varchar = REPEAT("a", 4000) , -col_7_binary = REPEAT("a", 255) +col_7_binary = REPEAT("a", 255) FROM testdb_wl5522.t1; col_1_varbinary = REPEAT("a", 4000) col_2_varchar = REPEAT("o", 4000) col_3_text = REPEAT("a", 4000) col_4_blob = REPEAT("o", 4000) col_5_text = REPEAT("a", 4000) col_6_varchar = REPEAT("a", 4000) col_7_binary = REPEAT("a", 255) 1 1 1 1 1 1 1 DROP TABLE testdb_wl5522.t1; CREATE TABLE testdb_wl5522.t1 ( col_1_int INT AUTO_INCREMENT, -col_2_varchar VARCHAR (20), +col_2_varchar VARCHAR (20), PRIMARY KEY (col_1_int)) ENGINE = Innodb; INSERT INTO testdb_wl5522.t1 VALUES (1,'a1'),(2,'a2'),(3,'a3'); INSERT INTO testdb_wl5522.t1 (col_2_varchar) VALUES ('a4'),('a5'),('a6'); @@ -245,7 +228,7 @@ col_1_int INT,col_2_varchar VARCHAR (20), PRIMARY KEY (col_2_varchar)) ENGINE = Innodb; CREATE TABLE testdb_wl5522.t1_fk ( col_1_int INT,col_2_varchar VARCHAR (20), -PRIMARY KEY (col_1_int), +PRIMARY KEY (col_1_int), FOREIGN KEY (col_2_varchar) REFERENCES testdb_wl5522.t1(col_2_varchar) ) ENGINE = Innodb; INSERT INTO testdb_wl5522.t1 VALUES (1,'a1'),(2,'a2'),(3,'a3'),(4,'a4'),(5,'a5'); @@ -702,19 +685,19 @@ DROP TABLE testdb_wl5522.t1; SET AUTOCOMMIT = 1; CREATE TABLE testdb_wl5522.t1(col1 bit(1) , col2 boolean,col3 tinyint , col4 smallint , -col5 mediumint ,col6 int , col7 bigint , +col5 mediumint ,col6 int , col7 bigint , col8 float (14,3) ,col9 double (14,3), col10 VARCHAR(20) CHARACTER SET utf8 , col11 TEXT CHARACTER SET binary , col12 ENUM('a','b','c') CHARACTER SET binary, col13 TEXT CHARACTER SET latin1 COLLATE latin1_general_cs , col14 CHAR(20) , col15 VARBINARY (400), -col16 BINARY(40), col17 BLOB (400), +col16 BINARY(40), col17 BLOB (400), col18 int not null primary key, col19 DATE ,col20 DATETIME , col21 TIMESTAMP , col22 TIME , col23 YEAR ) ENGINE = Innodb; CREATE TABLE testdb_wl5522.trigger_table ( i int ) ENGINE = Innodb; -CREATE TRIGGER testdb_wl5522.tri AFTER INSERT ON testdb_wl5522.t1 +CREATE TRIGGER testdb_wl5522.tri AFTER INSERT ON testdb_wl5522.t1 FOR EACH ROW INSERT INTO testdb_wl5522.trigger_table VALUES(NEW.col18); CREATE OR REPLACE VIEW testdb_wl5522.VW1 AS SELECT * FROM testdb_wl5522.t1; CREATE INDEX idx1 ON testdb_wl5522.t1(col18); @@ -812,7 +795,3 @@ DROP DATABASE testdb_wl5522; call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); -SET GLOBAL INNODB_FILE_FORMAT=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL INNODB_FILE_PER_TABLE=1; diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result b/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result index cb19c66914e..ab6bf0c808e 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-debug-zip.result @@ -5,23 +5,7 @@ call mtr.add_suppression("InnoDB: Tablespace flags: .* corrupted in file: .* ") call mtr.add_suppression("InnoDB: Page 0 at offset 0 looks corrupted in file .*"); call mtr.add_suppression("InnoDB: Page for tablespace .* "); flush tables; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SELECT @@innodb_file_format; -@@innodb_file_format -Barracuda SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; -@@SESSION.innodb_strict_mode -1 -DROP DATABASE IF EXISTS test_wl5522; -Warnings: -Note 1008 Can't drop database 'test_wl5522'; database doesn't exist CREATE DATABASE test_wl5522; CREATE TABLE test_wl5522.t1 (c1 INT) ENGINE = Innodb ROW_FORMAT=COMPRESSED; @@ -53,20 +37,7 @@ unlink: t1.cfg # Restart and reconnect to the server SET SESSION debug_dbug="-d,ib_import_before_checkpoint_crash"; DROP TABLE test_wl5522.t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SELECT @@innodb_file_format; -@@innodb_file_format -Barracuda SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; -@@SESSION.innodb_strict_mode -1 CREATE TABLE test_wl5522.t1 (c1 INT) ENGINE = Innodb ROW_FORMAT=COMPRESSED; ALTER TABLE test_wl5522.t1 DISCARD TABLESPACE; @@ -587,8 +558,3 @@ 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; -SET GLOBAL INNODB_FILE_PER_TABLE=1; -SET GLOBAL INNODB_FILE_FORMAT=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET SESSION innodb_strict_mode=1; diff --git a/mysql-test/suite/innodb/r/innodb-wl5522-zip.result b/mysql-test/suite/innodb/r/innodb-wl5522-zip.result index 42b2b6a527b..54f4bcc8c1f 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522-zip.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522-zip.result @@ -1,19 +1,5 @@ call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); -DROP TABLE IF EXISTS t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SELECT @@innodb_file_format; -@@innodb_file_format -Barracuda SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; -@@SESSION.innodb_strict_mode -1 CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b char(22), @@ -107,20 +93,7 @@ a b c 822 Devotion asdfuihknaskdf 821 Cavalry ..asdasdfaeraf DROP TABLE t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SELECT @@innodb_file_format; -@@innodb_file_format -Barracuda SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; -@@SESSION.innodb_strict_mode -1 CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 INT) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; @@ -213,7 +186,7 @@ COUNT(*) DROP TABLE t1; CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -c2 INT, INDEX(c2)) ENGINE=InnoDB +c2 INT, INDEX(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; INSERT INTO t1(c2) VALUES(1); INSERT INTO t1(c2) SELECT c2 FROM t1; @@ -500,8 +473,3 @@ DROP TABLE t1; call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); -SET GLOBAL INNODB_FILE_FORMAT=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL INNODB_FILE_PER_TABLE=1; -SET SESSION innodb_strict_mode=1; diff --git a/mysql-test/suite/innodb/r/innodb-wl5522.result b/mysql-test/suite/innodb/r/innodb-wl5522.result index 2f8f56e9550..4075c8a1486 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522.result @@ -1,15 +1,4 @@ call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); -DROP TABLE IF EXISTS t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SELECT @@innodb_file_format; -@@innodb_file_format -Barracuda CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b char(22), @@ -103,16 +92,6 @@ a b c 822 Devotion asdfuihknaskdf 821 Cavalry ..asdasdfaeraf DROP TABLE t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; -@@innodb_file_per_table -1 -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SELECT @@innodb_file_format; -@@innodb_file_format -Barracuda CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, c2 INT) ENGINE=InnoDB; @@ -1034,7 +1013,3 @@ DROP TABLE t1; call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); -SET GLOBAL INNODB_FILE_FORMAT=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL INNODB_FILE_PER_TABLE=1; diff --git a/mysql-test/suite/innodb/r/innodb_blob_truncate.result b/mysql-test/suite/innodb/r/innodb_blob_truncate.result index a71dd7678c0..b10d4a94eb7 100644 --- a/mysql-test/suite/innodb/r/innodb_blob_truncate.result +++ b/mysql-test/suite/innodb/r/innodb_blob_truncate.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format = `Barracuda`; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table = ON; create table t1(a blob) engine=innodb key_block_size=8; create function generate_blob() returns varchar(20000) @@ -19,5 +15,3 @@ truncate t1; insert into t1 select generate_blob(); drop table t1; drop function generate_blob; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result b/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result index 5ae138477b9..a3ac78aadce 100644 --- a/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result +++ b/mysql-test/suite/innodb/r/innodb_prefix_index_restart_server.result @@ -1,11 +1,6 @@ -set global innodb_file_format="Barracuda"; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table=1; set global innodb_large_prefix=1; Warnings: Warning 131 Using innodb_large_prefix is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -DROP TABLE IF EXISTS worklog5743; CREATE TABLE worklog5743 ( col_1_text TEXT(4000) , col_2_text TEXT(4000) , PRIMARY KEY (col_1_text(3072)) @@ -92,10 +87,6 @@ worklog5743; col_1_text = REPEAT("a", 3500) col_2_text = REPEAT("o", 3500) 1 1 DROP TABLE worklog5743; -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=1; SET GLOBAL innodb_large_prefix=1; Warnings: Warning 131 Using innodb_large_prefix is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result index 099c673bca7..cc61f811e62 100644 --- a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result +++ b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result @@ -1,6 +1,7 @@ # # Testing robustness against random compression failures # +call mtr.add_suppression(".*"); CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; SHOW CREATE TABLE t1; Table Create Table diff --git a/mysql-test/suite/innodb/t/innochecksum.opt b/mysql-test/suite/innodb/t/innochecksum.opt deleted file mode 100644 index cc738d97434..00000000000 --- a/mysql-test/suite/innodb/t/innochecksum.opt +++ /dev/null @@ -1,2 +0,0 @@ ---innodb_file_per_table=1 ---innodb_file_format=Barracuda diff --git a/mysql-test/suite/innodb/t/innodb-16k.test b/mysql-test/suite/innodb/t/innodb-16k.test index ad09666442d..a771fac27ed 100644 --- a/mysql-test/suite/innodb/t/innodb-16k.test +++ b/mysql-test/suite/innodb/t/innodb-16k.test @@ -8,17 +8,11 @@ call mtr.add_suppression("InnoDB: Cannot add field .* in table .* because after --disable_query_log let $MYSQLD_DATADIR= `select @@datadir`; # These values can change during the test -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; -let $innodb_strict_mode_orig = `SELECT @@session.innodb_strict_mode`; let $innodb_large_prefix_orig = `SELECT @@innodb_large_prefix`; --enable_query_log -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; SET GLOBAL innodb_large_prefix = OFF; - --echo # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_page_size'; @@ -263,8 +257,6 @@ SELECT table_name, row_format, create_options DROP TABLE t1; -SET GLOBAL innodb_file_format = `Barracuda`; - CREATE TABLE t2(d varchar(17) PRIMARY KEY) ENGINE=innodb DEFAULT CHARSET=utf8; CREATE TABLE t3(a int PRIMARY KEY) ENGINE=innodb; INSERT INTO t3 VALUES (22),(44),(33),(55),(66); @@ -381,9 +373,6 @@ UPDATE t1 SET t=@e; SHOW CREATE TABLE t1; DROP TABLE t1; -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - --echo Test an assertion failure on purge. # This test is not in innodb_8k or innodb_4k since the bug is not about @@ -440,8 +429,6 @@ DELETE FROM t3_purge; DELETE FROM t4_purge; # A secondary index tuple is found to be too long to fit into a page. -SET GLOBAL innodb_file_per_table=on; -SET GLOBAL innodb_file_format='Barracuda'; SET @r=REPEAT('a',500); CREATE TABLE tlong(a int, @@ -961,8 +948,5 @@ row_format=compact,ENGINE=INNODB; # --disable_query_log -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET SESSION innodb_strict_mode = $innodb_strict_mode_orig; EVAL SET GLOBAL innodb_large_prefix = $innodb_large_prefix_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-32k-crash.test b/mysql-test/suite/innodb/t/innodb-32k-crash.test index 8f2e7d6c1e2..b9d96fd92c8 100644 --- a/mysql-test/suite/innodb/t/innodb-32k-crash.test +++ b/mysql-test/suite/innodb/t/innodb-32k-crash.test @@ -10,16 +10,7 @@ call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); ---disable_query_log let $MYSQLD_DATADIR= `select @@datadir`; -# These values can change during the test -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; -let $innodb_strict_mode_orig = `SELECT @@session.innodb_strict_mode`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob, h blob,i blob,j blob,k blob,l blob,m blob,n blob, @@ -210,13 +201,3 @@ COMMIT; show create table t1; show create table t2; drop table t1,t2; - -# -# restore environment to the state it was before this test execution -# - ---disable_query_log -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET SESSION innodb_strict_mode = $innodb_strict_mode_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-32k.test b/mysql-test/suite/innodb/t/innodb-32k.test index 65c1d4bbc76..53a2d3a7442 100644 --- a/mysql-test/suite/innodb/t/innodb-32k.test +++ b/mysql-test/suite/innodb/t/innodb-32k.test @@ -3,21 +3,13 @@ --source include/have_innodb.inc --source include/have_innodb_32k.inc -call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); -call mtr.add_suppression("InnoDB: Resizing redo log from *"); -call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files."); -call mtr.add_suppression("InnoDB: New log files created, LSN=*"); +call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value "); +call mtr.add_suppression("InnoDB: Resizing redo log from "); +call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files"); +call mtr.add_suppression("InnoDB: New log files created, LSN="); +call mtr.add_suppression("Innodb: Cannot add field.*row size is"); ---disable_query_log let $MYSQLD_DATADIR= `select @@datadir`; -# These values can change during the test -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; -let $innodb_strict_mode_orig = `SELECT @@session.innodb_strict_mode`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; --echo # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status @@ -347,9 +339,9 @@ CREATE INDEX tn1f9 ON t1 (oa(767)); CREATE INDEX to1f11 ON t1 (pa(767)); UPDATE t1 SET t=@e; -# One more index and row size is too big ---replace_regex /> [0-9]*/> max_row_size/ ---error ER_TOO_BIG_ROWSIZE +# One more index and row size is too big (not any more!) +#--replace_regex /> [0-9]*/> max_row_size/ +#--error ER_TOO_BIG_ROWSIZE CREATE INDEX t1f6 ON t1 (l(767)); drop table t1; @@ -410,8 +402,6 @@ DELETE FROM t3_purge; DELETE FROM t4_purge; # A secondary index tuple is found to be too long to fit into a page. -SET GLOBAL innodb_file_per_table=on; -SET GLOBAL innodb_file_format='Barracuda'; SET @r=REPEAT('a',500); CREATE TABLE tlong(a int, @@ -758,12 +748,3 @@ show create table t2; update t2 set col150=@a; update t2 set col145=@b; drop table t2; -# -# restore environment to the state it was before this test execution -# - ---disable_query_log -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET SESSION innodb_strict_mode = $innodb_strict_mode_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-64k-crash.test b/mysql-test/suite/innodb/t/innodb-64k-crash.test index 9d2d0d66415..b61396bf22c 100644 --- a/mysql-test/suite/innodb/t/innodb-64k-crash.test +++ b/mysql-test/suite/innodb/t/innodb-64k-crash.test @@ -10,16 +10,7 @@ call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *"); ---disable_query_log let $MYSQLD_DATADIR= `select @@datadir`; -# These values can change during the test -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; -let $innodb_strict_mode_orig = `SELECT @@session.innodb_strict_mode`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob, h blob,i blob,j blob,k blob,l blob,m blob,n blob, @@ -400,13 +391,3 @@ COMMIT; show create table t1; show create table t2; drop table t1,t2; - -# -# restore environment to the state it was before this test execution -# - ---disable_query_log -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET SESSION innodb_strict_mode = $innodb_strict_mode_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-64k.test b/mysql-test/suite/innodb/t/innodb-64k.test index bd0da6b66ad..c611b6cb2e2 100644 --- a/mysql-test/suite/innodb/t/innodb-64k.test +++ b/mysql-test/suite/innodb/t/innodb-64k.test @@ -1,5 +1,5 @@ --source include/no_valgrind_without_big.inc -# Tests for setting innodb-page-size=64k; +# Tests for setting innodb-page-size=64k; --source include/have_innodb.inc --source include/have_innodb_64k.inc @@ -8,16 +8,7 @@ call mtr.add_suppression("InnoDB: Resizing redo log from *"); call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files."); call mtr.add_suppression("InnoDB: New log files created, LSN=*"); ---disable_query_log let $MYSQLD_DATADIR= `select @@datadir`; -# These values can change during the test -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; -let $innodb_strict_mode_orig = `SELECT @@session.innodb_strict_mode`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; --echo # Test 1) Show the page size from Information Schema SELECT variable_value FROM information_schema.global_status @@ -29,6 +20,7 @@ SET SESSION innodb_strict_mode = ON; # Redundant table; 32698 bytes +# MDEV-11828 FIXME: The length must be less! CREATE TABLE t1 ( c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200), c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200), @@ -432,9 +424,9 @@ CREATE INDEX xtc1c5 ON t1 (cc(767),dc(767)); CREATE INDEX xte1e5 ON t1 (ec(767),fc(767)); UPDATE t1 SET t=@e; -# One more index and row size is too big ---replace_regex /> [0-9]*/> max_row_size/ ---error ER_TOO_BIG_ROWSIZE +# One more index and row size is too big (not any more!) +#--replace_regex /> [0-9]*/> max_row_size/ +#--error ER_TOO_BIG_ROWSIZE CREATE INDEX xt5k1f6 ON t1 (lc(767),mc(767)); SHOW CREATE TABLE t1; SHOW WARNINGS; @@ -712,12 +704,3 @@ COMMIT; drop table t2; DROP TABLE t1; -# -# restore environment to the state it was before this test execution -# - ---disable_query_log -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET SESSION innodb_strict_mode = $innodb_strict_mode_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-bug-14068765.test b/mysql-test/suite/innodb/t/innodb-bug-14068765.test index 185e8849e21..c2446e0fecf 100644 --- a/mysql-test/suite/innodb/t/innodb-bug-14068765.test +++ b/mysql-test/suite/innodb/t/innodb-bug-14068765.test @@ -1,17 +1,6 @@ -- source include/have_innodb.inc ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings let MYSQLD_DATADIR =`SELECT @@datadir`; -let $innodb_file_per_table = `SELECT @@innodb_file_per_table`; -let $innodb_file_format = `SELECT @@innodb_file_format`; - -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -#SET GLOBAL innodb_file_format = `Barracuda`; -#SELECT @@innodb_file_format; # Export/import on the same instance, with --innodb-file-per-table=1 CREATE DATABASE testdb_wl5522; @@ -68,6 +57,3 @@ SELECT COUNT(*) FROM testdb_wl5522.t1; DROP TABLE testdb_wl5522.t1; DROP DATABASE testdb_wl5522; - -eval SET GLOBAL INNODB_FILE_FORMAT=$innodb_file_format; -eval SET GLOBAL INNODB_FILE_PER_TABLE=$innodb_file_per_table; diff --git a/mysql-test/suite/innodb/t/innodb-bug-14084530.test b/mysql-test/suite/innodb/t/innodb-bug-14084530.test index 94a2d6b2252..f27fbbe31d7 100644 --- a/mysql-test/suite/innodb/t/innodb-bug-14084530.test +++ b/mysql-test/suite/innodb/t/innodb-bug-14084530.test @@ -1,15 +1,6 @@ -- source include/have_innodb.inc ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - let MYSQLD_DATADIR =`SELECT @@datadir`; -let $innodb_file_per_table = `SELECT @@innodb_file_per_table`; -let $innodb_file_format = `SELECT @@innodb_file_format`; - -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; SET AUTOCOMMIT = 0; @@ -45,8 +36,4 @@ ALTER TABLE testdb_wl5522.t1 IMPORT TABLESPACE; CHECK TABLE testdb_wl5522.t1; SELECT c1 FROM testdb_wl5522.t1; -SET AUTOCOMMIT = 1; -DROP TABLE testdb_wl5522.t1; DROP DATABASE testdb_wl5522; -eval SET GLOBAL INNODB_FILE_FORMAT=$innodb_file_format; -eval SET GLOBAL INNODB_FILE_PER_TABLE=$innodb_file_per_table; diff --git a/mysql-test/suite/innodb/t/innodb-index.test b/mysql-test/suite/innodb/t/innodb-index.test index 8598647de66..4549b3b6b47 100644 --- a/mysql-test/suite/innodb/t/innodb-index.test +++ b/mysql-test/suite/innodb/t/innodb-index.test @@ -1,15 +1,7 @@ -- source include/have_innodb.inc -let $innodb_file_format_orig=`select @@innodb_file_format`; -let $innodb_file_format_max_orig=`select @@innodb_file_format_max`; - let $MYSQLD_DATADIR= `select @@datadir`; -let $per_table=`select @@innodb_file_per_table`; -let $format=`select @@innodb_file_format`; -set global innodb_file_per_table=on; -set global innodb_file_format='Barracuda'; - SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS; # Bug#13654923 BOGUS DEBUG ASSERTION IN INDEX CREATION FOR ZERO-LENGTH RECORD @@ -336,10 +328,6 @@ explain select * from t1; explain select * from t1 order by a; drop table t1; -eval set global innodb_file_per_table=$per_table; -eval set global innodb_file_format=$format; -eval set global innodb_file_format_max=$format; - # # Test to check whether CREATE INDEX handles implicit foreign key # constraint modifications (Issue #70, Bug #38786) @@ -558,8 +546,3 @@ show create table t2c; --disable_info DROP TABLE t1,t2,t2c,t2i; - ---disable_query_log -eval SET GLOBAL innodb_file_format=$innodb_file_format_orig; -eval SET GLOBAL innodb_file_format_max=$innodb_file_format_max_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test b/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test index 51493266a60..69a632d6010 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_bzip2.test @@ -2,14 +2,7 @@ -- source include/have_innodb_bzip2.inc -- source include/not_embedded.inc ---disable_query_log let $innodb_compression_algorithm_orig=`select @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `select @@innodb_file_format`; -let $innodb_file_per_table_orig = `select @@innodb_file_per_table`; ---enable_query_log - -set global innodb_file_format = `barracuda`; -set global innodb_file_per_table = on; # bzip2 set global innodb_compression_algorithm = 5; @@ -247,6 +240,4 @@ drop table innodb_page_compressed9; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test b/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test index f36ea9684e9..1b1df674e3c 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_lz4.test @@ -2,14 +2,7 @@ -- source include/have_innodb_lz4.inc -- source include/not_embedded.inc ---disable_query_log let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -set global innodb_file_format = `barracuda`; -set global innodb_file_per_table = on; # lz4 set global innodb_compression_algorithm = 2; @@ -248,6 +241,4 @@ drop table innodb_page_compressed9; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test b/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test index 6ea686bca04..9cec3e7a947 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_lzma.test @@ -2,14 +2,7 @@ -- source include/have_innodb_lzma.inc -- source include/not_embedded.inc ---disable_query_log let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -set global innodb_file_format = `barracuda`; -set global innodb_file_per_table = on; # lzma set global innodb_compression_algorithm = 4; @@ -247,6 +240,4 @@ drop table innodb_page_compressed9; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test b/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test index 96ba18f5112..65c7e5dd3d9 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_lzo.test @@ -2,15 +2,7 @@ -- source include/have_innodb_lzo.inc -- source include/not_embedded.inc - ---disable_query_log let $innodb_compression_algorithm_orig=`select @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `select @@innodb_file_format`; -let $innodb_file_per_table_orig = `select @@innodb_file_per_table`; ---enable_query_log - -set global innodb_file_format = `barracuda`; -set global innodb_file_per_table = on; # lzo set global innodb_compression_algorithm = 3; @@ -201,6 +193,4 @@ drop table innodb_page_compressed9; # reset system --disable_query_log eval set global innodb_compression_algorithm = $innodb_compression_algorithm_orig; -eval set global innodb_file_per_table = $innodb_file_per_table_orig; -eval set global innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test b/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test index 929f547b6ac..65b626f786d 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test @@ -3,14 +3,7 @@ call mtr.add_suppression("Compression failed for space*"); ---disable_query_log let $innodb_compression_algorithm_orig=`select @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `select @@innodb_file_format`; -let $innodb_file_per_table_orig = `select @@innodb_file_per_table`; ---enable_query_log - -set global innodb_file_format = `barracuda`; -set global innodb_file_per_table = on; # snappy set global innodb_compression_algorithm = 6; @@ -248,6 +241,4 @@ drop table innodb_page_compressed9; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_tables.test b/mysql-test/suite/innodb/t/innodb-page_compression_tables.test index 3a241810bbc..be8300b39aa 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_tables.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_tables.test @@ -1,14 +1,8 @@ --source include/have_innodb.inc --source include/not_embedded.inc ---disable_query_log let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; # zlib set global innodb_compression_algorithm = 1; @@ -75,8 +69,6 @@ update innodb_dynamic set c1 = c1 + 1; select count(*) from innodb_compact where c1 < 1500000; select count(*) from innodb_dynamic where c1 < 1500000; -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; # none set global innodb_compression_algorithm = 0; @@ -112,6 +104,4 @@ SET SESSION innodb_compression_default = 0; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_zip.test b/mysql-test/suite/innodb/t/innodb-page_compression_zip.test index 67fafdb9e83..0c843314eee 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_zip.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_zip.test @@ -1,14 +1,7 @@ --source include/have_innodb.inc --source include/not_embedded.inc ---disable_query_log let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; # zlib set global innodb_compression_algorithm = 1; @@ -198,6 +191,4 @@ drop table innodb_page_compressed9; # reset system --disable_query_log EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; --enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-1.test b/mysql-test/suite/innodb/t/innodb-wl5522-1.test index 6c2607effe8..0d59df11c44 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-1.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-1.test @@ -5,30 +5,15 @@ call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - let MYSQLD_DATADIR =`SELECT @@datadir`; -let $innodb_file_per_table = `SELECT @@innodb_file_per_table`; -let $innodb_file_format = `SELECT @@innodb_file_format`; - -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -SET GLOBAL innodb_file_format = `Barracuda`; -SELECT @@innodb_file_format; - -let $MYSQLD_DATADIR = `SELECT @@datadir`; # Following testcases are created from JET cases (where import # export instance are differnt server ) # Here test will be run on same import and export instance. -DROP DATABASE IF EXISTS testdb_wl5522; CREATE DATABASE testdb_wl5522; -# case 1 +# case 1 CREATE TABLE testdb_wl5522.t1 (c1 INT ) ENGINE = Innodb; INSERT INTO testdb_wl5522.t1 VALUES (1),(123),(331); SELECT c1 FROM testdb_wl5522.t1; @@ -57,43 +42,43 @@ ALTER TABLE testdb_wl5522.t1 IMPORT TABLESPACE; SELECT * FROM testdb_wl5522.t1 ORDER BY c1; DROP TABLE testdb_wl5522.t1; -# case 2 +# case 2 CREATE TABLE testdb_wl5522.t1 ( col1 BIT(1), col2 BOOLEAN, col3 TINYINT, -col4 SMALLINT, +col4 SMALLINT, col5 MEDIUMINT, col6 INT, -col7 BIGINT, +col7 BIGINT, col8 FLOAT (14,3) , -col9 DOUBLE (14,3), -col10 VARCHAR(20), +col9 DOUBLE (14,3), +col10 VARCHAR(20), col11 TEXT , col12 ENUM('a','b','c'), col13 TEXT, -col14 CHAR(20) , -col15 VARBINARY (400) , -col16 BINARY(40), -col17 BLOB (400) , +col14 CHAR(20), +col15 VARBINARY (400), +col16 BINARY(40), +col17 BLOB (400), col18 INT NOT NULL PRIMARY KEY, -col19 DATE , -col20 DATETIME , -col21 TIMESTAMP , -col22 TIME , +col19 DATE, +col20 DATETIME, +col21 TIMESTAMP, +col22 TIME, col23 YEAR ) ENGINE = Innodb; CREATE INDEX idx1 ON testdb_wl5522.t1(col18); CREATE INDEX prefix_idx ON testdb_wl5522.t1(col14 (10)); CREATE UNIQUE INDEX idx2 ON testdb_wl5522.t1(col12); CREATE UNIQUE INDEX idx3 ON testdb_wl5522.t1(col8); -INSERT INTO testdb_wl5522.t1 VALUES +INSERT INTO testdb_wl5522.t1 VALUES (1,1,-128,32767,-8388608,2147483647,-9223372036854775808, 92233720368.222, -92233720368.222,'aaa', + 'aaaaaaaaaa','b','bbbbb','ccccc', REPEAT('d',40),REPEAT('d',40),REPEAT('d',40),1,'1000-01-01', '3000-12-31 23:59:59.99','1990-01-01 00:00:01.00', '01:59:59.00','1901'); -INSERT INTO testdb_wl5522.t1 VALUES +INSERT INTO testdb_wl5522.t1 VALUES (NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL,NULL,NULL,3,NULL,NULL,NULL,NULL,NULL); --error 1048 @@ -136,7 +121,7 @@ col18 INT NOT NULL PRIMARY KEY, col19 DATE , col20 DATETIME , col21 TIMESTAMP , -col22 TIME , +col22 TIME, col23 YEAR ) ENGINE = Innodb; CREATE INDEX idx1 ON testdb_wl5522.t1(col18); @@ -162,8 +147,6 @@ DROP TABLE testdb_wl5522.t1; # case 3 - with blob objects -SET GLOBAL innodb_file_format='Barracuda'; - CREATE TABLE testdb_wl5522.t1 ( col_1_varbinary VARBINARY (4000) , col_2_varchar VARCHAR (4000), @@ -178,13 +161,13 @@ INSERT INTO testdb_wl5522.t1 VALUES( REPEAT('a', 4000),REPEAT('o', 4000),REPEAT('a', 4000), REPEAT('o', 4000), REPEAT('a', 4000),REPEAT('a', 4000),REPEAT('a', 255)); -SELECT col_1_varbinary = REPEAT("a", 4000) , +SELECT col_1_varbinary = REPEAT("a", 4000), col_2_varchar = REPEAT("o", 4000) , col_3_text = REPEAT("a", 4000) , col_4_blob = REPEAT("o", 4000) , col_5_text = REPEAT("a", 4000) , col_6_varchar = REPEAT("a", 4000) , -col_7_binary = REPEAT("a", 255) +col_7_binary = REPEAT("a", 255) FROM testdb_wl5522.t1; FLUSH TABLES testdb_wl5522.t1 FOR EXPORT; @@ -223,7 +206,7 @@ col_3_text = REPEAT("a", 4000) , col_4_blob = REPEAT("o", 4000) , col_5_text = REPEAT("a", 4000) , col_6_varchar = REPEAT("a", 4000) , -col_7_binary = REPEAT("a", 255) +col_7_binary = REPEAT("a", 255) FROM testdb_wl5522.t1; DROP TABLE testdb_wl5522.t1; @@ -231,7 +214,7 @@ DROP TABLE testdb_wl5522.t1; # case 4 - trasportable tablesace with autoincrement CREATE TABLE testdb_wl5522.t1 ( col_1_int INT AUTO_INCREMENT, -col_2_varchar VARCHAR (20), +col_2_varchar VARCHAR (20), PRIMARY KEY (col_1_int)) ENGINE = Innodb; INSERT INTO testdb_wl5522.t1 VALUES (1,'a1'),(2,'a2'),(3,'a3'); @@ -268,7 +251,7 @@ SELECT * FROM testdb_wl5522.t1 ORDER BY col_1_int; # error on inserting duplicate value --error 1062 INSERT INTO testdb_wl5522.t1 VALUES (1,'a1'); -# insert new values +# insert new values INSERT INTO testdb_wl5522.t1(col_2_varchar) VALUES ('a101'),('a102'),('a103'); SELECT * FROM testdb_wl5522.t1 ORDER BY col_1_int; # check table can be altered @@ -284,7 +267,7 @@ PRIMARY KEY (col_2_varchar)) ENGINE = Innodb; CREATE TABLE testdb_wl5522.t1_fk ( col_1_int INT,col_2_varchar VARCHAR (20), -PRIMARY KEY (col_1_int), +PRIMARY KEY (col_1_int), FOREIGN KEY (col_2_varchar) REFERENCES testdb_wl5522.t1(col_2_varchar) ) ENGINE = Innodb; @@ -452,7 +435,7 @@ UNLOCK TABLES; DROP TABLE testdb_wl5522.t1; -# create table with incorrect schema +# create table with incorrect schema CREATE TABLE testdb_wl5522.t1 ( i bigint) ENGINE = Innodb; ALTER TABLE testdb_wl5522.t1 DISCARD TABLESPACE; @@ -820,14 +803,14 @@ SET AUTOCOMMIT = 1; CREATE TABLE testdb_wl5522.t1(col1 bit(1) , col2 boolean,col3 tinyint , col4 smallint , -col5 mediumint ,col6 int , col7 bigint , +col5 mediumint ,col6 int , col7 bigint , col8 float (14,3) ,col9 double (14,3), col10 VARCHAR(20) CHARACTER SET utf8 , col11 TEXT CHARACTER SET binary , col12 ENUM('a','b','c') CHARACTER SET binary, col13 TEXT CHARACTER SET latin1 COLLATE latin1_general_cs , col14 CHAR(20) , col15 VARBINARY (400), -col16 BINARY(40), col17 BLOB (400), +col16 BINARY(40), col17 BLOB (400), col18 int not null primary key, col19 DATE ,col20 DATETIME , col21 TIMESTAMP , col22 TIME , col23 YEAR ) ENGINE = Innodb; @@ -835,7 +818,7 @@ col22 TIME , col23 YEAR ) ENGINE = Innodb; # table for trigger action CREATE TABLE testdb_wl5522.trigger_table ( i int ) ENGINE = Innodb; # define trigger -CREATE TRIGGER testdb_wl5522.tri AFTER INSERT ON testdb_wl5522.t1 +CREATE TRIGGER testdb_wl5522.tri AFTER INSERT ON testdb_wl5522.t1 FOR EACH ROW INSERT INTO testdb_wl5522.trigger_table VALUES(NEW.col18); # define view CREATE OR REPLACE VIEW testdb_wl5522.VW1 AS SELECT * FROM testdb_wl5522.t1; @@ -917,7 +900,7 @@ SELECT COUNT(*) FROM testdb_wl5522.t1; SELECT * FROM testdb_wl5522.trigger_table; SELECT COUNT(*) FROM testdb_wl5522.VW1; -# trigger table is not updated as trigger got dropped +# trigger table is not updated as trigger got dropped INSERT INTO testdb_wl5522.t1(col18) VALUES (5); # validate data in table not updated SELECT * FROM testdb_wl5522.trigger_table; @@ -949,6 +932,3 @@ call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tabl --remove_file $MYSQLTEST_VARDIR/tmp/t1.ibd --remove_file $MYSQLTEST_VARDIR/tmp/t1_fk.cfg --remove_file $MYSQLTEST_VARDIR/tmp/t1_fk.ibd - -eval SET GLOBAL INNODB_FILE_FORMAT=$innodb_file_format; -eval SET GLOBAL INNODB_FILE_PER_TABLE=$innodb_file_per_table; diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test b/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test index 1f15c81b90b..3b71bd802ef 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-debug-zip.test @@ -26,23 +26,10 @@ call mtr.add_suppression("InnoDB: Page for tablespace .* "); flush tables; let MYSQLD_DATADIR =`SELECT @@datadir`; -let $innodb_file_per_table = `SELECT @@innodb_file_per_table`; -let $innodb_file_format = `SELECT @@innodb_file_format`; -let $innodb_strict_mode_orig=`select @@session.innodb_strict_mode`; let $pathfix=/: '.*test_wl5522.*t1.ibd'/: 'test_wl5522_t1.ibd'/; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -SET GLOBAL innodb_file_format = `Barracuda`; -SELECT @@innodb_file_format; - SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; - - -DROP DATABASE IF EXISTS test_wl5522; CREATE DATABASE test_wl5522; # Create the table that we will use for crash recovery (during IMPORT) @@ -140,14 +127,7 @@ SET SESSION debug_dbug="-d,ib_import_before_checkpoint_crash"; DROP TABLE test_wl5522.t1; -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -SET GLOBAL innodb_file_format = `Barracuda`; -SELECT @@innodb_file_format; - SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; CREATE TABLE test_wl5522.t1 (c1 INT) ENGINE = Innodb ROW_FORMAT=COMPRESSED; @@ -755,7 +735,3 @@ call mtr.add_suppression("Could not find a valid tablespace file for 'test_wl552 #cleanup --remove_file $MYSQLTEST_VARDIR/tmp/t1.cfg --remove_file $MYSQLTEST_VARDIR/tmp/t1.ibd - -eval SET GLOBAL INNODB_FILE_PER_TABLE=$innodb_file_per_table; -eval SET GLOBAL INNODB_FILE_FORMAT=$innodb_file_format; -eval SET SESSION innodb_strict_mode=$innodb_strict_mode_orig; diff --git a/mysql-test/suite/innodb/t/innodb-wl5522-zip.test b/mysql-test/suite/innodb/t/innodb-wl5522-zip.test index 395e4def85d..4181b52573c 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522-zip.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522-zip.test @@ -9,22 +9,7 @@ call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -let $innodb_file_per_table = `SELECT @@innodb_file_per_table`; -let $innodb_file_format = `SELECT @@innodb_file_format`; -let $innodb_strict_mode_orig=`select @@session.innodb_strict_mode`; - -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -SET GLOBAL innodb_file_format = `Barracuda`; -SELECT @@innodb_file_format; - SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; let $MYSQLD_TMPDIR = `SELECT @@tmpdir`; let $MYSQLD_DATADIR = `SELECT @@datadir`; @@ -87,15 +72,8 @@ DROP TABLE t1; --remove_file $MYSQLD_TMPDIR/t1.cfg --remove_file $MYSQLD_TMPDIR/t1.ibd -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -SET GLOBAL innodb_file_format = `Barracuda`; -SELECT @@innodb_file_format; - # restore session variable SET SESSION innodb_strict_mode=1; -SELECT @@SESSION.innodb_strict_mode; let MYSQLD_DATADIR =`SELECT @@datadir`; @@ -218,7 +196,7 @@ DROP TABLE t1; # table and restore, this time the table has a secondary index too. CREATE TABLE t1( c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - c2 INT, INDEX(c2)) ENGINE=InnoDB + c2 INT, INDEX(c2)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; INSERT INTO t1(c2) VALUES(1); @@ -540,7 +518,3 @@ call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tabl # cleanup --remove_file $MYSQLTEST_VARDIR/tmp/t1.cfg --remove_file $MYSQLTEST_VARDIR/tmp/t1.ibd - -eval SET GLOBAL INNODB_FILE_FORMAT=$innodb_file_format; -eval SET GLOBAL INNODB_FILE_PER_TABLE=$innodb_file_per_table; -eval SET SESSION innodb_strict_mode=$innodb_strict_mode_orig; diff --git a/mysql-test/suite/innodb/t/innodb-wl5522.test b/mysql-test/suite/innodb/t/innodb-wl5522.test index b04c726b74a..138e02e1214 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522.test @@ -5,19 +5,6 @@ call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -let $innodb_file_per_table = `SELECT @@innodb_file_per_table`; -let $innodb_file_format = `SELECT @@innodb_file_format`; - -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -SET GLOBAL innodb_file_format = `Barracuda`; -SELECT @@innodb_file_format; - let $MYSQLD_TMPDIR = `SELECT @@tmpdir`; let $MYSQLD_DATADIR = `SELECT @@datadir`; @@ -80,12 +67,6 @@ DROP TABLE t1; --remove_file $MYSQLD_TMPDIR/t1.cfg --remove_file $MYSQLD_TMPDIR/t1.ibd -SET GLOBAL innodb_file_per_table = 1; -SELECT @@innodb_file_per_table; - -SET GLOBAL innodb_file_format = `Barracuda`; -SELECT @@innodb_file_format; - let MYSQLD_DATADIR =`SELECT @@datadir`; # Try importing when tablespace already exists @@ -881,6 +862,3 @@ call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tabl # cleanup --remove_file $MYSQLTEST_VARDIR/tmp/t1.cfg --remove_file $MYSQLTEST_VARDIR/tmp/t1.ibd - -eval SET GLOBAL INNODB_FILE_FORMAT=$innodb_file_format; -eval SET GLOBAL INNODB_FILE_PER_TABLE=$innodb_file_per_table; diff --git a/mysql-test/suite/innodb/t/innodb_blob_truncate.test b/mysql-test/suite/innodb/t/innodb_blob_truncate.test index 8a4248c795e..3e54ec80e2b 100644 --- a/mysql-test/suite/innodb/t/innodb_blob_truncate.test +++ b/mysql-test/suite/innodb/t/innodb_blob_truncate.test @@ -1,14 +1,6 @@ --source include/have_innodb.inc --source include/have_innodb_16k.inc ---disable_query_log -let $innodb_file_format_orig = `SELECT @@innodb_file_format`; -let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`; ---enable_query_log - -SET GLOBAL innodb_file_format = `Barracuda`; -SET GLOBAL innodb_file_per_table = ON; - create table t1(a blob) engine=innodb key_block_size=8; delimiter //; create function generate_blob() @@ -38,8 +30,3 @@ if ($x) { } drop table t1; drop function generate_blob; - ---disable_query_log -EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig; -EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig; ---enable_query_log diff --git a/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test b/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test index adae10df2ad..7fb4037e6bb 100644 --- a/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test +++ b/mysql-test/suite/innodb/t/innodb_prefix_index_restart_server.test @@ -16,20 +16,10 @@ # which is not there with embedded mode --source include/not_embedded.inc # Save innodb variables -let $innodb_file_format_orig=`select @@innodb_file_format`; -let $innodb_file_per_table_orig=`select @@innodb_file_per_table`; let $innodb_large_prefix_orig=`select @@innodb_large_prefix`; -# Set Innodb file format as feature works for Barracuda file format -set global innodb_file_format="Barracuda"; -set global innodb_file_per_table=1; set global innodb_large_prefix=1; --- disable_warnings -DROP TABLE IF EXISTS worklog5743; --- enable_warnings - - #------------------------------------------------------------------------------ # Stop the server in between when prefix index are created and see if state is # correct when server is restarted. @@ -111,6 +101,4 @@ DROP TABLE worklog5743; #------------------------------------------------------------------------------ -eval SET GLOBAL innodb_file_format=$innodb_file_format_orig; -eval SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig; eval SET GLOBAL innodb_large_prefix=$innodb_large_prefix_orig; diff --git a/mysql-test/suite/innodb_zip/include/innodb_wl6501_crash_stripped.inc b/mysql-test/suite/innodb_zip/include/innodb_wl6501_crash_stripped.inc deleted file mode 100644 index fcefd0cdf7e..00000000000 --- a/mysql-test/suite/innodb_zip/include/innodb_wl6501_crash_stripped.inc +++ /dev/null @@ -1,144 +0,0 @@ -# -# WL#6501: make truncate table atomic -# - ---source include/have_innodb.inc ---source include/have_debug.inc - -# Valgrind would complain about memory leaks when we crash on purpose. ---source include/not_valgrind.inc -# Embedded server does not support crashing ---source include/not_embedded.inc -# Avoid CrashReporter popup on Mac ---source include/not_crashrep.inc - -# suppress expected warnings. -call mtr.add_suppression("The file '.*' already exists though the corresponding table did not exist in the InnoDB data dictionary"); -call mtr.add_suppression("Cannot create file '.*'"); -call mtr.add_suppression("InnoDB: Error number 17 means 'File exists'"); - -################################################################################ -# -# Will test following scenarios: -# 1. Hit crash point on completing drop of all indexes before creation of index -# is commenced. -# 2. Hit crash point after data is updated to system-table and in-memory dict. -# 3. Post truncate recovery, abruptly shutdown the server. -# On restart ensure table state is maintained. -# -################################################################################ - -#----------------------------------------------------------------------------- -# -# create test-bed -# - -let $WL6501_TMP_DIR = `select @@tmpdir`; -let $WL6501_DATA_DIR = `select @@datadir`; -let SEARCH_FILE = $MYSQLTEST_VARDIR/log/my_restart.err; - -#----------------------------------------------------------------------------- -# -# 1. Hit crash point on completing drop of all indexes before creation of index -# is commenced. -# ---echo "1. Hit crash point on completing drop of all indexes before creation" ---echo " of index is commenced." -eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; -set innodb_strict_mode=off; ---disable_warnings -eval create $wl6501_temp table t ( - i int, f float, c char, - primary key pk(i), unique findex(f), index ck(c)) - engine = innodb row_format = $wl6501_row_fmt - key_block_size = $wl6501_kbs; ---enable_warnings -insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); -select * from t; -check table t; -# -set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; ---source include/expect_crash.inc ---error 2013 -truncate table t; -# ---source include/start_mysqld.inc - -check table t; -select * from t; -insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); -select * from t; -select * from t where f < 2.5; -drop table t; - -#----------------------------------------------------------------------------- -# -# 2. Hit crash point after data is updated to system-table and in-memory dict. -# ---echo "2. Hit crash point after data is updated to system-table and" ---echo " in-memory dict." -eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; -set innodb_strict_mode=off; ---disable_warnings -eval create $wl6501_temp table t ( - i int, f float, c char, - primary key pk(i), unique findex(f), index ck(c)) - engine = innodb row_format = $wl6501_row_fmt - key_block_size = $wl6501_kbs; ---enable_warnings -insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); -select * from t; -check table t; -# -set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; ---source include/expect_crash.inc ---error 2013 -truncate table t; -# ---source include/start_mysqld.inc -check table t; -select * from t; -insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); -select * from t; -select * from t where f < 2.5; -drop table t; - -#----------------------------------------------------------------------------- -# -# 3. Post truncate recovery, abruptly shutdown the server. -# On restart ensure table state is maintained. -# ---echo "3. Post truncate recovery, abruptly shutdown the server." ---echo " On restart ensure table state is maintained." -eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; -set innodb_strict_mode=off; ---disable_warnings -eval create $wl6501_temp table t ( - i int, f float, c char, - primary key pk(i), unique findex(f), index ck(c)) - engine = innodb row_format = $wl6501_row_fmt - key_block_size = $wl6501_kbs; ---enable_warnings -insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); -select * from t; -check table t; -# -set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; ---source include/expect_crash.inc ---error 2013 -truncate table t; -# ---source include/start_mysqld.inc -check table t; -select * from t; -insert into t values (1, 1.1, 'a'), (2, 2.2, 'b'), (3, 3.3, 'c'); -# ---source include/kill_and_restart_mysqld.inc -# -check table t; -select * from t; -select * from t where f < 2.5; -drop table t; diff --git a/mysql-test/suite/innodb_zip/include/innodb_wl6501_error.inc b/mysql-test/suite/innodb_zip/include/innodb_wl6501_error.inc index 0939d452dae..424608f251b 100644 --- a/mysql-test/suite/innodb_zip/include/innodb_wl6501_error.inc +++ b/mysql-test/suite/innodb_zip/include/innodb_wl6501_error.inc @@ -44,7 +44,6 @@ set innodb_strict_mode=off; # --echo "1. Error in assigning undo logs for truncate action." eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --disable_warnings eval create $wl6501_temp table t ( i int, f float, c char, @@ -71,7 +70,6 @@ drop table t; # --echo "2. Error while preparing for truncate." eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --disable_warnings eval create $wl6501_temp table t ( i int, f float, c char, @@ -98,7 +96,6 @@ drop table t; # --echo "3. Error while dropping/creating indexes" eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --disable_warnings eval create $wl6501_temp table t ( i int, f float, c char, @@ -122,7 +119,6 @@ drop table t; # # eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --disable_warnings eval create $wl6501_temp table t ( i int, f float, c char, @@ -146,7 +142,6 @@ drop table t; # # eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --disable_warnings eval create temporary table t ( i int, f float, c char, @@ -174,7 +169,6 @@ drop table t; # --echo "4. Error while completing truncate of table involving FTS." eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --disable_warnings eval create $wl6501_temp table t (i int, f float, c char(100), primary key pk(i), index fk(f), fulltext index ck(c)) @@ -203,7 +197,6 @@ drop table t; # --echo "5. Error while updating sys-tables." eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --disable_warnings eval create $wl6501_temp table t (i int, f float, c char(100), primary key pk(i), index fk(f), fulltext index ck(c)) @@ -230,5 +223,4 @@ drop table t; # # remove test-bed # -eval set global innodb_file_format = $format; eval set global innodb_file_per_table = $per_table; diff --git a/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc b/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc index 67569d3dae9..bef28a9c484 100644 --- a/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc +++ b/mysql-test/suite/innodb_zip/include/innodb_wl6501_scale.inc @@ -45,7 +45,6 @@ delimiter ;| # create and load the tables. # eval set global innodb_file_per_table = $wl6501_file_per_table; -eval set global innodb_file_format = $wl6501_file_format; --replace_regex /[0-9]+/NUMBER/ eval create table t1 (i int, c1 char(100), c2 char(100), diff --git a/mysql-test/suite/innodb_zip/r/innodb_bug36169.result b/mysql-test/suite/innodb_zip/r/innodb_bug36169.result index 161cef10ad5..bae08bd54a2 100644 --- a/mysql-test/suite/innodb_zip/r/innodb_bug36169.result +++ b/mysql-test/suite/innodb_zip/r/innodb_bug36169.result @@ -1,5 +1 @@ call mtr.add_suppression("Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size .* for a record on index leaf page."); -SET GLOBAL innodb_file_format='Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=ON; diff --git a/mysql-test/suite/innodb_zip/r/innodb_bug52745.result b/mysql-test/suite/innodb_zip/r/innodb_bug52745.result index 5ba26753ea6..7ae3cc4bb71 100644 --- a/mysql-test/suite/innodb_zip/r/innodb_bug52745.result +++ b/mysql-test/suite/innodb_zip/r/innodb_bug52745.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format='Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=on; CREATE TABLE bug52745 ( a2 int(10) unsigned DEFAULT NULL, col37 time DEFAULT NULL, @@ -128,7 +124,3 @@ Warning 1264 Out of range value for column 'col78' at row 1 Warning 1265 Data truncated for column 'col79' at row 1 Warning 1264 Out of range value for column 'col84' at row 1 DROP TABLE bug52745; -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=1; diff --git a/mysql-test/suite/innodb_zip/r/innodb_bug53591.result b/mysql-test/suite/innodb_zip/r/innodb_bug53591.result index 3b10942c2de..0222ad64fa2 100644 --- a/mysql-test/suite/innodb_zip/r/innodb_bug53591.result +++ b/mysql-test/suite/innodb_zip/r/innodb_bug53591.result @@ -1,7 +1,3 @@ -SET GLOBAL innodb_file_format='Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=on; SET GLOBAL innodb_strict_mode=on; set old_alter_table=0; CREATE TABLE bug53591(a text charset utf8 not null) @@ -12,8 +8,4 @@ SHOW WARNINGS; Level Code Message Error 1118 Row size too large. The maximum row size for the used table type, not counting BLOBs, is {checked_valid}. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs DROP TABLE bug53591; -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=1; SET GLOBAL innodb_strict_mode=DEFAULT; diff --git a/mysql-test/suite/innodb_zip/r/innodb_bug56680.result b/mysql-test/suite/innodb_zip/r/innodb_bug56680.result index 92b589c6b7e..c509c5bad21 100644 --- a/mysql-test/suite/innodb_zip/r/innodb_bug56680.result +++ b/mysql-test/suite/innodb_zip/r/innodb_bug56680.result @@ -1,8 +1,4 @@ SET GLOBAL tx_isolation='REPEATABLE-READ'; -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=on; CREATE TABLE bug56680( a INT AUTO_INCREMENT PRIMARY KEY, b CHAR(1), @@ -121,5 +117,3 @@ Table Op Msg_type Msg_text test.bug56680_2 check status OK DROP TABLE bug56680_2; DROP TABLE bug56680; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html diff --git a/mysql-test/suite/innodb_zip/r/innodb_index_large_prefix.result b/mysql-test/suite/innodb_zip/r/innodb_index_large_prefix.result index d44c7e33fe3..b599716905d 100644 --- a/mysql-test/suite/innodb_zip/r/innodb_index_large_prefix.result +++ b/mysql-test/suite/innodb_zip/r/innodb_index_large_prefix.result @@ -1,9 +1,5 @@ SET default_storage_engine=InnoDB; call mtr.add_suppression("Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size (.*) for a record on index leaf page."); -set global innodb_file_format="Barracuda"; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table=1; set global innodb_large_prefix=1; Warnings: Warning 131 Using innodb_large_prefix is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html @@ -491,6 +487,7 @@ connection con1; select a = repeat("a", 20000) from worklog5743; a = repeat("a", 20000) 1 +disconnect con1; connection con2; SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; select @@session.tx_isolation; @@ -500,6 +497,7 @@ select a = repeat("x", 25000) from worklog5743; a = repeat("x", 25000) 1 1 +disconnect con2; connection default; rollback; drop table worklog5743; @@ -529,16 +527,7 @@ create index idx on worklog5743(a(768)); ERROR HY000: Index column size too large. The maximum column size is 767 bytes create index idx2 on worklog5743(a(767)); drop table worklog5743; -SET GLOBAL innodb_file_format=Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -SET GLOBAL innodb_file_per_table=1; SET GLOBAL innodb_large_prefix=1; Warnings: Warning 131 Using innodb_large_prefix is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET GLOBAL innodb_strict_mode = DEFAULT; -connection con1; -disconnect con1; -connection con2; -disconnect con2; -connection default; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result index e874ab1a37a..554bb2892f6 100644 --- a/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_3.result @@ -5,9 +5,6 @@ set global innodb_file_per_table = on; "1. Hit crash point while writing redo log." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -44,9 +41,6 @@ drop table t; "2. Hit crash point on completion of redo log write." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -86,9 +80,6 @@ drop table t; "3. Hit crash point while dropping indexes." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -127,9 +118,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -168,9 +156,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -211,9 +196,6 @@ drop table t; " of index is commenced." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -253,9 +235,6 @@ drop table t; "5. Hit crash point while creating indexes." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -294,9 +273,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -335,9 +311,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -378,9 +351,6 @@ drop table t; " in-memory dict." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -420,9 +390,6 @@ drop table t; "7. Hit crash point before/after log checkpoint is done." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -456,9 +423,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -495,7 +459,4 @@ i f c 1 1.1 a 2 2.2 b drop table t; -set global innodb_file_format = Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result index cb8a4d5a157..1a02c1a711a 100644 --- a/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_4.result @@ -5,9 +5,6 @@ set global innodb_file_per_table = on; "1. Hit crash point while writing redo log." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -24,9 +21,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -43,9 +41,6 @@ drop table t; "2. Hit crash point on completion of redo log write." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -62,9 +57,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -84,9 +80,6 @@ drop table t; "3. Hit crash point while dropping indexes." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -103,9 +96,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -124,9 +118,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -143,9 +134,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -164,9 +156,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -183,9 +172,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -206,9 +196,6 @@ drop table t; " of index is commenced." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -225,9 +212,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -247,9 +235,6 @@ drop table t; "5. Hit crash point while creating indexes." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -266,9 +251,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -287,9 +273,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -306,9 +289,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -327,9 +311,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -346,9 +327,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -369,9 +351,6 @@ drop table t; " in-memory dict." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -388,9 +367,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -410,9 +390,6 @@ drop table t; "7. Hit crash point before/after log checkpoint is done." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -429,9 +406,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -445,9 +423,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -464,9 +439,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -483,18 +459,16 @@ i f c 1 1.1 a 2 2.2 b drop table t; -set global innodb_file_format = Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; call mtr.add_suppression("does not exist in the InnoDB internal"); +Warnings: +Error 145 Table './mtr/test_suppressions' is marked as crashed and should be repaired +Error 1194 Table 'test_suppressions' is marked as crashed and should be repaired +Error 1034 1 client is using or hasn't closed the table properly set global innodb_file_per_table = on; "1. Hit crash point on completing drop of all indexes before creation" " of index is commenced." set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set innodb_strict_mode=off; create temporary table t ( i int, f float, c char, @@ -511,9 +485,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check Error Table 'test.t' doesn't exist @@ -521,9 +496,6 @@ test.t check status Operation failed "2. Hit crash point after data is updated to system-table and" " in-memory dict." set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set innodb_strict_mode=off; create temporary table t ( i int, f float, c char, @@ -540,14 +512,11 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check Error Table 'test.t' doesn't exist test.t check status Operation failed -set global innodb_file_format = Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html -set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result b/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result index 74f1e9dd1ad..b5fea6382ff 100644 --- a/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result +++ b/mysql-test/suite/innodb_zip/r/wl6501_crash_5.result @@ -5,9 +5,6 @@ set global innodb_file_per_table = on; "1. Hit crash point while writing redo log." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -24,9 +21,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_while_writing_redo_log"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -43,9 +41,6 @@ drop table t; "2. Hit crash point on completion of redo log write." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -62,9 +57,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_after_redo_log_write_complete"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -84,9 +80,6 @@ drop table t; "3. Hit crash point while dropping indexes." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -103,9 +96,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_drop_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -124,9 +118,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -143,9 +134,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_drop_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -164,9 +156,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -183,9 +172,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_drop_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -206,9 +196,6 @@ drop table t; " of index is commenced." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -225,9 +212,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_drop_reinit_done_create_to_start"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -247,9 +235,6 @@ drop table t; "5. Hit crash point while creating indexes." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -266,9 +251,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_create_of_clust_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -287,9 +273,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -306,9 +289,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_create_of_uniq_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -327,9 +311,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -346,9 +327,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_create_of_sec_index"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -369,9 +351,6 @@ drop table t; " in-memory dict." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -388,9 +367,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_on_updating_dict_sys_info"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -410,9 +390,6 @@ drop table t; "7. Hit crash point before/after log checkpoint is done." use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -429,9 +406,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_before_log_removal"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -445,9 +423,6 @@ i f c drop table t; use test; set global innodb_file_per_table = 1; -set global innodb_file_format = 'Barracuda'; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SET innodb_strict_mode=OFF; create table t ( i int, f float, c char, @@ -464,9 +439,10 @@ check table t; Table Op Msg_type Msg_text test.t check status OK set session debug = "+d,ib_trunc_crash_after_truncate_done"; +Warnings: +Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead truncate table t; ERROR HY000: Lost connection to MySQL server during query -# restart check table t; Table Op Msg_type Msg_text test.t check status OK @@ -483,7 +459,4 @@ i f c 1 1.1 a 2 2.2 b drop table t; -set global innodb_file_format = Barracuda; -Warnings: -Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result index 72fdceab7e4..0064cf2a469 100644 --- a/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result +++ b/mysql-test/suite/innodb_zip/r/wl6501_scale_1.result @@ -41,6 +41,7 @@ engine=innodb row_format=compact key_block_size=16; Warnings: Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. select count(*) from t1; count(*) 0 @@ -63,8 +64,6 @@ select count(*) from t3; count(*) 5000 truncate table t1; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16 unless ROW_FORMAT=COMPRESSED. select count(*) from t1; count(*) 0 @@ -85,12 +84,7 @@ select count(*) from t3; count(*) 7000 truncate table t2; -Warnings: -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16 unless ROW_FORMAT=COMPRESSED. -# WL#7811/WL#7743/WL#7141 TODO: Remove the warnings! truncate table t3; -Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. select count(*) from t1; count(*) 2000 @@ -115,6 +109,9 @@ drop table t2; drop table t3; drop procedure populate; drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; set innodb_strict_mode=OFF; create procedure populate() @@ -155,6 +152,7 @@ engine=innodb row_format=compressed key_block_size=16; Warnings: Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. select count(*) from t1; @@ -199,12 +197,7 @@ select count(*) from t3; count(*) 7000 truncate table t2; -# WL#7811/WL#7743/WL#7141 TODO: Remove the warnings! truncate table t3; -Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. -Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY TABLE. -Warning 1478 InnoDB: assuming ROW_FORMAT=DYNAMIC. select count(*) from t1; count(*) 2000 @@ -229,6 +222,9 @@ drop table t2; drop table t3; drop procedure populate; drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; set innodb_strict_mode=OFF; create procedure populate() @@ -275,6 +271,7 @@ engine=innodb row_format=compact key_block_size=16; Warnings: Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. +Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. select count(*) from t1; count(*) 0 @@ -297,9 +294,6 @@ select count(*) from t3; count(*) 5000 truncate table t1; -Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. select count(*) from t1; count(*) 0 @@ -320,13 +314,7 @@ select count(*) from t3; count(*) 7000 truncate table t2; -Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. -Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=16. -# WL#7811/WL#7743/WL#7141 TODO: Remove the warnings! truncate table t3; -Warnings: -Warning 1478 InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE. select count(*) from t1; count(*) 2000 @@ -351,4 +339,7 @@ drop table t2; drop table t3; drop procedure populate; drop procedure populate_small; +set global innodb_file_format = Barracuda; +Warnings: +Warning 131 Using innodb_file_format is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html set global innodb_file_per_table = 1; diff --git a/mysql-test/suite/innodb_zip/t/innodb_bug36169.test b/mysql-test/suite/innodb_zip/t/innodb_bug36169.test index 1d82b95a602..93051d56639 100644 --- a/mysql-test/suite/innodb_zip/t/innodb_bug36169.test +++ b/mysql-test/suite/innodb_zip/t/innodb_bug36169.test @@ -6,11 +6,6 @@ call mtr.add_suppression("Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size .* for a record on index leaf page."); -let $file_format=`select @@innodb_file_format`; -let $file_per_table=`select @@innodb_file_per_table`; -SET GLOBAL innodb_file_format='Barracuda'; -SET GLOBAL innodb_file_per_table=ON; - # # The following is copied from http://bugs.mysql.com/36169 # (http://bugs.mysql.com/file.php?id=9121) @@ -1156,6 +1151,3 @@ DROP TABLE IF EXISTS table3; DROP TABLE IF EXISTS table4; DROP TABLE IF EXISTS table5; DROP TABLE IF EXISTS table6; - -EVAL SET GLOBAL innodb_file_format=$file_format; -EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/suite/innodb_zip/t/innodb_bug36172.test b/mysql-test/suite/innodb_zip/t/innodb_bug36172.test index 015f461e532..622e0c56b15 100644 --- a/mysql-test/suite/innodb_zip/t/innodb_bug36172.test +++ b/mysql-test/suite/innodb_zip/t/innodb_bug36172.test @@ -14,17 +14,9 @@ SET storage_engine=InnoDB; -- disable_query_log -- disable_result_log -let $file_format=`select @@innodb_file_format`; -let $file_per_table=`select @@innodb_file_per_table`; -SET GLOBAL innodb_file_format='Barracuda'; -SET GLOBAL innodb_file_per_table=on; - -DROP TABLE IF EXISTS `table0`; CREATE TABLE `table0` ( `col0` tinyint(1) DEFAULT NULL, `col1` tinyint(1) DEFAULT NULL, `col2` tinyint(4) DEFAULT NULL, `col3` date DEFAULT NULL, `col4` time DEFAULT NULL, `col5` set('test1','test2','test3') DEFAULT NULL, `col6` time DEFAULT NULL, `col7` text, `col8` decimal(10,0) DEFAULT NULL, `col9` set('test1','test2','test3') DEFAULT NULL, `col10` float DEFAULT NULL, `col11` double DEFAULT NULL, `col12` enum('test1','test2','test3') DEFAULT NULL, `col13` tinyblob, `col14` year(4) DEFAULT NULL, `col15` set('test1','test2','test3') DEFAULT NULL, `col16` decimal(10,0) DEFAULT NULL, `col17` decimal(10,0) DEFAULT NULL, `col18` blob, `col19` datetime DEFAULT NULL, `col20` double DEFAULT NULL, `col21` decimal(10,0) DEFAULT NULL, `col22` datetime DEFAULT NULL, `col23` decimal(10,0) DEFAULT NULL, `col24` decimal(10,0) DEFAULT NULL, `col25` longtext, `col26` tinyblob, `col27` time DEFAULT NULL, `col28` tinyblob, `col29` enum('test1','test2','test3') DEFAULT NULL, `col30` smallint(6) DEFAULT NULL, `col31` double DEFAULT NULL, `col32` float DEFAULT NULL, `col33` char(175) DEFAULT NULL, `col34` tinytext, `col35` tinytext, `col36` tinyblob, `col37` tinyblob, `col38` tinytext, `col39` mediumblob, `col40` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `col41` double DEFAULT NULL, `col42` smallint(6) DEFAULT NULL, `col43` longblob, `col44` varchar(80) DEFAULT NULL, `col45` mediumtext, `col46` decimal(10,0) DEFAULT NULL, `col47` bigint(20) DEFAULT NULL, `col48` date DEFAULT NULL, `col49` tinyblob, `col50` date DEFAULT NULL, `col51` tinyint(1) DEFAULT NULL, `col52` mediumint(9) DEFAULT NULL, `col53` float DEFAULT NULL, `col54` tinyblob, `col55` longtext, `col56` smallint(6) DEFAULT NULL, `col57` enum('test1','test2','test3') DEFAULT NULL, `col58` datetime DEFAULT NULL, `col59` mediumtext, `col60` varchar(232) DEFAULT NULL, `col61` decimal(10,0) DEFAULT NULL, `col62` year(4) DEFAULT NULL, `col63` smallint(6) DEFAULT NULL, `col64` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `col65` blob, `col66` longblob, `col67` int(11) DEFAULT NULL, `col68` longtext, `col69` enum('test1','test2','test3') DEFAULT NULL, `col70` int(11) DEFAULT NULL, `col71` time DEFAULT NULL, `col72` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `col73` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `col74` varchar(170) DEFAULT NULL, `col75` set('test1','test2','test3') DEFAULT NULL, `col76` tinyblob, `col77` bigint(20) DEFAULT NULL, `col78` decimal(10,0) DEFAULT NULL, `col79` datetime DEFAULT NULL, `col80` year(4) DEFAULT NULL, `col81` decimal(10,0) DEFAULT NULL, `col82` longblob, `col83` text, `col84` char(83) DEFAULT NULL, `col85` decimal(10,0) DEFAULT NULL, `col86` float DEFAULT NULL, `col87` int(11) DEFAULT NULL, `col88` varchar(145) DEFAULT NULL, `col89` date DEFAULT NULL, `col90` decimal(10,0) DEFAULT NULL, `col91` decimal(10,0) DEFAULT NULL, `col92` mediumblob, `col93` time DEFAULT NULL, KEY `idx0` (`col69`,`col90`,`col8`), KEY `idx1` (`col60`), KEY `idx2` (`col60`,`col70`,`col74`), KEY `idx3` (`col22`,`col32`,`col72`,`col30`), KEY `idx4` (`col29`), KEY `idx5` (`col19`,`col45`(143)), KEY `idx6` (`col46`,`col48`,`col5`,`col39`(118)), KEY `idx7` (`col48`,`col61`), KEY `idx8` (`col93`), KEY `idx9` (`col31`), KEY `idx10` (`col30`,`col21`), KEY `idx11` (`col67`), KEY `idx12` (`col44`,`col6`,`col8`,`col38`(226)), KEY `idx13` (`col71`,`col41`,`col15`,`col49`(88)), KEY `idx14` (`col78`), KEY `idx15` (`col63`,`col67`,`col64`), KEY `idx16` (`col17`,`col86`), KEY `idx17` (`col77`,`col56`,`col10`,`col55`(24)), KEY `idx18` (`col62`), KEY `idx19` (`col31`,`col57`,`col56`,`col53`), KEY `idx20` (`col46`), KEY `idx21` (`col83`(54)), KEY `idx22` (`col51`,`col7`(120)), KEY `idx23` (`col7`(163),`col31`,`col71`,`col14`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2; insert ignore into `table0` set `col23` = 7887371.5084383683, `col24` = 4293854615.6906948000, `col25` = 'vitalist', `col26` = 'widespread', `col27` = '3570490', `col28` = 'habitual', `col30` = -5471, `col31` = 4286985783.6771750000, `col32` = 6354540.9826654866, `col33` = 'defoliation', `col34` = 'logarithms', `col35` = 'tegument\'s', `col36` = 'scouting\'s', `col37` = 'intermittency', `col38` = 'elongates', `col39` = 'prophecies', `col40` = '20560103035939', `col41` = 4292809130.0544143000, `col42` = 22057, `col43` = 'Hess\'s', `col44` = 'bandstand', `col45` = 'phenylketonuria', `col46` = 6338767.4018677324, `col47` = 5310247, `col48` = '12592418', `col49` = 'churchman\'s', `col50` = '32226125', `col51` = -58, `col52` = -6207968, `col53` = 1244839.3255104220, `col54` = 'robotized', `col55` = 'monotonous', `col56` = -26909, `col58` = '20720107023550', `col59` = 'suggestiveness\'s', `col60` = 'gemology', `col61` = 4287800670.2229986000, `col62` = '1944', `col63` = -16827, `col64` = '20700107212324', `col65` = 'Nicolais', `col66` = 'apteryx', `col67` = 6935317, `col68` = 'stroganoff', `col70` = 3316430, `col71` = '3277608', `col72` = '19300511045918', `col73` = '20421201003327', `col74` = 'attenuant', `col75` = '15173', `col76` = 'upstroke\'s', `col77` = 8118987, `col78` = 6791516.2735374002, `col79` = '20780701144624', `col80` = '2134', `col81` = 4290682351.3127537000, `col82` = 'unexplainably', `col83` = 'Storm', `col84` = 'Greyso\'s', `col85` = 4289119212.4306774000, `col86` = 7617575.8796655172, `col87` = -6325335, `col88` = 'fondue\'s', `col89` = '40608940', `col90` = 1659421.8093508712, `col91` = 8346904.6584368423, `col92` = 'reloads', `col93` = '5188366'; CHECK TABLE table0 EXTENDED; INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.9055146948, `col21` = 4293243420.5621204000, `col22` = '20511211123705', `col23` = 4289899778.6573381000, `col24` = 4293449279.0540481000, `col25` = 'emphysemic', `col26` = 'dentally', `col27` = '2347406', `col28` = 'eruct', `col30` = 1222, `col31` = 4294372994.9941406000, `col32` = 4291385574.1173744000, `col33` = 'borrowing\'s', `col34` = 'septics', `col35` = 'ratter\'s', `col36` = 'Kaye', `col37` = 'Florentia', `col38` = 'allium', `col39` = 'barkeep', `col40` = '19510407003441', `col41` = 4293559200.4215522000, `col42` = 22482, `col43` = 'decussate', `col44` = 'Brom\'s', `col45` = 'violated', `col46` = 4925506.4635456400, `col47` = 930549, `col48` = '51296066', `col49` = 'voluminously', `col50` = '29306676', `col51` = -88, `col52` = -2153690, `col53` = 4290250202.1464887000, `col54` = 'expropriation', `col55` = 'Aberdeen\'s', `col56` = 20343, `col58` = '19640415171532', `col59` = 'extern', `col60` = 'Ubana', `col61` = 4290487961.8539081000, `col62` = '2147', `col63` = -24271, `col64` = '20750801194548', `col65` = 'Cunaxa\'s', `col66` = 'pasticcio', `col67` = 2795817, `col68` = 'Indore\'s', `col70` = 6864127, `col71` = '1817832', `col72` = '20540506114211', `col73` = '20040101012300', `col74` = 'rationalized', `col75` = '45522', `col76` = 'indene', `col77` = -6964559, `col78` = 4247535.5266884370, `col79` = '20720416124357', `col80` = '2143', `col81` = 4292060102.4466386000, `col82` = 'striving', `col83` = 'boneblack\'s', `col84` = 'redolent', `col85` = 6489697.9009369183, `col86` = 4287473465.9731131000, `col87` = 7726015, `col88` = 'perplexed', `col89` = '17153791', `col90` = 5478587.1108127078, `col91` = 4287091404.7004304000, `col92` = 'Boulez\'s', `col93` = '2931278'; CHECK TABLE table0 EXTENDED; DROP TABLE table0; -EVAL SET GLOBAL innodb_file_format=$file_format; -EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/suite/innodb_zip/t/innodb_bug52745.test b/mysql-test/suite/innodb_zip/t/innodb_bug52745.test index 3c5d79826f0..fe7bdbae42d 100644 --- a/mysql-test/suite/innodb_zip/t/innodb_bug52745.test +++ b/mysql-test/suite/innodb_zip/t/innodb_bug52745.test @@ -1,10 +1,5 @@ -- source include/have_innodb.inc -let $file_format=`select @@innodb_file_format`; -let $file_per_table=`select @@innodb_file_per_table`; -SET GLOBAL innodb_file_format='Barracuda'; -SET GLOBAL innodb_file_per_table=on; - CREATE TABLE bug52745 ( a2 int(10) unsigned DEFAULT NULL, col37 time DEFAULT NULL, @@ -102,6 +97,3 @@ col90=repeat('gale',48); SHOW WARNINGS; DROP TABLE bug52745; - -EVAL SET GLOBAL innodb_file_format=$file_format; -EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/mysql-test/suite/innodb_zip/t/innodb_bug53591.test b/mysql-test/suite/innodb_zip/t/innodb_bug53591.test index 6c80165f6eb..1366e0e43ac 100644 --- a/mysql-test/suite/innodb_zip/t/innodb_bug53591.test +++ b/mysql-test/suite/innodb_zip/t/innodb_bug53591.test @@ -1,10 +1,5 @@ -- source include/have_innodb.inc -let $file_format=`select @@innodb_file_format`; -let $file_per_table=`select @@innodb_file_per_table`; - -SET GLOBAL innodb_file_format='Barracuda'; -SET GLOBAL innodb_file_per_table=on; SET GLOBAL innodb_strict_mode=on; set old_alter_table=0; @@ -18,6 +13,4 @@ SHOW WARNINGS; DROP TABLE bug53591; -EVAL SET GLOBAL innodb_file_format=$file_format; -EVAL SET GLOBAL innodb_file_per_table=$file_per_table; SET GLOBAL innodb_strict_mode=DEFAULT; diff --git a/mysql-test/suite/innodb_zip/t/innodb_bug56680.test b/mysql-test/suite/innodb_zip/t/innodb_bug56680.test index f592bd16942..4e73b1fce0f 100644 --- a/mysql-test/suite/innodb_zip/t/innodb_bug56680.test +++ b/mysql-test/suite/innodb_zip/t/innodb_bug56680.test @@ -4,8 +4,6 @@ # -- disable_query_log SET @tx_isolation_orig = @@tx_isolation; -SET @innodb_file_per_table_orig = @@innodb_file_per_table; -SET @innodb_file_format_orig = @@innodb_file_format; # The flag innodb_change_buffering_debug is only available in debug builds. # It instructs InnoDB to try to evict pages from the buffer pool when # change buffering is possible, so that the change buffer will be used @@ -16,8 +14,6 @@ SET @innodb_change_buffering_debug_orig = @@innodb_change_buffering_debug; SET GLOBAL innodb_change_buffering_debug = 1; -- enable_query_log SET GLOBAL tx_isolation='REPEATABLE-READ'; -SET GLOBAL innodb_file_format=Barracuda; -SET GLOBAL innodb_file_per_table=on; CREATE TABLE bug56680( a INT AUTO_INCREMENT PRIMARY KEY, @@ -133,7 +129,5 @@ DROP TABLE bug56680; -- disable_query_log SET GLOBAL tx_isolation = @tx_isolation_orig; -SET GLOBAL innodb_file_per_table = @innodb_file_per_table_orig; -SET GLOBAL innodb_file_format = @innodb_file_format_orig; -- error 0, ER_UNKNOWN_SYSTEM_VARIABLE SET GLOBAL innodb_change_buffering_debug = @innodb_change_buffering_debug_orig; diff --git a/mysql-test/suite/innodb_zip/t/innodb_index_large_prefix.test b/mysql-test/suite/innodb_zip/t/innodb_index_large_prefix.test index 8af2bc7ffc7..72890a933f2 100644 --- a/mysql-test/suite/innodb_zip/t/innodb_index_large_prefix.test +++ b/mysql-test/suite/innodb_zip/t/innodb_index_large_prefix.test @@ -6,12 +6,8 @@ SET default_storage_engine=InnoDB; call mtr.add_suppression("Cannot add field .* in table .* because after adding it, the row size is .* which is greater than maximum allowed size (.*) for a record on index leaf page."); -let $innodb_file_format_orig=`select @@innodb_file_format`; -let $innodb_file_per_table_orig=`select @@innodb_file_per_table`; let $innodb_large_prefix_orig=`select @@innodb_large_prefix`; -set global innodb_file_format="Barracuda"; -set global innodb_file_per_table=1; set global innodb_large_prefix=1; set global innodb_strict_mode=1; @@ -391,11 +387,13 @@ update worklog5743 set a = (repeat("x", 25000)); select @@session.tx_isolation; --connection con1 select a = repeat("a", 20000) from worklog5743; +--disconnect con1 --connection con2 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; select @@session.tx_isolation; select a = repeat("x", 25000) from worklog5743; +--disconnect con2 --connection default rollback; @@ -427,16 +425,5 @@ create index idx on worklog5743(a(768)); create index idx2 on worklog5743(a(767)); drop table worklog5743; - -eval SET GLOBAL innodb_file_format=$innodb_file_format_orig; -eval SET GLOBAL innodb_file_per_table=$innodb_file_per_table_orig; eval SET GLOBAL innodb_large_prefix=$innodb_large_prefix_orig; SET GLOBAL innodb_strict_mode = DEFAULT; ---connection con1 ---disconnect con1 ---source include/wait_until_disconnected.inc ---connection con2 ---disconnect con2 ---source include/wait_until_disconnected.inc ---connection default - diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test index eb4c23aa66e..3ec990b4715 100644 --- a/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_3.test @@ -21,6 +21,5 @@ let $wl6501_file_per_table = 1; let $wl6501_row_fmt = compressed; let $wl6501_kbs = 16; -let $wl6501_file_format = 'Barracuda'; --source suite/innodb/include/innodb_wl6501_crash.inc diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test index 870af3dfc94..f54df3c128c 100644 --- a/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_4.test @@ -21,9 +21,7 @@ let $wl6501_file_per_table = 1; let $wl6501_row_fmt = compressed; let $wl6501_kbs = 4; -let $wl6501_file_format = 'Barracuda'; --source suite/innodb/include/innodb_wl6501_crash.inc let $wl6501_temp = temporary; --source suite/innodb/include/innodb_wl6501_crash_temp.inc - diff --git a/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test b/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test index 3432a5a5c76..2f9847ae5fb 100644 --- a/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test +++ b/mysql-test/suite/innodb_zip/t/wl6501_crash_5.test @@ -21,6 +21,5 @@ let $wl6501_file_per_table = 1; let $wl6501_row_fmt = compressed; let $wl6501_kbs = 8; -let $wl6501_file_format = 'Barracuda'; --source suite/innodb/include/innodb_wl6501_crash.inc diff --git a/mysql-test/t/partition_innodb_plugin.test b/mysql-test/t/partition_innodb_plugin.test index a514736ff42..18ed0a27f96 100644 --- a/mysql-test/t/partition_innodb_plugin.test +++ b/mysql-test/t/partition_innodb_plugin.test @@ -36,11 +36,9 @@ call mtr.add_suppression("InnoDB: Error: table `test`.`t1` .* InnoDB internal"); --echo # --echo # Bug#55091: Server crashes on ADD PARTITION after a failed attempt --echo # -SET @old_innodb_file_format = @@global.innodb_file_format; SET @old_innodb_file_per_table = @@global.innodb_file_per_table; SET @old_innodb_strict_mode = @@global.innodb_strict_mode; -SET @@global.innodb_file_format = Barracuda, -@@global.innodb_file_per_table = ON, +SET @@global.innodb_file_per_table = ON, @@global.innodb_strict_mode = ON; --connect(con1,localhost,root,,) @@ -90,7 +88,6 @@ DROP TABLE t1; --disconnect con2 --connection default SET @@global.innodb_strict_mode = @old_innodb_strict_mode; -SET @@global.innodb_file_format = @old_innodb_file_format; SET @@global.innodb_file_per_table = @old_innodb_file_per_table; # @@ -153,4 +150,3 @@ ROLLBACK; disconnect con1; connection default; DROP TABLE `t``\""e`; -SET NAMES DEFAULT; diff --git a/storage/innobase/mysql-test/storage_engine/tbl_opt_key_block_size.opt b/storage/innobase/mysql-test/storage_engine/tbl_opt_key_block_size.opt deleted file mode 100644 index 7cd737b2b87..00000000000 --- a/storage/innobase/mysql-test/storage_engine/tbl_opt_key_block_size.opt +++ /dev/null @@ -1,3 +0,0 @@ ---innodb-file-per-table=1 ---innodb-file-format=Barracuda - diff --git a/storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.opt b/storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.opt deleted file mode 100644 index 7cd737b2b87..00000000000 --- a/storage/innobase/mysql-test/storage_engine/tbl_opt_row_format.opt +++ /dev/null @@ -1,3 +0,0 @@ ---innodb-file-per-table=1 ---innodb-file-format=Barracuda - From 9ea0b44c5696d9357465625c3fc9b7f57a856009 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 18 Jan 2017 09:27:19 +0100 Subject: [PATCH 090/167] Such big blocks in query processing should be represented in the debugging trace. --- sql/sql_derived.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 898b6336ae5..c27649ca5e8 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1129,23 +1129,24 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) { + DBUG_ENTER("pushdown_cond_for_derived"); if (!cond) - return false; + DBUG_RETURN(false); st_select_lex_unit *unit= derived->get_unit(); st_select_lex *sl= unit->first_select(); /* Do not push conditions into constant derived */ if (unit->executed) - return false; + DBUG_RETURN(false); /* Do not push conditions into recursive with tables */ if (derived->is_recursive_with_table()) - return false; + DBUG_RETURN(false); /* Do not push conditions into unit with global ORDER BY ... LIMIT */ if (unit->fake_select_lex && unit->fake_select_lex->explicit_limit) - return false; + DBUG_RETURN(false); /* Check whether any select of 'unit' allows condition pushdown */ bool some_select_allows_cond_pushdown= false; @@ -1158,7 +1159,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) } } if (!some_select_allows_cond_pushdown) - return false; + DBUG_RETURN(false); /* Build the most restrictive condition extractable from 'cond' @@ -1173,7 +1174,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) if (!extracted_cond) { /* Nothing can be pushed into the derived table */ - return false; + DBUG_RETURN(false); } /* Push extracted_cond into every select of the unit specifying 'derived' */ st_select_lex *save_curr_select= thd->lex->current_select; @@ -1257,6 +1258,6 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) sl->cond_pushed_into_having= extracted_cond_copy; } thd->lex->current_select= save_curr_select; - return false; + DBUG_RETURN(false); } From 25e5ce198228b4e9ca74015c7d320eb9c618d86b Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 18 Jan 2017 14:13:11 +0300 Subject: [PATCH 091/167] NOT FIXED: MDEV-10773: ANALYZE FORMAT=JSON query_with_CTE crashes Remove the testcase. It turns out, the crash still happens, just not on all platforms. --- mysql-test/r/cte_recursive.result | 65 ------------------------------- mysql-test/t/cte_recursive.test | 12 ------ 2 files changed, 77 deletions(-) diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index e68d5a38283..d5476aec1c4 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -2343,68 +2343,3 @@ select id + 1, uuid() from data_generator where id < 150000 select * from data_generator ) as a; drop table t1; -# -# MDEV-10773: ANALYZE FORMAT=JSON query_with_CTE crashes -# -analyze format=json -with recursive src(counter) as -(select 1 -union -select counter+1 from src where counter<10 -) select * from src; -ANALYZE -{ - "query_block": { - "select_id": 1, - "r_loops": 1, - "r_total_time_ms": "REPLACED", - "table": { - "table_name": "", - "access_type": "ALL", - "r_loops": 1, - "rows": 2, - "r_rows": 10, - "r_total_time_ms": "REPLACED"e-4, - "filtered": 100, - "r_filtered": 100, - "materialized": { - "query_block": { - "recursive_union": { - "table_name": "", - "access_type": "ALL", - "r_loops": 0, - "r_rows": null, - "query_specifications": [ - { - "query_block": { - "select_id": 2, - "table": { - "message": "No tables used" - } - } - }, - { - "query_block": { - "select_id": 3, - "r_loops": 10, - "r_total_time_ms": "REPLACED", - "table": { - "table_name": "", - "access_type": "ALL", - "r_loops": 10, - "rows": 2, - "r_rows": 1, - "r_total_time_ms": "REPLACED", - "filtered": 100, - "r_filtered": 90, - "attached_condition": "src.counter < 10" - } - } - } - ] - } - } - } - } - } -} diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index bb57a8600b6..ea0f73be259 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -1505,15 +1505,3 @@ select id, test_data ) as a; drop table t1; - ---echo # ---echo # MDEV-10773: ANALYZE FORMAT=JSON query_with_CTE crashes ---echo # ---replace_regex /"r_total_time_ms": [0-9]*[.]?[0-9]*/"r_total_time_ms": "REPLACED"/ -analyze format=json -with recursive src(counter) as -(select 1 - union - select counter+1 from src where counter<10 -) select * from src; - From 716b87845d6478b7838cfa291b29cb0d381f7d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 18 Jan 2017 13:32:55 +0200 Subject: [PATCH 092/167] Fix test failure on innodb-page_compression_snappy test. Modified test data to be more easily compressed and fixed mtr_suppression if compression fails. --- .../r/innodb-page_compression_snappy.result | 47 ++++++++++--------- .../t/innodb-page_compression_snappy.test | 26 +++++----- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result b/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result index 6b1ddd64e6c..442885755fd 100644 --- a/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result +++ b/mysql-test/suite/innodb/r/innodb-page_compression_snappy.result @@ -1,97 +1,98 @@ +call mtr.add_suppression("InnoDB: Compression failed for space.*"); set global innodb_compression_algorithm = 6; -create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; +create table innodb_compressed(c1 int, b char(200)) engine=innodb row_format=compressed key_block_size=8; show warnings; Level Code Message -create table innodb_normal (c1 int, b char(20)) engine=innodb; +create table innodb_normal (c1 int, b char(200)) engine=innodb; show warnings; Level Code Message -create table innodb_page_compressed1 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=1; +create table innodb_page_compressed1 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=1; show warnings; Level Code Message show create table innodb_page_compressed1; Table Create Table innodb_page_compressed1 CREATE TABLE `innodb_page_compressed1` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=1 -create table innodb_page_compressed2 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=2; +create table innodb_page_compressed2 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=2; show warnings; Level Code Message show create table innodb_page_compressed2; Table Create Table innodb_page_compressed2 CREATE TABLE `innodb_page_compressed2` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=2 -create table innodb_page_compressed3 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=3; +create table innodb_page_compressed3 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=3; show warnings; Level Code Message show create table innodb_page_compressed3; Table Create Table innodb_page_compressed3 CREATE TABLE `innodb_page_compressed3` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=3 -create table innodb_page_compressed4 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=4; +create table innodb_page_compressed4 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=4; show warnings; Level Code Message show create table innodb_page_compressed4; Table Create Table innodb_page_compressed4 CREATE TABLE `innodb_page_compressed4` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=4 -create table innodb_page_compressed5 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=5; +create table innodb_page_compressed5 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=5; show warnings; Level Code Message show create table innodb_page_compressed5; Table Create Table innodb_page_compressed5 CREATE TABLE `innodb_page_compressed5` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=5 -create table innodb_page_compressed6 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=6; +create table innodb_page_compressed6 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=6; show warnings; Level Code Message show create table innodb_page_compressed6; Table Create Table innodb_page_compressed6 CREATE TABLE `innodb_page_compressed6` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=6 -create table innodb_page_compressed7 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=7; +create table innodb_page_compressed7 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=7; show warnings; Level Code Message show create table innodb_page_compressed7; Table Create Table innodb_page_compressed7 CREATE TABLE `innodb_page_compressed7` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=7 -create table innodb_page_compressed8 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=8; +create table innodb_page_compressed8 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=8; show warnings; Level Code Message show create table innodb_page_compressed8; Table Create Table innodb_page_compressed8 CREATE TABLE `innodb_page_compressed8` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 -create table innodb_page_compressed9 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=9; +create table innodb_page_compressed9 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=9; show warnings; Level Code Message show create table innodb_page_compressed9; Table Create Table innodb_page_compressed9 CREATE TABLE `innodb_page_compressed9` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=9 create procedure innodb_insert_proc (repeat_count int) begin declare current_num int; set current_num = 0; while current_num < repeat_count do -insert into innodb_normal values(current_num,'testing..'); +insert into innodb_normal values(current_num,'aaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccc'); set current_num = current_num + 1; end while; end// @@ -154,7 +155,7 @@ show create table innodb_normal; Table Create Table innodb_normal CREATE TABLE `innodb_normal` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 alter table innodb_compressed row_format=default page_compressed=1 page_compression_level=8 key_block_size=0; show warnings; @@ -163,7 +164,7 @@ show create table innodb_compressed; Table Create Table innodb_compressed CREATE TABLE `innodb_compressed` ( `c1` int(11) DEFAULT NULL, - `b` char(20) DEFAULT NULL + `b` char(200) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `page_compressed`=1 `page_compression_level`=8 update innodb_page_compressed1 set c1 = c1 + 1; update innodb_page_compressed2 set c1 = c1 + 1; diff --git a/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test b/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test index 65b626f786d..b90d15f1fa3 100644 --- a/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test +++ b/mysql-test/suite/innodb/t/innodb-page_compression_snappy.test @@ -1,42 +1,42 @@ -- source include/have_innodb.inc -- source include/have_innodb_snappy.inc -call mtr.add_suppression("Compression failed for space*"); +call mtr.add_suppression("InnoDB: Compression failed for space.*"); let $innodb_compression_algorithm_orig=`select @@innodb_compression_algorithm`; # snappy set global innodb_compression_algorithm = 6; -create table innodb_compressed(c1 int, b char(20)) engine=innodb row_format=compressed key_block_size=8; +create table innodb_compressed(c1 int, b char(200)) engine=innodb row_format=compressed key_block_size=8; show warnings; -create table innodb_normal (c1 int, b char(20)) engine=innodb; +create table innodb_normal (c1 int, b char(200)) engine=innodb; show warnings; -create table innodb_page_compressed1 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=1; +create table innodb_page_compressed1 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=1; show warnings; show create table innodb_page_compressed1; -create table innodb_page_compressed2 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=2; +create table innodb_page_compressed2 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=2; show warnings; show create table innodb_page_compressed2; -create table innodb_page_compressed3 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=3; +create table innodb_page_compressed3 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=3; show warnings; show create table innodb_page_compressed3; -create table innodb_page_compressed4 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=4; +create table innodb_page_compressed4 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=4; show warnings; show create table innodb_page_compressed4; -create table innodb_page_compressed5 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=5; +create table innodb_page_compressed5 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=5; show warnings; show create table innodb_page_compressed5; -create table innodb_page_compressed6 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=6; +create table innodb_page_compressed6 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=6; show warnings; show create table innodb_page_compressed6; -create table innodb_page_compressed7 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=7; +create table innodb_page_compressed7 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=7; show warnings; show create table innodb_page_compressed7; -create table innodb_page_compressed8 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=8; +create table innodb_page_compressed8 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=8; show warnings; show create table innodb_page_compressed8; -create table innodb_page_compressed9 (c1 int, b char(20)) engine=innodb page_compressed=1 page_compression_level=9; +create table innodb_page_compressed9 (c1 int, b char(200)) engine=innodb page_compressed=1 page_compression_level=9; show warnings; show create table innodb_page_compressed9; delimiter //; @@ -45,7 +45,7 @@ begin declare current_num int; set current_num = 0; while current_num < repeat_count do - insert into innodb_normal values(current_num,'testing..'); + insert into innodb_normal values(current_num,'aaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccc'); set current_num = current_num + 1; end while; end// From 95ebca7197e42f06fc17a624802bfd5aeb178cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 18 Jan 2017 13:38:52 +0200 Subject: [PATCH 093/167] Fix test failure on sysvars_innodb. MySQL Compression code was removed but missed this test case. --- mysql-test/suite/sys_vars/r/sysvars_innodb.result | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 8f655c91427..b4c7b2cc1fb 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -594,20 +594,6 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL -VARIABLE_NAME INNODB_COMPRESS_DEBUG -SESSION_VALUE NULL -GLOBAL_VALUE none -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE none -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE ENUM -VARIABLE_COMMENT Compress all tables, without specifying the COMPRESS table attribute -NUMERIC_MIN_VALUE NULL -NUMERIC_MAX_VALUE NULL -NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST none,zlib,lz4,lz4hc -READ_ONLY NO -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME INNODB_CONCURRENCY_TICKETS SESSION_VALUE NULL GLOBAL_VALUE 5000 From 8780b895296a685da8c0bb2c6f301f748c87cf57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 18 Jan 2017 12:53:35 +0200 Subject: [PATCH 094/167] MDEV-11831 Make InnoDB mini-transaction memo checks stricter InnoDB keeps track of buffer-fixed buf_block_t or acquired rw_lock_t within a mini-transaction. There are some memo_contains assertions in the code that document when certain blocks or rw_locks must be held. But, these assertions only check the mini-transaction memo, not the fact whether the rw_lock_t are actually being held by the caller. btr_pcur_store_position(): Remove #ifdef, and assert that the block is always buffer-fixed. rtr_pcur_getnext_from_path(), rtr_pcur_open_low(), ibuf_rec_get_page_no_func(), ibuf_rec_get_space_func(), ibuf_rec_get_info_func(), ibuf_rec_get_op_type_func(), ibuf_build_entry_from_ibuf_rec_func(), ibuf_rec_get_volume_func(), ibuf_get_merge_page_nos_func(), ibuf_get_volume_buffered_count_func() ibuf_get_entry_counter_low_func(), page_set_ssn_id(), row_vers_old_has_index_entry(), row_vers_build_for_consistent_read(), row_vers_build_for_semi_consistent_read(), trx_undo_prev_version_build(): Make use of mtr_memo_contains_page_flagged(). mtr_t::memo_contains(): Take a const memo. Assert rw_lock_own(). FindPage, FlaggedCheck: Assert rw_lock_own_flagged(). --- storage/innobase/btr/btr0pcur.cc | 31 ++++------- storage/innobase/gis/gis0sea.cc | 18 +++--- storage/innobase/ibuf/ibuf0ibuf.cc | 39 ++++++------- storage/innobase/include/mtr0mtr.h | 8 +-- storage/innobase/include/mtr0types.h | 13 +++-- storage/innobase/include/page0page.ic | 7 ++- storage/innobase/mtr/mtr0mtr.cc | 80 +++++++++++++++++++++++---- storage/innobase/row/row0vers.cc | 13 +++-- storage/innobase/trx/trx0rec.cc | 7 ++- 9 files changed, 136 insertions(+), 80 deletions(-) diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 377a332bd9f..ecf3f7c07cb 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2016, 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 @@ -120,24 +120,17 @@ btr_pcur_store_position( page = page_align(rec); offs = page_offset(rec); -#ifdef UNIV_DEBUG - if (dict_index_is_spatial(index)) { - /* For spatial index, when we do positioning on parent - buffer if necessary, it might not hold latches, but the - tree must be locked to prevent change on the page */ - ut_ad((mtr_memo_contains_flagged( - mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK) - || mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_S_FIX - | MTR_MEMO_PAGE_X_FIX)) - && (block->page.buf_fix_count > 0)); - } else { - ut_ad(mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_S_FIX - | MTR_MEMO_PAGE_X_FIX)); - } -#endif /* UNIV_DEBUG */ + ut_ad(block->page.buf_fix_count); + /* For spatial index, when we do positioning on parent + buffer if necessary, it might not hold latches, but the + tree must be locked to prevent change on the page */ + ut_ad(mtr_memo_contains_flagged(mtr, block, + MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX) + || (dict_index_is_spatial(index) + && mtr_memo_contains_flagged( + mtr, dict_index_get_lock(index), + MTR_MEMO_X_LOCK | MTR_MEMO_SX_LOCK))); if (page_is_empty(page)) { /* It must be an empty index tree; NOTE that in this case diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index 99543ef8c9c..0bc96199486 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -129,12 +130,10 @@ rtr_pcur_getnext_from_path( || latch_mode & BTR_MODIFY_LEAF); mtr_s_lock(dict_index_get_lock(index), mtr); } else { - ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_SX_LOCK) - || mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_S_LOCK) - || mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK)); + ut_ad(mtr_memo_contains_flagged(mtr, &index->lock, + MTR_MEMO_SX_LOCK + | MTR_MEMO_S_LOCK + | MTR_MEMO_X_LOCK)); } const page_size_t& page_size = dict_table_page_size(index->table); @@ -601,10 +600,9 @@ rtr_pcur_open_low( } if (latch_mode & BTR_MODIFY_TREE) { - ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_X_LOCK) - || mtr_memo_contains(mtr, dict_index_get_lock(index), - MTR_MEMO_SX_LOCK)); + ut_ad(mtr_memo_contains_flagged(mtr, &index->lock, + MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK)); tree_latched = true; } diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 612a2f9a690..e6c36b425e6 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, MariaDB Corporation. +Copyright (c) 2016, 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 @@ -1227,8 +1227,9 @@ ibuf_rec_get_page_no_func( const byte* field; ulint len; - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, + MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); @@ -1265,8 +1266,8 @@ ibuf_rec_get_space_func( const byte* field; ulint len; - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); @@ -1315,8 +1316,8 @@ ibuf_rec_get_info_func( ulint info_len_local; ulint counter_local; - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); fields = rec_get_n_fields_old(rec); ut_a(fields > IBUF_REC_FIELD_USER); @@ -1387,8 +1388,8 @@ ibuf_rec_get_op_type_func( { ulint len; - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(rec) > 2); @@ -1586,8 +1587,8 @@ ibuf_build_entry_from_ibuf_rec_func( ulint comp; dict_index_t* index; - ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); data = rec_get_nth_field_old(ibuf_rec, IBUF_REC_FIELD_MARKER, &len); @@ -1708,8 +1709,8 @@ ibuf_rec_get_volume_func( ibuf_op_t op; ulint info_len; - ut_ad(mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, ibuf_rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, ibuf_rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); ut_ad(rec_get_n_fields_old(ibuf_rec) > 2); @@ -2291,8 +2292,8 @@ ibuf_get_merge_page_nos_func( ulint limit; ulint n_pages; - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); *n_stored = 0; @@ -2875,8 +2876,8 @@ ibuf_get_volume_buffered_count_func( const byte* types; ulint n_fields; - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(ibuf_inside(mtr)); n_fields = rec_get_n_fields_old(rec); @@ -3248,8 +3249,8 @@ ibuf_get_entry_counter_low_func( ulint len; ut_ad(ibuf_inside(mtr)); - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(rec_get_n_fields_old(rec) > 2); field = rec_get_nth_field_old(rec, IBUF_REC_FIELD_MARKER, &len); diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 3526436f042..e761aaf7ec1 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -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 @@ -487,9 +487,9 @@ struct mtr_t { @param type type of object @return true if contains */ static bool memo_contains( - mtr_buf_t* memo, - const void* object, - ulint type) + const mtr_buf_t* memo, + const void* object, + ulint type) MY_ATTRIBUTE((warn_unused_result)); /** Check if memo contains the given item. diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h index 69a68830af1..95879a43872 100644 --- a/storage/innobase/include/mtr0types.h +++ b/storage/innobase/include/mtr0types.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -257,10 +258,10 @@ The record consists of a MLOG_CHECKPOINT byte followed by mach_write_to_8(checkpoint_lsn). */ #define SIZE_OF_MLOG_CHECKPOINT 9 +#ifndef UNIV_INNOCHECKSUM /** Types for the mlock objects to store in the mtr memo; NOTE that the first 3 values must be RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ enum mtr_memo_type_t { -#ifndef UNIV_INNOCHECKSUM MTR_MEMO_PAGE_S_FIX = RW_S_LATCH, MTR_MEMO_PAGE_X_FIX = RW_X_LATCH, @@ -268,18 +269,18 @@ enum mtr_memo_type_t { MTR_MEMO_PAGE_SX_FIX = RW_SX_LATCH, MTR_MEMO_BUF_FIX = RW_NO_LATCH, -#endif /* !UNIV_CHECKSUM */ #ifdef UNIV_DEBUG - MTR_MEMO_MODIFY = 32, + MTR_MEMO_MODIFY = 16, #endif /* UNIV_DEBUG */ - MTR_MEMO_S_LOCK = 64, + MTR_MEMO_S_LOCK = RW_S_LATCH << 5, - MTR_MEMO_X_LOCK = 128, + MTR_MEMO_X_LOCK = RW_X_LATCH << 5, - MTR_MEMO_SX_LOCK = 256 + MTR_MEMO_SX_LOCK = RW_SX_LATCH << 5 }; +#endif /* !UNIV_CHECKSUM */ #ifdef UNIV_DEBUG # define MTR_MAGIC_N 54551 diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index 97f9d5a578f..a70ca3da8d8 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, MariaDB Corporation. +Copyright (c) 2016, 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 @@ -147,8 +147,9 @@ page_set_ssn_id( { page_t* page = buf_block_get_frame(block); - ut_ad(!mtr || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_SX_FIX) - || mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); + ut_ad(!mtr || mtr_memo_contains_flagged(mtr, block, + MTR_MEMO_PAGE_SX_FIX + | MTR_MEMO_PAGE_X_FIX)); if (page_zip) { mach_write_to_8(page + FIL_RTREE_SPLIT_SEQ_NUM, ssn_id); diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 736933bdaed..418cd7042c6 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -120,6 +121,8 @@ struct FindPage FindPage(const void* ptr, ulint flags) : m_ptr(ptr), m_flags(flags), m_slot(NULL) { + /* There must be some flags to look for. */ + ut_ad(flags); /* We can only look for page-related flags. */ ut_ad(!(flags & ~(MTR_MEMO_PAGE_S_FIX | MTR_MEMO_PAGE_X_FIX @@ -148,6 +151,11 @@ struct FindPage return(true); } + ut_ad(!(m_flags & (MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_SX_FIX + | MTR_MEMO_PAGE_X_FIX)) + || rw_lock_own_flagged(&block->lock, m_flags)); + m_slot = slot; return(false); } @@ -1009,14 +1017,30 @@ mtr_t::release_free_extents(ulint n_reserved) @return true if contains */ bool mtr_t::memo_contains( - mtr_buf_t* memo, - const void* object, - ulint type) + const mtr_buf_t* memo, + const void* object, + ulint type) { Find find(object, type); Iterate iterator(find); - return(!memo->for_each_block_in_reverse(iterator)); + if (memo->for_each_block_in_reverse(iterator)) { + return(false); + } + + switch (type) { + case MTR_MEMO_X_LOCK: + ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_X)); + break; + case MTR_MEMO_SX_LOCK: + ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_SX)); + break; + case MTR_MEMO_S_LOCK: + ut_ad(rw_lock_own((rw_lock_t*) object, RW_LOCK_S)); + break; + } + + return(true); } /** Debug check for flags */ @@ -1026,20 +1050,56 @@ struct FlaggedCheck { m_ptr(ptr), m_flags(flags) { - // Do nothing + /* There must be some flags to look for. */ + ut_ad(flags); + /* Look for rw-lock-related and page-related flags. */ + ut_ad(!(flags & ~(MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_SX_FIX + | MTR_MEMO_BUF_FIX + | MTR_MEMO_MODIFY + | MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK + | MTR_MEMO_S_LOCK))); + /* Either some rw-lock-related or page-related flags + must be specified, but not both at the same time. */ + ut_ad(!(flags & (MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_SX_FIX + | MTR_MEMO_BUF_FIX + | MTR_MEMO_MODIFY)) + == !!(flags & (MTR_MEMO_X_LOCK + | MTR_MEMO_SX_LOCK + | MTR_MEMO_S_LOCK))); } + /** Visit a memo entry. + @param[in] slot memo entry to visit + @retval false if m_ptr was found + @retval true if the iteration should continue */ bool operator()(const mtr_memo_slot_t* slot) const { - if (m_ptr == slot->object && (m_flags & slot->type)) { - return(false); + if (m_ptr != slot->object || !(m_flags & slot->type)) { + return(true); } - return(true); + if (ulint flags = m_flags & (MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_SX_FIX + | MTR_MEMO_PAGE_X_FIX)) { + rw_lock_t* lock = &static_cast( + const_cast(m_ptr))->lock; + ut_ad(rw_lock_own_flagged(lock, flags)); + } else { + rw_lock_t* lock = static_cast( + const_cast(m_ptr)); + ut_ad(rw_lock_own_flagged(lock, m_flags >> 5)); + } + + return(false); } - const void* m_ptr; - ulint m_flags; + const void*const m_ptr; + const ulint m_flags; }; /** Check if memo contains the given item. diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index f21b1ebbb85..69e7a889de9 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -876,8 +877,8 @@ row_vers_old_has_index_entry( mem_heap_t* v_heap = NULL; const dtuple_t* cur_vrow = NULL; - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_S)); clust_index = dict_table_get_first_index(index->table); @@ -1134,8 +1135,8 @@ row_vers_build_for_consistent_read( dberr_t err; ut_ad(dict_index_is_clust(index)); - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_S)); ut_ad(rec_offs_validate(rec, index, *offsets)); @@ -1246,8 +1247,8 @@ row_vers_build_for_semi_consistent_read( trx_id_t rec_trx_id = 0; ut_ad(dict_index_is_clust(index)); - ut_ad(mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_X_FIX) - || mtr_memo_contains_page(mtr, rec, MTR_MEMO_PAGE_S_FIX)); + ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_S_FIX)); ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_S)); ut_ad(rec_offs_validate(rec, index, *offsets)); diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 25807e7f825..3cea123cc1b 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -2234,9 +2235,9 @@ trx_undo_prev_version_build( byte* buf; ut_ad(!rw_lock_own(&purge_sys->latch, RW_LOCK_S)); - ut_ad(mtr_memo_contains_page(index_mtr, index_rec, MTR_MEMO_PAGE_S_FIX) - || mtr_memo_contains_page(index_mtr, index_rec, - MTR_MEMO_PAGE_X_FIX)); + ut_ad(mtr_memo_contains_page_flagged(index_mtr, index_rec, + MTR_MEMO_PAGE_S_FIX + | MTR_MEMO_PAGE_X_FIX)); ut_ad(rec_offs_validate(rec, index, offsets)); ut_a(dict_index_is_clust(index)); From a1315a650a69745bac7166cfe1423215dfaac6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 18 Jan 2017 14:02:17 +0200 Subject: [PATCH 095/167] MDEV-11202 InnoDB 10.1 -> 10.2 migration does not work This is the final preparation for the merge of MDEV-11623 from MariaDB Server 10.1 (correcting the assignment of FSP_SPACE_FLAGS in MariaDB Server 10.1). We must avoid reading FSP_SPACE_FLAGS directly from page 0, because the flags that affect the uncompressed page size cannot be trusted if we are upgrading from MariaDB 10.1. We will pass fil_space_t* instead of a numeric tablespace ID in many low-level functions, so that fil_space_t::flags will be available. This will also reduce the amount o tablespace ID lookups and the pressure on fil_system->mutex. fil_space_is_being_truncated(), fil_space_is_redo_skipped(), PageCallback::set_page_size(), fsp_header_get_page_size(): Remove. fil_node_open_file(), fil_space_get_crypt_data(): Use space->flags. fsp_free_extent(), fseg_get_first_extent(), fsp_get_space_header(), xdes_get_descriptor_with_space_hdr(), xdes_get_descriptor(), xdes_lst_get_descriptor(), fsp_space_modify_check(), fsp_init_file_page(), fsp_alloc_free_extent(), fsp_page_create(), fsp_alloc_free_page(), fsp_free_page(), fsp_alloc_seg_inode_page(), fsp_alloc_seg_inode(), fsp_free_seg_inode(), fseg_fill_free_list(), fseg_mark_page_used(), fseg_free_page_low(), fseg_free_extent(): Take fil_space_t* as a parameter, instead of taking a numeric ID. --- storage/innobase/fil/fil0fil.cc | 52 +-- storage/innobase/fsp/fsp0file.cc | 2 +- storage/innobase/fsp/fsp0fsp.cc | 582 ++++++++++++++--------------- storage/innobase/include/fil0fil.h | 19 - storage/innobase/include/fsp0fsp.h | 28 -- storage/innobase/row/row0import.cc | 30 +- 6 files changed, 284 insertions(+), 429 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index bfae83af3df..3070badd6db 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -659,7 +659,7 @@ retry: os_file_close(node->handle); - const page_size_t page_size(flags); + const page_size_t page_size(space->flags); min_size = FIL_IBD_FILE_INITIAL_SIZE * page_size.physical(); @@ -1903,20 +1903,6 @@ fil_space_get_flags( return(flags); } -/** Check if table is mark for truncate. -@param[in] id space id -@return true if tablespace is marked for truncate. */ -bool -fil_space_is_being_truncated( - ulint id) -{ - bool mark_for_truncate; - mutex_enter(&fil_system->mutex); - mark_for_truncate = fil_space_get_by_id(id)->is_being_truncated; - mutex_exit(&fil_system->mutex); - return(mark_for_truncate); -} - /** Open each fil_node_t of a named fil_space_t if not already open. @param[in] name Tablespace name @return true if all nodes are open */ @@ -3312,30 +3298,6 @@ fil_space_dec_redo_skipped_count( mutex_exit(&fil_system->mutex); } - -/** -Check whether a single-table tablespace is redo skipped. -@param[in] id space id -@return true if redo skipped */ -bool -fil_space_is_redo_skipped( - ulint id) -{ - fil_space_t* space; - bool is_redo_skipped; - - mutex_enter(&fil_system->mutex); - - space = fil_space_get_by_id(id); - - ut_a(space != NULL); - - is_redo_skipped = space->redo_skipped_count > 0; - - mutex_exit(&fil_system->mutex); - - return(is_redo_skipped); -} #endif /* UNIV_DEBUG */ /*******************************************************************//** @@ -6131,15 +6093,6 @@ fil_tablespace_iterate( return(err); } -/** Set the tablespace table size. -@param[in] page a page belonging to the tablespace */ -void -PageCallback::set_page_size( - const buf_frame_t* page) UNIV_NOTHROW -{ - m_page_size.copy_from(fsp_header_get_page_size(page)); -} - /********************************************************************//** Delete the tablespace file and any related files like .cfg. This should not be called for temporary tables. @@ -6656,10 +6609,9 @@ fil_space_get_crypt_data( byte *page = static_cast(ut_align(buf, UNIV_PAGE_SIZE)); fil_read(page_id_t(space_id, 0), univ_page_size, 0, univ_page_size.physical(), page); - ulint flags = fsp_header_get_flags(page); ulint offset = FSP_HEADER_OFFSET + fsp_header_get_encryption_offset( - page_size_t(flags)); + page_size_t(space->flags)); space->crypt_data = fil_space_read_crypt_data(space_id, page, offset); ut_free(buf); diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index afd4ba9dddc..cdcd9924d41 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -353,7 +353,7 @@ Datafile::read_first_page(bool read_only_mode) m_crypt_info = fil_space_read_crypt_data( m_space_id, m_first_page, FSP_HEADER_OFFSET + fsp_header_get_encryption_offset( - fsp_header_get_page_size(m_first_page))); + page_size_t(m_flags))); return(err); } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 8739326b022..70d73ead0b7 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -52,14 +53,19 @@ Created 11/29/1995 Heikki Tuuri // JAN: MySQL 5.7 Encryption // #include -/** Returns an extent to the free list of a space. -@param[in] page_id page id in the extent +typedef ulint page_no_t; + +/** Return an extent to the free list of a space. +@param[in,out] space tablespace +@param[in] offset page number in the extent @param[in] page_size page size @param[in,out] mtr mini-transaction */ +MY_ATTRIBUTE((nonnull)) static void fsp_free_extent( - const page_id_t& page_id, + fil_space_t* space, + page_no_t offset, const page_size_t& page_size, mtr_t* mtr); @@ -71,7 +77,7 @@ void fseg_mark_page_used( /*================*/ fseg_inode_t* seg_inode,/*!< in: segment inode */ - ulint page, /*!< in: page offset */ + page_no_t page, /*!< in: page offset */ xdes_t* descr, /*!< in: extent descriptor */ mtr_t* mtr); /*!< in/out: mini-transaction */ @@ -79,15 +85,16 @@ fseg_mark_page_used( We think of the extent lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE. @param[in] inode segment inode -@param[in] space_id space id +@param[in] space tablespace @param[in] page_size page size @param[in,out] mtr mini-transaction @return the first extent descriptor, or NULL if none */ +MY_ATTRIBUTE((nonnull, warn_unused_result)) static xdes_t* fseg_get_first_extent( fseg_inode_t* inode, - ulint space_id, + const fil_space_t* space, const page_size_t& page_size, mtr_t* mtr); @@ -147,31 +154,30 @@ fseg_alloc_free_page_low( MY_ATTRIBUTE((warn_unused_result)); /** Gets a pointer to the space header and x-locks its page. -@param[in] id space id +@param[in] space tablespace @param[in] page_size page size @param[in,out] mtr mini-transaction @return pointer to the space header, page x-locked */ UNIV_INLINE fsp_header_t* fsp_get_space_header( - ulint id, + const fil_space_t* space, const page_size_t& page_size, mtr_t* mtr) { buf_block_t* block; fsp_header_t* header; - ut_ad(id != 0 || !page_size.is_compressed()); + ut_ad(space->purpose != FIL_TYPE_LOG); + ut_ad(!FSP_FLAGS_GET_ZIP_SSIZE(space->flags) + == !page_size.is_compressed()); - block = buf_page_get(page_id_t(id, 0), page_size, RW_SX_LATCH, mtr); + block = buf_page_get(page_id_t(space->id, 0), page_size, + RW_SX_LATCH, mtr); header = FSP_HEADER_OFFSET + buf_block_get_frame(block); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - ut_ad(id == mach_read_from_4(FSP_SPACE_ID + header)); -#ifdef UNIV_DEBUG - const ulint flags = mach_read_from_4(FSP_SPACE_FLAGS + header); - ut_ad(page_size_t(flags).equals_to(page_size)); -#endif /* UNIV_DEBUG */ + ut_ad(space->id == mach_read_from_4(FSP_SPACE_ID + header)); return(header); } @@ -552,7 +558,7 @@ xdes_init( /** Get pointer to a the extent descriptor of a page. @param[in,out] sp_header tablespace header page, x-latched -@param[in] space tablespace identifier +@param[in] space tablespace @param[in] offset page offset @param[in,out] mtr mini-transaction @param[in] init_space whether the tablespace is being initialized @@ -563,43 +569,36 @@ exist in the space or if the offset exceeds free limit */ UNIV_INLINE MY_ATTRIBUTE((warn_unused_result)) xdes_t* xdes_get_descriptor_with_space_hdr( - fsp_header_t* sp_header, - ulint space, - ulint offset, - mtr_t* mtr, - bool init_space = false, - buf_block_t** desc_block = NULL) + fsp_header_t* sp_header, + const fil_space_t* space, + page_no_t offset, + mtr_t* mtr, + bool init_space = false, + buf_block_t** desc_block = NULL) { ulint limit; ulint size; ulint descr_page_no; - ulint flags; page_t* descr_page; -#ifdef UNIV_DEBUG - const fil_space_t* fspace = fil_space_get(space); - ut_ad(fspace != NULL); -#endif /* UNIV_DEBUG */ - ut_ad(mtr_memo_contains(mtr, &fspace->latch, MTR_MEMO_X_LOCK)); + ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_SX_FIX)); ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET); /* Read free limit and space size */ limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT); size = mach_read_from_4(sp_header + FSP_SIZE); - flags = mach_read_from_4(sp_header + FSP_SPACE_FLAGS); - ut_ad(limit == fspace->free_limit - || (fspace->free_limit == 0 + ut_ad(limit == space->free_limit + || (space->free_limit == 0 && (init_space - || fspace->purpose == FIL_TYPE_TEMPORARY + || space->purpose == FIL_TYPE_TEMPORARY || (srv_startup_is_before_trx_rollback_phase - && fspace->id <= srv_undo_tablespaces)))); - ut_ad(size == fspace->size_in_header); - ut_ad(flags == fspace->flags); + && space->id <= srv_undo_tablespaces)))); + ut_ad(size == space->size_in_header); if ((offset >= size) || (offset >= limit)) { return(NULL); } - const page_size_t page_size(flags); + const page_size_t page_size(space->flags); descr_page_no = xdes_calc_descriptor_page(page_size, offset); @@ -612,7 +611,7 @@ xdes_get_descriptor_with_space_hdr( block = NULL; } else { block = buf_page_get( - page_id_t(space, descr_page_no), page_size, + page_id_t(space->id, descr_page_no), page_size, RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -628,63 +627,60 @@ xdes_get_descriptor_with_space_hdr( + XDES_SIZE * xdes_calc_descriptor_index(page_size, offset)); } -/** Gets pointer to a the extent descriptor of a page. -The page where the extent descriptor resides is x-locked. If the page offset -is equal to the free limit of the space, adds new extents from above the free -limit to the space free list, if not free limit == space size. This adding -is necessary to make the descriptor defined, as they are uninitialized -above the free limit. -@param[in] space_id space id +/** Get the extent descriptor of a page. +The page where the extent descriptor resides is x-locked. If the page +offset is equal to the free limit of the space, we will add new +extents from above the free limit to the space free list, if not free +limit == space size. This adding is necessary to make the descriptor +defined, as they are uninitialized above the free limit. +@param[in] space tablespace @param[in] offset page offset; if equal to the free limit, we try to add new extents to the space free list @param[in] page_size page size @param[in,out] mtr mini-transaction -@return pointer to the extent descriptor, NULL if the page does not -exist in the space or if the offset exceeds the free limit */ +@return the extent descriptor */ +static xdes_t* xdes_get_descriptor( - ulint space_id, - ulint offset, + const fil_space_t* space, + page_no_t offset, const page_size_t& page_size, mtr_t* mtr) { buf_block_t* block; fsp_header_t* sp_header; - block = buf_page_get(page_id_t(space_id, 0), page_size, + block = buf_page_get(page_id_t(space->id, 0), page_size, RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); sp_header = FSP_HEADER_OFFSET + buf_block_get_frame(block); - return(xdes_get_descriptor_with_space_hdr(sp_header, space_id, offset, - mtr)); + return(xdes_get_descriptor_with_space_hdr( + sp_header, space, offset, mtr)); } -/********************************************************************//** -Gets pointer to a the extent descriptor if the file address -of the descriptor list node is known. The page where the +/** Get a pointer to the extent descriptor. The page where the extent descriptor resides is x-locked. +@param[in] space tablespace +@param[in] page_size page size +@param[in] lst_node file address of the list node + contained in the descriptor +@param[in,out] mtr mini-transaction @return pointer to the extent descriptor */ +MY_ATTRIBUTE((nonnull, warn_unused_result)) UNIV_INLINE xdes_t* xdes_lst_get_descriptor( -/*====================*/ - ulint space, /*!< in: space id */ + const fil_space_t* space, const page_size_t& page_size, - fil_addr_t lst_node,/*!< in: file address of the list node - contained in the descriptor */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + fil_addr_t lst_node, + mtr_t* mtr) { - xdes_t* descr; - - ut_ad(mtr); - ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL), - MTR_MEMO_X_LOCK)); - descr = fut_get_ptr(space, page_size, lst_node, RW_SX_LATCH, mtr) - - XDES_FLST_NODE; - - return(descr); + ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); + ut_ad(page_size.equals_to(page_size_t(space->flags))); + return(fut_get_ptr(space->id, page_size, lst_node, RW_SX_LATCH, mtr) + - XDES_FLST_NODE); } /********************************************************************//** @@ -739,30 +735,28 @@ updating an allocation bitmap page. static void fsp_space_modify_check( - ulint id, - const mtr_t* mtr) + const fil_space_t* space, + const mtr_t* mtr) { switch (mtr->get_log_mode()) { case MTR_LOG_SHORT_INSERTS: case MTR_LOG_NONE: /* These modes are only allowed within a non-bitmap page when there is a higher-level redo log record written. */ + ut_ad(space->purpose == FIL_TYPE_TABLESPACE + || space->purpose == FIL_TYPE_TEMPORARY); break; case MTR_LOG_NO_REDO: - { - const fil_type_t type = fil_space_get_type(id); - ut_a(srv_is_tablespace_truncated(id) - || fil_space_is_being_truncated(id) - || fil_space_get_flags(id) == ULINT_UNDEFINED - || type == FIL_TYPE_TEMPORARY - || type == FIL_TYPE_IMPORT - || fil_space_is_redo_skipped(id)); - } + ut_ad(space->purpose == FIL_TYPE_TEMPORARY + || space->purpose == FIL_TYPE_IMPORT + || space->redo_skipped_count + || space->is_being_truncated + || srv_is_tablespace_truncated(space->id)); return; case MTR_LOG_ALL: /* We may only write redo log for a persistent tablespace. */ - ut_ad(fil_space_get_type(id) == FIL_TYPE_TABLESPACE); - ut_ad(mtr->is_named_space(id)); + ut_ad(space->purpose == FIL_TYPE_TABLESPACE); + ut_ad(mtr->is_named_space(space->id)); return; } @@ -771,17 +765,21 @@ fsp_space_modify_check( #endif /* UNIV_DEBUG */ /** Initialize a file page. +@param[in] space tablespace @param[in,out] block file page @param[in,out] mtr mini-transaction */ +MY_ATTRIBUTE((nonnull)) static void fsp_init_file_page( - buf_block_t* block, - mtr_t* mtr) + const fil_space_t* space MY_ATTRIBUTE((unused)), + buf_block_t* block, + mtr_t* mtr) { + ut_d(fsp_space_modify_check(space, mtr)); + ut_ad(space->id == block->page.id.space()); fsp_init_file_page_low(block); - ut_d(fsp_space_modify_check(block->page.id.space(), mtr)); mlog_write_initial_log_record(buf_block_get_frame(block), MLOG_INIT_FILE_PAGE2, mtr); } @@ -878,7 +876,7 @@ fsp_header_init( /* The prior contents of the file page should be ignored */ - fsp_init_file_page(block, mtr); + fsp_init_file_page(space, block, mtr); page = buf_block_get_frame(block); mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_FSP_HDR, @@ -950,16 +948,6 @@ fsp_header_get_space_id( return(id); } -/** Reads the page size from the first page of a tablespace. -@param[in] page first page of a tablespace -@return page size */ -page_size_t -fsp_header_get_page_size( - const page_t* page) -{ - return(page_size_t(fsp_header_get_flags(page))); -} - /**********************************************************************//** Increases the space size field of a space. */ void @@ -975,10 +963,10 @@ fsp_header_inc_size( ut_ad(mtr); fil_space_t* space = mtr_x_lock_space(space_id, mtr); - ut_d(fsp_space_modify_check(space_id, mtr)); + ut_d(fsp_space_modify_check(space, mtr)); header = fsp_get_space_header( - space_id, page_size_t(space->flags), mtr); + space, page_size_t(space->flags), mtr); size = mach_read_from_4(header + FSP_SIZE); ut_ad(size == space->size_in_header); @@ -1005,12 +993,9 @@ fsp_header_get_tablespace_size(void) mtr_start(&mtr); -#ifdef UNIV_DEBUG - fil_space_t* space = -#endif /* UNIV_DEBUG */ - mtr_x_lock_space(TRX_SYS_SPACE, &mtr); + fil_space_t* space = mtr_x_lock_space(TRX_SYS_SPACE, &mtr); - header = fsp_get_space_header(TRX_SYS_SPACE, univ_page_size, &mtr); + header = fsp_get_space_header(space, univ_page_size, &mtr); size = mach_read_from_4(header + FSP_SIZE); ut_ad(space->size_in_header == size); @@ -1039,7 +1024,7 @@ fsp_try_extend_data_file_with_pages( ulint size; ut_a(!is_system_tablespace(space->id)); - ut_d(fsp_space_modify_check(space->id, mtr)); + ut_d(fsp_space_modify_check(space, mtr)); size = mach_read_from_4(header + FSP_SIZE); ut_ad(size == space->size_in_header); @@ -1073,7 +1058,7 @@ fsp_try_extend_data_file( "ran out of space. Please add another file or use" " 'autoextend' for the last file in setting"; - ut_d(fsp_space_modify_check(space->id, mtr)); + ut_d(fsp_space_modify_check(space, mtr)); if (space->id == srv_sys_space.space_id() && !srv_sys_space.can_auto_extend_last_file()) { @@ -1217,7 +1202,6 @@ fsp_fill_free_list( { ulint limit; ulint size; - ulint flags; xdes_t* descr; ulint count = 0; ulint frag_n_used; @@ -1226,18 +1210,16 @@ fsp_fill_free_list( ut_ad(header != NULL); ut_ad(mtr != NULL); ut_ad(page_offset(header) == FSP_HEADER_OFFSET); - ut_d(fsp_space_modify_check(space->id, mtr)); + ut_d(fsp_space_modify_check(space, mtr)); /* Check if we can fill free list from above the free list limit */ size = mach_read_from_4(header + FSP_SIZE); limit = mach_read_from_4(header + FSP_FREE_LIMIT); - flags = mach_read_from_4(header + FSP_SPACE_FLAGS); ut_ad(size == space->size_in_header); ut_ad(limit == space->free_limit); - ut_ad(flags == space->flags); - const page_size_t page_size(flags); + const page_size_t page_size(space->flags); if (size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) { bool skip_resize = init_space; @@ -1288,7 +1270,7 @@ fsp_fill_free_list( buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - fsp_init_file_page(block, mtr); + fsp_init_file_page(space, block, mtr); mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE, FIL_PAGE_TYPE_XDES, @@ -1326,7 +1308,7 @@ fsp_fill_free_list( buf_block_dbg_add_level(block, SYNC_FSP_PAGE); - fsp_init_file_page(block, &ibuf_mtr); + fsp_init_file_page(space, block, &ibuf_mtr); ibuf_bitmap_page_init(block, &ibuf_mtr); @@ -1336,7 +1318,7 @@ fsp_fill_free_list( buf_block_t* desc_block = NULL; descr = xdes_get_descriptor_with_space_hdr( - header, space->id, i, mtr, init_space, &desc_block); + header, space, i, mtr, init_space, &desc_block); if (desc_block != NULL) { fil_block_check_type( desc_block, FIL_PAGE_TYPE_XDES, mtr); @@ -1373,7 +1355,7 @@ fsp_fill_free_list( } /** Allocates a new free extent. -@param[in] space_id tablespace identifier +@param[in,out] space tablespace @param[in] page_size page size @param[in] hint hint of which extent would be desirable: any page offset in the extent goes; the hint must not be > FSP_FREE_LIMIT @@ -1382,7 +1364,7 @@ page offset in the extent goes; the hint must not be > FSP_FREE_LIMIT static xdes_t* fsp_alloc_free_extent( - ulint space_id, + fil_space_t* space, const page_size_t& page_size, ulint hint, mtr_t* mtr) @@ -1392,13 +1374,10 @@ fsp_alloc_free_extent( xdes_t* descr; buf_block_t* desc_block = NULL; - header = fsp_get_space_header(space_id, page_size, mtr); + header = fsp_get_space_header(space, page_size, mtr); descr = xdes_get_descriptor_with_space_hdr( - header, space_id, hint, mtr, false, &desc_block); - - fil_space_t* space = fil_space_get(space_id); - ut_a(space != NULL); + header, space, hint, mtr, false, &desc_block); if (desc_block != NULL) { fil_block_check_type(desc_block, FIL_PAGE_TYPE_XDES, mtr); @@ -1422,7 +1401,7 @@ fsp_alloc_free_extent( } descr = xdes_lst_get_descriptor( - space_id, page_size, first, mtr); + space, page_size, first, mtr); } flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr); @@ -1471,7 +1450,8 @@ fsp_alloc_from_free_frag( NOTE: If init_mtr != mtr, the block will only be initialized if it was not previously x-latched. It is assumed that the block has been x-latched only by mtr, and freed in mtr in that case. -@param[in] page_id page id of the allocated page +@param[in,out] space tablespace +@param[in] offset page number of the allocated page @param[in] page_size page size of the allocated page @param[in] rw_latch RW_SX_LATCH, RW_X_LATCH @param[in,out] mtr mini-transaction of the allocation @@ -1481,19 +1461,21 @@ or rw_lock_x_lock_count(&block->lock) == 1 */ static buf_block_t* fsp_page_create( - const page_id_t& page_id, + fil_space_t* space, + page_no_t offset, const page_size_t& page_size, rw_lock_type_t rw_latch, mtr_t* mtr, mtr_t* init_mtr) { - buf_block_t* block = buf_page_create(page_id, page_size, init_mtr); + ut_ad(page_size.equals_to(page_size_t(space->flags))); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX) - == rw_lock_own(&block->lock, RW_LOCK_X)); + buf_block_t* block = buf_page_create(page_id_t(space->id, offset), + page_size, init_mtr); - ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_SX_FIX) - == rw_lock_own(&block->lock, RW_LOCK_SX)); + ut_d(bool latched = mtr_memo_contains_flagged(mtr, block, + MTR_MEMO_PAGE_X_FIX + | MTR_MEMO_PAGE_SX_FIX)); ut_ad(rw_latch == RW_X_LATCH || rw_latch == RW_SX_LATCH); @@ -1519,12 +1501,8 @@ fsp_page_create( /* Initialize the page, unless it was already SX-latched in mtr. (In this case, we would want to allocate another page that has not been freed in mtr.) */ - ut_ad(init_mtr == mtr - || !mtr_memo_contains_flagged(mtr, block, - MTR_MEMO_PAGE_X_FIX - | MTR_MEMO_PAGE_SX_FIX)); - - fsp_init_file_page(block, init_mtr); + ut_ad(init_mtr == mtr || !latched); + fsp_init_file_page(space, block, init_mtr); } return(block); @@ -1532,7 +1510,7 @@ fsp_page_create( /** Allocates a single free page from a space. The page is marked as used. -@param[in] space space id +@param[in,out] space tablespace @param[in] page_size page size @param[in] hint hint of which page would be desirable @param[in] rw_latch RW_SX_LATCH, RW_X_LATCH @@ -1546,7 +1524,7 @@ initialized (may be the same as mtr) static MY_ATTRIBUTE((warn_unused_result)) buf_block_t* fsp_alloc_free_page( - ulint space, + fil_space_t* space, const page_size_t& page_size, ulint hint, rw_lock_type_t rw_latch, @@ -1557,8 +1535,7 @@ fsp_alloc_free_page( fil_addr_t first; xdes_t* descr; ulint free; - ulint page_no; - ulint space_size; + const ulint space_id = space->id; ut_ad(mtr); ut_ad(init_mtr); @@ -1617,18 +1594,18 @@ fsp_alloc_free_page( ut_error; } - page_no = xdes_get_offset(descr) + free; + page_no_t page_no = xdes_get_offset(descr) + free; - space_size = mach_read_from_4(header + FSP_SIZE); - ut_ad(space_size == fil_space_get(space)->size_in_header - || (space == TRX_SYS_SPACE + page_no_t space_size = mach_read_from_4(header + FSP_SIZE); + ut_ad(space_size == space->size_in_header + || (space_id == TRX_SYS_SPACE && srv_startup_is_before_trx_rollback_phase)); if (space_size <= page_no) { /* It must be that we are extending a single-table tablespace whose size is still < 64 pages */ - ut_a(!is_system_tablespace(space)); + ut_a(!is_system_tablespace(space_id)); if (page_no >= FSP_EXTENT_SIZE) { ib::error() << "Trying to extend a single-table" " tablespace " << space << " , by single" @@ -1637,9 +1614,7 @@ fsp_alloc_free_page( return(NULL); } - fil_space_t* fspace = fil_space_get(space); - - if (!fsp_try_extend_data_file_with_pages(fspace, page_no, + if (!fsp_try_extend_data_file_with_pages(space, page_no, header, mtr)) { /* No disk space left */ return(NULL); @@ -1647,19 +1622,21 @@ fsp_alloc_free_page( } fsp_alloc_from_free_frag(header, descr, free, mtr); - return(fsp_page_create(page_id_t(space, page_no), page_size, - rw_latch, mtr, init_mtr)); + return(fsp_page_create(space, page_no, page_size, rw_latch, + mtr, init_mtr)); } /** Frees a single page of a space. The page is marked as free and clean. +@param[in,out] space tablespace @param[in] page_id page id @param[in] page_size page size @param[in,out] mtr mini-transaction */ static void fsp_free_page( - const page_id_t& page_id, + fil_space_t* space, + ulint offset, const page_size_t& page_size, mtr_t* mtr) { @@ -1669,24 +1646,22 @@ fsp_free_page( ulint frag_n_used; ut_ad(mtr); - ut_d(fsp_space_modify_check(page_id.space(), mtr)); + ut_d(fsp_space_modify_check(space, mtr)); /* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */ - header = fsp_get_space_header( - page_id.space(), page_size, mtr); + header = fsp_get_space_header(space, page_size, mtr); descr = xdes_get_descriptor_with_space_hdr( - header, page_id.space(), page_id.page_no(), mtr); + header, space, offset, mtr); state = xdes_get_state(descr, mtr); - if (state != XDES_FREE_FRAG && state != XDES_FULL_FRAG) { + if (UNIV_UNLIKELY(state != XDES_FREE_FRAG + && state != XDES_FULL_FRAG)) { ib::error() << "File space extent descriptor of page " - << page_id << " has state " << state; - fputs("InnoDB: Dump of descriptor: ", stderr); - ut_print_buf(stderr, ((byte*) descr) - 50, 200); - putc('\n', stderr); + << page_id_t(space->id, offset) + << " has state " << state; /* Crash in debug version, so that we get a core dump of this corruption. */ ut_ad(0); @@ -1702,12 +1677,11 @@ fsp_free_page( } if (xdes_mtr_get_bit(descr, XDES_FREE_BIT, - page_id.page_no() % FSP_EXTENT_SIZE, mtr)) { + offset % FSP_EXTENT_SIZE, mtr)) { ib::error() << "File space extent descriptor of page " - << page_id << " says it is free. Dump of descriptor: "; - ut_print_buf(stderr, ((byte*) descr) - 50, 200); - putc('\n', stderr); + << page_id_t(space->id, offset) + << " says it is free."; /* Crash in debug version, so that we get a core dump of this corruption. */ ut_ad(0); @@ -1718,7 +1692,7 @@ fsp_free_page( return; } - const ulint bit = page_id.page_no() % FSP_EXTENT_SIZE; + const ulint bit = offset % FSP_EXTENT_SIZE; xdes_set_bit(descr, XDES_FREE_BIT, bit, TRUE, mtr); xdes_set_bit(descr, XDES_CLEAN_BIT, bit, TRUE, mtr); @@ -1745,37 +1719,39 @@ fsp_free_page( /* The extent has become free: move it to another list */ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); - fsp_free_extent(page_id, page_size, mtr); + fsp_free_extent(space, offset, page_size, mtr); } } -/** Returns an extent to the free list of a space. -@param[in] page_id page id in the extent +/** Return an extent to the free list of a space. +@param[in,out] space tablespace +@param[in] offset page number in the extent @param[in] page_size page size @param[in,out] mtr mini-transaction */ static void fsp_free_extent( - const page_id_t& page_id, + fil_space_t* space, + page_no_t offset, const page_size_t& page_size, mtr_t* mtr) { fsp_header_t* header; xdes_t* descr; - ut_ad(mtr); + ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); - header = fsp_get_space_header(page_id.space(), page_size, mtr); + header = fsp_get_space_header(space, page_size, mtr); descr = xdes_get_descriptor_with_space_hdr( - header, page_id.space(), page_id.page_no(), mtr); + header, space, offset, mtr); ut_a(xdes_get_state(descr, mtr) != XDES_FREE); xdes_init(descr, mtr); flst_add_last(header + FSP_FREE, descr + XDES_FLST_NODE, mtr); - fil_space_get(page_id.space())->free_len++; + space->free_len++; } /** Returns the nth inode slot on an inode page. @@ -1863,33 +1839,34 @@ fsp_seg_inode_page_find_free( return(ULINT_UNDEFINED); } -/**********************************************************************//** -Allocates a new file segment inode page. -@return TRUE if could be allocated */ +/** Allocate a file segment inode page. +@param[in,out] space tablespace +@param[in,out] space_header tablespace header +@param[in,out] mtr mini-transaction +@return whether the allocation succeeded */ +MY_ATTRIBUTE((nonnull, warn_unused_result)) static -ibool +bool fsp_alloc_seg_inode_page( -/*=====================*/ - fsp_header_t* space_header, /*!< in: space header */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + fil_space_t* space, + fsp_header_t* space_header, + mtr_t* mtr) { fseg_inode_t* inode; buf_block_t* block; page_t* page; - ulint space; ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET); + ut_ad(page_get_space_id(page_align(space_header)) == space->id); - space = page_get_space_id(page_align(space_header)); + const page_size_t page_size(space->flags); - const page_size_t page_size(mach_read_from_4(FSP_SPACE_FLAGS - + space_header)); - - block = fsp_alloc_free_page(space, page_size, 0, RW_SX_LATCH, mtr, mtr); + block = fsp_alloc_free_page( + space, page_size, 0, RW_SX_LATCH, mtr, mtr); if (block == NULL) { - return(FALSE); + return(false); } buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -1912,18 +1889,22 @@ fsp_alloc_seg_inode_page( space_header + FSP_SEG_INODES_FREE, page + FSEG_INODE_PAGE_NODE, mtr); - return(TRUE); + return(true); } -/**********************************************************************//** -Allocates a new file segment inode. -@return segment inode, or NULL if not enough space */ +/** Allocate a file segment inode. +@param[in,out] space tablespace +@param[in,out] space_header tablespace header +@param[in,out] mtr mini-transaction +@return segment inode +@retval NULL if not enough space */ +MY_ATTRIBUTE((nonnull, warn_unused_result)) static fseg_inode_t* fsp_alloc_seg_inode( -/*================*/ - fsp_header_t* space_header, /*!< in: space header */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + fil_space_t* space, + fsp_header_t* space_header, + mtr_t* mtr) { buf_block_t* block; page_t* page; @@ -1934,14 +1915,12 @@ fsp_alloc_seg_inode( /* Allocate a new segment inode page if needed. */ if (flst_get_len(space_header + FSP_SEG_INODES_FREE) == 0 - && !fsp_alloc_seg_inode_page(space_header, mtr)) { + && !fsp_alloc_seg_inode_page(space, space_header, mtr)) { return(NULL); } - const page_size_t page_size( - mach_read_from_4(FSP_SPACE_FLAGS + space_header)); - + const page_size_t page_size(space->flags); const page_id_t page_id( - page_get_space_id(page_align(space_header)), + space->id, flst_get_first(space_header + FSP_SEG_INODES_FREE, mtr).page); block = buf_page_get(page_id, page_size, RW_SX_LATCH, mtr); @@ -1974,14 +1953,14 @@ fsp_alloc_seg_inode( } /** Frees a file segment inode. -@param[in] space space id +@param[in,out] space tablespace @param[in] page_size page size @param[in,out] inode segment inode @param[in,out] mtr mini-transaction */ static void fsp_free_seg_inode( - ulint space, + fil_space_t* space, const page_size_t& page_size, fseg_inode_t* inode, mtr_t* mtr) @@ -2020,8 +1999,7 @@ fsp_free_seg_inode( flst_remove(space_header + FSP_SEG_INODES_FREE, page + FSEG_INODE_PAGE_NODE, mtr); - fsp_free_page(page_id_t(space, page_get_page_no(page)), - page_size, mtr); + fsp_free_page(space, page_get_page_no(page), page_size, mtr); } } @@ -2238,10 +2216,10 @@ fseg_create_general( ut_ad(mtr); ut_ad(byte_offset + FSEG_HEADER_SIZE <= UNIV_PAGE_SIZE - FIL_PAGE_DATA_END); - ut_d(fsp_space_modify_check(space_id, mtr)); fil_space_t* space = mtr_x_lock_space(space_id, mtr); const page_size_t page_size(space->flags); + ut_d(fsp_space_modify_check(space, mtr)); if (page != 0) { block = buf_page_get(page_id_t(space_id, page), page_size, @@ -2272,9 +2250,9 @@ fseg_create_general( DBUG_RETURN(NULL); } - space_header = fsp_get_space_header(space_id, page_size, mtr); + space_header = fsp_get_space_header(space, page_size, mtr); - inode = fsp_alloc_seg_inode(space_header, mtr); + inode = fsp_alloc_seg_inode(space, space_header, mtr); if (inode == NULL) { @@ -2316,7 +2294,7 @@ fseg_create_general( if (block == NULL) { - fsp_free_seg_inode(space_id, page_size, inode, mtr); + fsp_free_seg_inode(space, page_size, inode, mtr); goto funct_exit; } @@ -2428,7 +2406,7 @@ This happens if the segment is big enough to allow extents in the free list, the free list is empty, and the extents can be allocated consecutively from the hint onward. @param[in] inode segment inode -@param[in] space space id +@param[in] space tablespace @param[in] page_size page size @param[in] hint hint which extent would be good as the first extent @@ -2437,7 +2415,7 @@ static void fseg_fill_free_list( fseg_inode_t* inode, - ulint space, + fil_space_t* space, const page_size_t& page_size, ulint hint, mtr_t* mtr) @@ -2497,7 +2475,7 @@ the segment, then tries to allocate from the space free list. NOTE that the extent returned still resides in the segment free list, it is not yet taken off it! @param[in] inode segment inode -@param[in] space space id +@param[in,out] space tablespace @param[in] page_size page size @param[in,out] mtr mini-transaction @retval NULL if no page could be allocated @@ -2508,7 +2486,7 @@ static xdes_t* fseg_alloc_free_extent( fseg_inode_t* inode, - ulint space, + fil_space_t* space, const page_size_t& page_size, mtr_t* mtr) { @@ -2608,21 +2586,21 @@ fseg_alloc_free_page_low( seg_id = mach_read_from_8(seg_inode + FSEG_ID); ut_ad(seg_id); - ut_d(fsp_space_modify_check(space_id, mtr)); + ut_d(fsp_space_modify_check(space, mtr)); ut_ad(fil_page_get_type(page_align(seg_inode)) == FIL_PAGE_INODE); reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr); - space_header = fsp_get_space_header(space_id, page_size, mtr); + space_header = fsp_get_space_header(space, page_size, mtr); - descr = xdes_get_descriptor_with_space_hdr(space_header, space_id, + descr = xdes_get_descriptor_with_space_hdr(space_header, space, hint, mtr); if (descr == NULL) { /* Hint outside space or too high above free limit: reset hint */ /* The file space header page is always allocated. */ hint = 0; - descr = xdes_get_descriptor(space_id, hint, page_size, mtr); + descr = xdes_get_descriptor(space, hint, page_size, mtr); } /* In the big if-else below we look for ret_page and ret_descr */ @@ -2649,8 +2627,7 @@ take_hinted_page: ========================================================= the hinted page ===============*/ - ret_descr = fsp_alloc_free_extent( - space_id, page_size, hint, mtr); + ret_descr = fsp_alloc_free_extent(space, page_size, hint, mtr); ut_a(ret_descr == descr); @@ -2660,7 +2637,7 @@ take_hinted_page: ret_descr + XDES_FLST_NODE, mtr); /* Try to fill the segment free list */ - fseg_fill_free_list(seg_inode, space_id, page_size, + fseg_fill_free_list(seg_inode, space, page_size, hint + FSP_EXTENT_SIZE, mtr); goto take_hinted_page; /*-----------------------------------------------------------*/ @@ -2669,7 +2646,7 @@ take_hinted_page: && (used >= FSEG_FRAG_LIMIT) && (!!(ret_descr = fseg_alloc_free_extent( - seg_inode, space_id, page_size, mtr)))) { + seg_inode, space, page_size, mtr)))) { /* 3. We take any free extent (which was already assigned above =============================================================== @@ -2715,7 +2692,7 @@ take_hinted_page: return(NULL); } - ret_descr = xdes_lst_get_descriptor(space_id, page_size, + ret_descr = xdes_lst_get_descriptor(space, page_size, first, mtr); ret_page = xdes_get_offset(ret_descr) + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE, @@ -2726,7 +2703,7 @@ take_hinted_page: /* 6. We allocate an individual page from the space ===================================================*/ buf_block_t* block = fsp_alloc_free_page( - space_id, page_size, hint, rw_latch, mtr, init_mtr); + space, page_size, hint, rw_latch, mtr, init_mtr); ut_ad(!has_done_reservation || block != NULL); @@ -2749,7 +2726,7 @@ take_hinted_page: /* 7. We allocate a new extent and take its first page ======================================================*/ ret_descr = fseg_alloc_free_extent(seg_inode, - space_id, page_size, mtr); + space, page_size, mtr); if (ret_descr == NULL) { ret_page = FIL_NULL; @@ -2797,7 +2774,7 @@ got_hinted_page: The extent is still in the appropriate list (FSEG_NOT_FULL or FSEG_FREE), and the page is not yet marked as used. */ - ut_ad(xdes_get_descriptor(space_id, ret_page, page_size, mtr) + ut_ad(xdes_get_descriptor(space, ret_page, page_size, mtr) == ret_descr); ut_ad(xdes_mtr_get_bit( @@ -2807,10 +2784,8 @@ got_hinted_page: fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } - ut_ad(space->flags - == mach_read_from_4(FSP_SPACE_FLAGS + space_header)); - return(fsp_page_create(page_id_t(space_id, ret_page), page_size, - rw_latch, mtr, init_mtr)); + return(fsp_page_create(space, ret_page, page_size, rw_latch, + mtr, init_mtr)); } /**********************************************************************//** @@ -2920,7 +2895,7 @@ fsp_reserve_free_pages( ut_a(size < FSP_EXTENT_SIZE); descr = xdes_get_descriptor_with_space_hdr( - space_header, space->id, 0, mtr); + space_header, space, 0, mtr); n_used = xdes_get_n_used(descr, mtr); ut_a(n_used <= size); @@ -2994,7 +2969,7 @@ fsp_reserve_free_extents( fil_space_t* space = mtr_x_lock_space(space_id, mtr); const page_size_t page_size(space->flags); - space_header = fsp_get_space_header(space_id, page_size, mtr); + space_header = fsp_get_space_header(space, page_size, mtr); try_again: size = mach_read_from_4(space_header + FSP_SIZE); ut_ad(size == space->size_in_header); @@ -3210,7 +3185,8 @@ fseg_mark_page_used( /** Frees a single page of a segment. @param[in] seg_inode segment inode -@param[in] page_id page id +@param[in,out] space tablespace +@param[in] offset page number @param[in] page_size page size @param[in] ahi whether we may need to drop the adaptive hash index @@ -3219,7 +3195,8 @@ static void fseg_free_page_low( fseg_inode_t* seg_inode, - const page_id_t& page_id, + fil_space_t* space, + page_no_t offset, const page_size_t& page_size, bool ahi, mtr_t* mtr) @@ -3236,30 +3213,27 @@ fseg_free_page_low( ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); - ut_d(fsp_space_modify_check(page_id.space(), mtr)); + ut_d(fsp_space_modify_check(space, mtr)); /* Drop search system page hash index if the page is found in the pool and is hashed */ if (ahi) { - btr_search_drop_page_hash_when_freed(page_id, page_size); + btr_search_drop_page_hash_when_freed( + page_id_t(space->id, offset), page_size); } - descr = xdes_get_descriptor(page_id.space(), page_id.page_no(), - page_size, mtr); + descr = xdes_get_descriptor(space, offset, page_size, mtr); if (xdes_mtr_get_bit(descr, XDES_FREE_BIT, - page_id.page_no() % FSP_EXTENT_SIZE, mtr)) { - fputs("InnoDB: Dump of the tablespace extent descriptor: ", - stderr); - ut_print_buf(stderr, descr, 40); - ib::error() << "InnoDB is trying to free page " << page_id + offset % FSP_EXTENT_SIZE, mtr)) { + ib::fatal() << "InnoDB is trying to free page " + << page_id_t(space->id, offset) << " though it is already marked as free in the" " tablespace! The tablespace free space info is" " corrupt. You may need to dump your tables and" - " recreate the whole database!"; -crash: - ib::fatal() << FORCE_RECOVERY_MSG; + " recreate the whole database!" + << FORCE_RECOVERY_MSG; } state = xdes_get_state(descr, mtr); @@ -3269,7 +3243,7 @@ crash: for (i = 0;; i++) { if (fseg_get_nth_frag_page_no(seg_inode, i, mtr) - == page_id.page_no()) { + == offset) { fseg_set_nth_frag_page_no(seg_inode, i, FIL_NULL, mtr); @@ -3277,7 +3251,7 @@ crash: } } - fsp_free_page(page_id, page_size, mtr); + fsp_free_page(space, offset, page_size, mtr); return; } @@ -3295,10 +3269,11 @@ crash: ut_print_buf(stderr, seg_inode, 40); putc('\n', stderr); - ib::error() << "InnoDB is trying to free page " << page_id + ib::fatal() << "InnoDB is trying to free page " + << page_id_t(space->id, offset) << ", which does not belong to segment " << descr_id - << " but belongs to segment " << seg_id << "."; - goto crash; + << " but belongs to segment " << seg_id << "." + << FORCE_RECOVERY_MSG; } not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED, @@ -3318,7 +3293,7 @@ crash: not_full_n_used - 1, MLOG_4BYTES, mtr); } - const ulint bit = page_id.page_no() % FSP_EXTENT_SIZE; + const ulint bit = offset % FSP_EXTENT_SIZE; xdes_set_bit(descr, XDES_FREE_BIT, bit, TRUE, mtr); xdes_set_bit(descr, XDES_CLEAN_BIT, bit, TRUE, mtr); @@ -3327,7 +3302,7 @@ crash: /* The extent has become free: free it to space */ flst_remove(seg_inode + FSEG_NOT_FULL, descr + XDES_FLST_NODE, mtr); - fsp_free_extent(page_id, page_size, mtr); + fsp_free_extent(space, offset, page_size, mtr); } } @@ -3346,7 +3321,7 @@ fseg_free_page( DBUG_ENTER("fseg_free_page"); fseg_inode_t* seg_inode; buf_block_t* iblock; - const fil_space_t* space = mtr_x_lock_space(space_id, mtr); + fil_space_t* space = mtr_x_lock_space(space_id, mtr); const page_size_t page_size(space->flags); DBUG_LOG("fseg_free_page", "space_id: " << space_id @@ -3356,11 +3331,9 @@ fseg_free_page( &iblock); fil_block_check_type(iblock, FIL_PAGE_INODE, mtr); - const page_id_t page_id(space_id, page); + fseg_free_page_low(seg_inode, space, page, page_size, ahi, mtr); - fseg_free_page_low(seg_inode, page_id, page_size, ahi, mtr); - - ut_d(buf_page_set_file_page_was_freed(page_id)); + ut_d(buf_page_set_file_page_was_freed(page_id_t(space_id, page))); DBUG_VOID_RETURN; } @@ -3391,7 +3364,7 @@ fseg_page_is_free( == FSEG_MAGIC_N_VALUE); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); - descr = xdes_get_descriptor(space_id, page, page_size, &mtr); + descr = xdes_get_descriptor(space, page, page_size, &mtr); ut_a(descr); is_free = xdes_mtr_get_bit( @@ -3402,19 +3375,24 @@ fseg_page_is_free( return(is_free); } -/**********************************************************************//** -Frees an extent of a segment to the space free list. */ -static MY_ATTRIBUTE((nonnull)) +/** Free an extent of a segment to the space free list. +@param[in,out] seg_inode segment inode +@param[in,out] space tablespace +@param[in] page_size page size +@param[in] page page number in the extent +@param[in] ahi whether we may need to drop + the adaptive hash index +@param[in,out] mtr mini-transaction */ +MY_ATTRIBUTE((nonnull)) +static void fseg_free_extent( -/*=============*/ - fseg_inode_t* seg_inode, /*!< in: segment inode */ - ulint space, /*!< in: space id */ + fseg_inode_t* seg_inode, + fil_space_t* space, const page_size_t& page_size, - ulint page, /*!< in: a page in the extent */ - bool ahi, /*!< in: whether we may need to drop - the adaptive hash index */ - mtr_t* mtr) /*!< in/out: mini-transaction */ + ulint page, + bool ahi, + mtr_t* mtr) { ulint first_page_in_extent; xdes_t* descr; @@ -3444,7 +3422,7 @@ fseg_free_extent( is hashed */ btr_search_drop_page_hash_when_freed( - page_id_t(space, + page_id_t(space->id, first_page_in_extent + i), page_size); } @@ -3471,13 +3449,13 @@ fseg_free_extent( MLOG_4BYTES, mtr); } - fsp_free_extent(page_id_t(space, page), page_size, mtr); + fsp_free_extent(space, page, page_size, mtr); #ifdef UNIV_DEBUG for (i = 0; i < FSP_EXTENT_SIZE; i++) { buf_page_set_file_page_was_freed( - page_id_t(space, first_page_in_extent + i)); + page_id_t(space->id, first_page_in_extent + i)); } #endif /* UNIV_DEBUG */ } @@ -3511,10 +3489,10 @@ fseg_free_step( space_id = page_get_space_id(page_align(header)); header_page = page_get_page_no(page_align(header)); - const fil_space_t* space = mtr_x_lock_space(space_id, mtr); + fil_space_t* space = mtr_x_lock_space(space_id, mtr); const page_size_t page_size(space->flags); - descr = xdes_get_descriptor(space_id, header_page, page_size, mtr); + descr = xdes_get_descriptor(space, header_page, page_size, mtr); /* Check that the header resides on a page which has not been freed yet */ @@ -3532,13 +3510,13 @@ fseg_free_step( } fil_block_check_type(iblock, FIL_PAGE_INODE, mtr); - descr = fseg_get_first_extent(inode, space_id, page_size, mtr); + descr = fseg_get_first_extent(inode, space, page_size, mtr); if (descr != NULL) { /* Free the extent held by the segment */ page = xdes_get_offset(descr); - fseg_free_extent(inode, space_id, page_size, page, ahi, mtr); + fseg_free_extent(inode, space, page_size, page, ahi, mtr); DBUG_RETURN(FALSE); } @@ -3548,21 +3526,21 @@ fseg_free_step( if (n == ULINT_UNDEFINED) { /* Freeing completed: free the segment inode */ - fsp_free_seg_inode(space_id, page_size, inode, mtr); + fsp_free_seg_inode(space, page_size, inode, mtr); DBUG_RETURN(TRUE); } fseg_free_page_low( - inode, - page_id_t(space_id, fseg_get_nth_frag_page_no(inode, n, mtr)), + inode, space, + fseg_get_nth_frag_page_no(inode, n, mtr), page_size, ahi, mtr); n = fseg_find_last_used_frag_page_slot(inode, mtr); if (n == ULINT_UNDEFINED) { /* Freeing completed: free the segment inode */ - fsp_free_seg_inode(space_id, page_size, inode, mtr); + fsp_free_seg_inode(space, page_size, inode, mtr); DBUG_RETURN(TRUE); } @@ -3593,20 +3571,20 @@ fseg_free_step_not_header( space_id = page_get_space_id(page_align(header)); ut_ad(mtr->is_named_space(space_id)); - const fil_space_t* space = mtr_x_lock_space(space_id, mtr); + fil_space_t* space = mtr_x_lock_space(space_id, mtr); const page_size_t page_size(space->flags); buf_block_t* iblock; inode = fseg_inode_get(header, space_id, page_size, mtr, &iblock); fil_block_check_type(iblock, FIL_PAGE_INODE, mtr); - descr = fseg_get_first_extent(inode, space_id, page_size, mtr); + descr = fseg_get_first_extent(inode, space, page_size, mtr); if (descr != NULL) { /* Free the extent held by the segment */ page = xdes_get_offset(descr); - fseg_free_extent(inode, space_id, page_size, page, ahi, mtr); + fseg_free_extent(inode, space, page_size, page, ahi, mtr); return(FALSE); } @@ -3626,8 +3604,7 @@ fseg_free_step_not_header( return(TRUE); } - fseg_free_page_low(inode, page_id_t(space_id, page_no), page_size, ahi, - mtr); + fseg_free_page_low(inode, space, page_no, page_size, ahi, mtr); return(FALSE); } @@ -3636,28 +3613,24 @@ fseg_free_step_not_header( We think of the extent lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE. @param[in] inode segment inode -@param[in] space_id space id +@param[in] space tablespace @param[in] page_size page size @param[in,out] mtr mini-transaction @return the first extent descriptor, or NULL if none */ +MY_ATTRIBUTE((nonnull, warn_unused_result)) static xdes_t* fseg_get_first_extent( fseg_inode_t* inode, - ulint space_id, + const fil_space_t* space, const page_size_t& page_size, mtr_t* mtr) { fil_addr_t first; - xdes_t* descr; - ut_ad(inode && mtr); - - ut_ad(space_id == page_get_space_id(page_align(inode))); + ut_ad(space->id == page_get_space_id(page_align(inode))); ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); - first = fil_addr_null; - if (flst_get_len(inode + FSEG_FULL) > 0) { first = flst_get_first(inode + FSEG_FULL, mtr); @@ -3669,15 +3642,14 @@ fseg_get_first_extent( } else if (flst_get_len(inode + FSEG_FREE) > 0) { first = flst_get_first(inode + FSEG_FREE, mtr); - } - - if (first.page == FIL_NULL) { - + } else { return(NULL); } - descr = xdes_lst_get_descriptor(space_id, page_size, first, mtr); - return(descr); + ut_ad(first.page != FIL_NULL); + + return(first.page == FIL_NULL ? NULL + : xdes_lst_get_descriptor(space, page_size, first, mtr)); } #ifdef UNIV_DEBUG @@ -3694,7 +3666,6 @@ fseg_validate_low( ulint space_id; ib_id_t seg_id; mtr_t mtr; - xdes_t* descr; fil_addr_t node_addr; ulint n_used = 0; ulint n_used2 = 0; @@ -3718,11 +3689,8 @@ fseg_validate_low( mtr_start(&mtr); const fil_space_t* space = mtr_x_lock_space( space_id, &mtr); - - const page_size_t page_size(space->flags); - - descr = xdes_lst_get_descriptor(space_id, page_size, - node_addr, &mtr); + const xdes_t* descr = xdes_lst_get_descriptor( + space, page_size_t(space->flags), node_addr, &mtr); ut_a(xdes_get_n_used(descr, &mtr) == 0); ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG); @@ -3740,10 +3708,8 @@ fseg_validate_low( mtr_start(&mtr); const fil_space_t* space = mtr_x_lock_space( space_id, &mtr); - const page_size_t page_size(space->flags); - - descr = xdes_lst_get_descriptor(space_id, page_size, - node_addr, &mtr); + const xdes_t* descr = xdes_lst_get_descriptor( + space, page_size_t(space->flags), node_addr, &mtr); ut_a(xdes_get_n_used(descr, &mtr) > 0); ut_a(xdes_get_n_used(descr, &mtr) < FSP_EXTENT_SIZE); @@ -3764,10 +3730,8 @@ fseg_validate_low( mtr_start(&mtr); const fil_space_t* space = mtr_x_lock_space( space_id, &mtr); - const page_size_t page_size(space->flags); - - descr = xdes_lst_get_descriptor(space_id, page_size, - node_addr, &mtr); + const xdes_t* descr = xdes_lst_get_descriptor( + space, page_size_t(space->flags), node_addr, &mtr); ut_a(xdes_get_n_used(descr, &mtr) == FSP_EXTENT_SIZE); ut_a(xdes_get_state(descr, &mtr) == XDES_FSEG); @@ -3914,10 +3878,10 @@ fsp_page_is_free_func( { ut_ad(mtr); - const fil_space_t* space = mtr_x_lock_space(space_id, mtr); + fil_space_t* space = mtr_x_lock_space(space_id, mtr); const page_size_t page_size(space->flags); - xdes_t* descr = xdes_get_descriptor(space_id, page_no, page_size, mtr); + xdes_t* descr = xdes_get_descriptor(space, page_no, page_size, mtr); ut_a(descr); return xdes_mtr_get_bit( diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 3d786764148..5cf75395d8c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -630,13 +630,6 @@ fil_space_get_flags( /*================*/ ulint id); /*!< in: space id */ -/** Check if table is mark for truncate. -@param[in] id space id -@return true if tablespace is marked for truncate. */ -bool -fil_space_is_being_truncated( - ulint id); - /** Open each fil_node_t of a named fil_space_t if not already open. @param[in] name Tablespace name @return true if all file nodes are opened. */ @@ -1275,14 +1268,6 @@ fil_space_inc_redo_skipped_count( void fil_space_dec_redo_skipped_count( ulint id); - -/*******************************************************************//** -Check whether a single-table tablespace is redo skipped. -@return true if redo skipped */ -bool -fil_space_is_redo_skipped( -/*======================*/ - ulint id); /*!< in: space id */ #endif /********************************************************************//** @@ -1341,10 +1326,6 @@ struct PageCallback { @retval the space flags of the tablespace being iterated over */ virtual ulint get_space_flags() const UNIV_NOTHROW = 0; - /** Set the tablespace table size. - @param[in] page a page belonging to the tablespace */ - void set_page_size(const buf_frame_t* page) UNIV_NOTHROW; - /** The compressed page size @return the compressed page size */ const page_size_t& get_page_size() const diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 878929c085c..2551677ecbe 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -329,13 +329,6 @@ fsp_header_get_flags(const page_t* page) return(fsp_header_get_field(page, FSP_SPACE_FLAGS)); } -/** Reads the page size from the first page of a tablespace. -@param[in] page first page of a tablespace -@return page size */ -page_size_t -fsp_header_get_page_size( - const page_t* page); - /** Get the byte offset of encryption information in page 0. @param[in] ps page size @return byte offset relative to FSP_HEADER_OFFSET */ @@ -688,27 +681,6 @@ xdes_calc_descriptor_index( const page_size_t& page_size, ulint offset); -/** Gets pointer to a the extent descriptor of a page. -The page where the extent descriptor resides is x-locked. If the page offset -is equal to the free limit of the space, adds new extents from above the free -limit to the space free list, if not free limit == space size. This adding -is necessary to make the descriptor defined, as they are uninitialized -above the free limit. -@param[in] space_id space id -@param[in] offset page offset; if equal to the free limit, we -try to add new extents to the space free list -@param[in] page_size page size -@param[in,out] mtr mini-transaction -@return pointer to the extent descriptor, NULL if the page does not -exist in the space or if the offset exceeds the free limit */ -xdes_t* -xdes_get_descriptor( - ulint space_id, - ulint offset, - const page_size_t& page_size, - mtr_t* mtr) -MY_ATTRIBUTE((warn_unused_result)); - /**********************************************************************//** Gets a descriptor bit of a page. @return TRUE if free */ diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 554455509a7..7fe925ae3ee 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2016, MariaDB Corporation. +Copyright (c) 2015, 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 @@ -384,6 +384,12 @@ public: return(get_page_size().is_compressed()); } + /** @return the tablespace flags */ + ulint get_space_flags() const + { + return(m_space_flags); + } + protected: /** Get the data page depending on the table type, compressed or not. @param block block read from disk @@ -541,13 +547,7 @@ AbstractCallback::init( const page_t* page = block->frame; m_space_flags = fsp_header_get_flags(page); - - /* Since we don't know whether it is a compressed table - or not, the data is always read into the block->frame. */ - - set_page_size(block->frame); - - /* Set the page size used to traverse the tablespace. */ + m_page_size.copy_from(page_size_t(m_space_flags)); if (!is_compressed_table() && !m_page_size.equals_to(univ_page_size)) { @@ -614,13 +614,6 @@ struct FetchIndexRootPages : public AbstractCallback { return(m_space); } - /** - @retval the space flags of the tablespace being iterated over */ - virtual ulint get_space_flags() const UNIV_NOTHROW - { - return(m_space_flags); - } - /** Check if the .ibd file row format is the same as the table's. @param ibd_table_flags determined from space and page. @return DB_SUCCESS or error code. */ @@ -849,13 +842,6 @@ public: return(m_cfg->m_table->space); } - /** - @retval the space flags of the tablespace being iterated over */ - virtual ulint get_space_flags() const UNIV_NOTHROW - { - return(m_space_flags); - } - /** Called for each block as it is read from the file. @param offset physical offset in the file @param block block to convert, it is not from the buffer pool. From 833aa97cec771fbfb2ef8dd104de6a3d1e971daa Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 18 Jan 2017 21:03:01 -0800 Subject: [PATCH 096/167] Fixed bug mdev-11818. When a query containing a WITH clause is printed by EXPLAIN EXTENDED command there should not be any data expansion in the query specifications of the WITH elements of this WITH clause. --- mysql-test/r/cte_nonrecursive.result | 12 ++++++++++++ mysql-test/t/cte_nonrecursive.test | 12 ++++++++++++ sql/sql_cte.cc | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result index 71bf617df0a..bd681dbb343 100644 --- a/mysql-test/r/cte_nonrecursive.result +++ b/mysql-test/r/cte_nonrecursive.result @@ -927,3 +927,15 @@ Sergei Golubchik Development DE Claudio Nanni Support ES Sergei Petrunia Development RU drop table employees; +# +# MDEV-11818: EXPLAIN EXTENDED for a query with optimized away CTE table +# +CREATE TABLE t1 (i INT, c VARCHAR(3)); +INSERT INTO t1 VALUES (1,'foo'); +EXPLAIN EXTENDED +WITH cte AS ( SELECT * FROM t1 ) SELECT i FROM cte; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00 +Warnings: +Note 1003 with cte as (select `test`.`t1`.`i` AS `i`,`test`.`t1`.`c` AS `c` from `test`.`t1`)select 1 AS `i` from dual +DROP TABLE t1; diff --git a/mysql-test/t/cte_nonrecursive.test b/mysql-test/t/cte_nonrecursive.test index 8dbde472c16..b3a127475f2 100644 --- a/mysql-test/t/cte_nonrecursive.test +++ b/mysql-test/t/cte_nonrecursive.test @@ -609,3 +609,15 @@ where and T2.name <> T1.name); drop table employees; + +--echo # +--echo # MDEV-11818: EXPLAIN EXTENDED for a query with optimized away CTE table +--echo # + +CREATE TABLE t1 (i INT, c VARCHAR(3)); +INSERT INTO t1 VALUES (1,'foo'); + +EXPLAIN EXTENDED +WITH cte AS ( SELECT * FROM t1 ) SELECT i FROM cte; + +DROP TABLE t1; diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index a4ceae52e5e..42cc20647a4 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -1246,6 +1246,12 @@ bool st_select_lex::check_subqueries_with_recursive_references() void With_clause::print(String *str, enum_query_type query_type) { + /* + Any with clause contains just definitions of CTE tables. + No data expansion is applied to these definitions. + */ + query_type= (enum_query_type) (query_type | QT_NO_DATA_EXPANSION); + str->append(STRING_WITH_LEN("with ")); if (with_recursive) str->append(STRING_WITH_LEN("recursive ")); From b9631b46337b2ad76f0cc336cb2990e6bb8ad6f6 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Thu, 19 Jan 2017 17:55:37 +0200 Subject: [PATCH 097/167] Follow-up for the 10.1 -> 10.2 merge Fix 32-bit rdiffs to get rid of failed hunks --- .../sys_vars/r/sysvars_innodb,32bit.rdiff | 22 ------------------- .../r/sysvars_server_embedded,32bit.rdiff | 10 ++++----- .../r/sysvars_server_notembedded,32bit.rdiff | 12 +++++----- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff index 41ec54bb4fa..ed57382a2a9 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit.rdiff @@ -134,15 +134,6 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -641,7 +641,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 0 - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT InnoDB system tablespace size to be set in recovery. - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 4294967295 @@ -865,7 +865,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 120 @@ -543,19 +534,6 @@ VARIABLE_COMMENT Memory buffer size for index creation NUMERIC_MIN_VALUE 65536 NUMERIC_MAX_VALUE 67108864 -@@ -2195,10 +2195,10 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 6 - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Maximum delay between polling for a spin lock (6 by default) - NUMERIC_MIN_VALUE 0 --NUMERIC_MAX_VALUE 18446744073709551615 -+NUMERIC_MAX_VALUE 4294967295 - NUMERIC_BLOCK_SIZE 0 - ENUM_VALUE_LIST NULL - READ_ONLY NO @@ -2391,7 +2391,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index 66f38d270b0..0f34179a16d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -997,12 +997,12 @@ VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 4294967295 + VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 @@ -3123,7 +3123,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 16384 + GLOBAL_VALUE_ORIGIN COMPILE-TIME + DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index e9fa72fb5b7..88216992587 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -997,12 +997,12 @@ VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 4294967295 + VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. + NUMERIC_MIN_VALUE 0 + NUMERIC_MAX_VALUE 4294967295 @@ -3347,7 +3347,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 16384 + GLOBAL_VALUE_ORIGIN COMPILE-TIME + DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED @@ -1204,7 +1204,7 @@ NUMERIC_MAX_VALUE 1048576 @@ -4719,7 +4719,7 @@ GLOBAL_VALUE_ORIGIN AUTO - DEFAULT_VALUE 0 + DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED From d75d8631ed2d6af730931ea7079ec7e512e61796 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 20 Jan 2017 15:33:28 +0200 Subject: [PATCH 098/167] [MDEV-10570] Add Flashback support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ==== Description ==== Flashback can rollback the instances/databases/tables to an old snapshot. It's implement on Server-Level by full image format binary logs (--binlog-row-image=FULL), so it supports all engines. Currently, it’s a feature inside mysqlbinlog tool (with --flashback arguments). Because the flashback binlog events will store in the memory, you should check if there is enough memory in your machine. ==== New Arguments to mysqlbinlog ==== --flashback (-B) It will let mysqlbinlog to work on FLASHBACK mode. ==== New Arguments to mysqld ==== --flashback Setup the server to use flashback. This enables binary log in row mode and will enable extra logging for DDL's needed by flashback feature ==== Example ==== I have a table "t" in database "test", we can compare the output with "--flashback" and without. #client/mysqlbinlog /data/mysqldata_10.0/binlog/mysql-bin.000001 -vv -d test -T t --start-datetime="2013-03-27 14:54:00" > /tmp/1.sql #client/mysqlbinlog /data/mysqldata_10.0/binlog/mysql-bin.000001 -vv -d test -T t --start-datetime="2013-03-27 14:54:00" -B > /tmp/2.sql Then, importing the output flashback file (/tmp/2.log), it can flashback your database/table to the special time (--start-datetime). And if you know the exact postion, "--start-postion" is also works, mysqlbinlog will output the flashback logs that can flashback to "--start-postion" position. ==== Implement ==== 1. As we know, if binlog_format is ROW (binlog-row-image=FULL in 10.1 and later), all columns value are store in the row event, so we can get the data before mis-operation. 2. Just do following things: 2.1 Change Event Type, INSERT->DELETE, DELETE->INSERT. For example: INSERT INTO t VALUES (...) ---> DELETE FROM t WHERE ... DELETE FROM t ... ---> INSERT INTO t VALUES (...) 2.2 For Update_Event, swapping the SET part and WHERE part. For example: UPDATE t SET cols1 = vals1 WHERE cols2 = vals2 ---> UPDATE t SET cols2 = vals2 WHERE cols1 = vals1 2.3 For Multi-Rows Event, reverse the rows sequence, from the last row to the first row. For example: DELETE FROM t WHERE id=1; DELETE FROM t WHERE id=2; ...; DELETE FROM t WHERE id=n; ---> DELETE FROM t WHERE id=n; ...; DELETE FROM t WHERE id=2; DELETE FROM t WHERE id=1; 2.4 Output those events from the last one to the first one which mis-operation happened. For example: --- client/client_priv.h | 4 + client/mysqlbinlog.cc | 251 ++++++++- mysql-test/r/mysqld--help.result | 4 + mysql-test/suite/binlog/r/flashback.result | 480 ++++++++++++++++++ .../suite/binlog/t/flashback-master.opt | 2 + mysql-test/suite/binlog/t/flashback.test | 163 ++++++ mysql-test/suite/wsrep/r/binlog_format.result | 8 +- sql/log_event.cc | 418 +++++++++++++-- sql/log_event.h | 76 ++- sql/mysqld.cc | 18 +- sql/mysqld.h | 1 + sql/sys_vars.cc | 7 +- 12 files changed, 1377 insertions(+), 55 deletions(-) create mode 100644 mysql-test/suite/binlog/r/flashback.result create mode 100644 mysql-test/suite/binlog/t/flashback-master.opt create mode 100644 mysql-test/suite/binlog/t/flashback.test diff --git a/client/client_priv.h b/client/client_priv.h index 1d85791fa73..e96e187fb34 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -66,6 +66,10 @@ enum options_client OPT_MYSQLDUMP_SLAVE_APPLY, OPT_MYSQLDUMP_SLAVE_DATA, OPT_MYSQLDUMP_INCLUDE_MASTER_HOST_PORT, +#ifdef WHEN_FLASHBACK_REVIEW_READY + OPT_REVIEW, + OPT_REVIEW_DBNAME, OPT_REVIEW_TABLENAME, +#endif OPT_SLAP_CSV, OPT_SLAP_CREATE_STRING, OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, OPT_SLAP_AUTO_GENERATE_WRITE_NUM, OPT_SLAP_AUTO_GENERATE_ADD_AUTO, diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 558dbebc89c..39a879bc619 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -66,6 +66,10 @@ Rpl_filter *binlog_filter= 0; /* Needed for Rpl_filter */ CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci; +/* Needed for Flashback */ +DYNAMIC_ARRAY binlog_events; // Storing the events output string +String stop_event_string; // Storing the STOP_EVENT output string + char server_version[SERVER_VERSION_LENGTH]; ulong server_id = 0; @@ -89,7 +93,7 @@ static const char *load_groups[]= static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); -static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0; +static bool one_database=0, one_table=0, to_last_remote_log= 0, disable_log_bin= 0; static bool opt_hexdump= 0, opt_version= 0; const char *base64_output_mode_names[]= {"NEVER", "AUTO", "ALWAYS", "UNSPEC", "DECODE-ROWS", NullS}; @@ -99,6 +103,7 @@ TYPELIB base64_output_mode_typelib= static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC; static char *opt_base64_output_mode_str= NullS; static char* database= 0; +static char* table= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static my_bool debug_info_flag, debug_check_flag; static my_bool force_if_open_opt= 1; @@ -132,6 +137,12 @@ static MYSQL* mysql = NULL; static const char* dirname_for_local_load= 0; static bool opt_skip_annotate_row_events= 0; +static my_bool opt_flashback; +#ifdef WHEN_FLASHBACK_REVIEW_READY +static my_bool opt_flashback_review; +static char *flashback_review_dbname, *flashback_review_tablename; +#endif + /** Pointer to the Format_description_log_event of the currently active binlog. @@ -790,6 +801,23 @@ print_skip_replication_statement(PRINT_EVENT_INFO *pinfo, const Log_event *ev) pinfo->skip_replication= cur_val; } +/** + Indicates whether the given table should be filtered out, + according to the --table=X option. + + @param log_tblname Name of table. + + @return nonzero if the table with the given name should be + filtered out, 0 otherwise. +*/ +static bool shall_skip_table(const char *log_tblname) +{ + return one_table && + (log_tblname != NULL) && + strcmp(log_tblname, table); +} + + /** Prints the given event in base64 format. @@ -952,6 +980,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, Exit_status retval= OK_CONTINUE; IO_CACHE *const head= &print_event_info->head_cache; + /* Bypass flashback settings to event */ + ev->is_flashback= opt_flashback; +#ifdef WHEN_FLASHBACK_REVIEW_READY + ev->need_flashback_review= opt_flashback_review; +#endif + /* Format events are not concerned by --offset and such, we always need to read them to be able to process the wanted events. @@ -988,7 +1022,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, retval= OK_STOP; goto end; } - if (!short_form) + if (!short_form && !opt_flashback) fprintf(result_file, "# at %s\n",llstr(pos,ll_buff)); if (!opt_hexdump) @@ -1214,12 +1248,128 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, case TABLE_MAP_EVENT: { Table_map_log_event *map= ((Table_map_log_event *)ev); - if (shall_skip_database(map->get_db_name())) + if (shall_skip_database(map->get_db_name()) || + shall_skip_table(map->get_table_name())) { print_event_info->m_table_map_ignored.set_table(map->get_table_id(), map); destroy_evt= FALSE; goto end; } +#ifdef WHEN_FLASHBACK_REVIEW_READY + /* Create review table for Flashback */ + if (opt_flashback_review) + { + // Check if the table was already created? + Table_map_log_event *exist_table; + exist_table= print_event_info->m_table_map.get_table(map->get_table_id()); + + if (!exist_table) + { + + MYSQL *conn; + MYSQL_RES *res; + MYSQL_ROW row; + char tmp_sql[8096]; + int tmp_sql_offset; + + conn = mysql_init(NULL); + if (!mysql_real_connect(conn, host, user, pass, + map->get_db_name(), port, sock, 0)) + { + fprintf(stderr, "%s\n", mysql_error(conn)); + exit(1); + } + + if (mysql_query(conn, "SET group_concat_max_len=10000;")) + { + fprintf(stderr, "%s\n", mysql_error(conn)); + exit(1); + } + + memset(tmp_sql, 0, sizeof(tmp_sql)); + sprintf(tmp_sql, " " + "SELECT Group_concat(cols) " + "FROM (SELECT 'op_type char(1)' cols " + " UNION ALL " + " SELECT Concat('`', column_name, '_old` ', column_type, ' ', " + " IF(character_set_name IS NOT NULL, " + " Concat('character set ', character_set_name, ' '), ' '), " + " IF(collation_name IS NOT NULL, " + " Concat('collate ', collation_name, ' '), ' ')) cols " + " FROM information_schema.columns " + " WHERE table_schema = '%s' " + " AND table_name = '%s' " + " UNION ALL " + " SELECT Concat('`', column_name, '_new` ', column_type, ' ', " + " IF(character_set_name IS NOT NULL, " + " Concat('character set ', character_set_name, ' '), ' '), " + " IF(collation_name IS NOT NULL, " + " Concat('collate ', collation_name, ' '), ' ')) cols " + " FROM information_schema.columns " + " WHERE table_schema = '%s' " + " AND table_name = '%s') tmp;", + map->get_db_name(), map->get_table_name(), + map->get_db_name(), map->get_table_name()); + + if (mysql_query(conn, tmp_sql)) + { + fprintf(stderr, "%s\n", mysql_error(conn)); + exit(1); + } + res = mysql_use_result(conn); + if ((row = mysql_fetch_row(res)) != NULL) // only one row + { + if (flashback_review_dbname) + { + ev->set_flashback_review_dbname(flashback_review_dbname); + } + else + { + ev->set_flashback_review_dbname(map->get_db_name()); + } + if (flashback_review_tablename) + { + ev->set_flashback_review_tablename(flashback_review_tablename); + } + else + { + memset(tmp_sql, 0, sizeof(tmp_sql)); + sprintf(tmp_sql, "__%s", map->get_table_name()); + ev->set_flashback_review_tablename(tmp_sql); + } + memset(tmp_sql, 0, sizeof(tmp_sql)); + tmp_sql_offset= sprintf(tmp_sql, "CREATE TABLE IF NOT EXISTS"); + tmp_sql_offset+= sprintf(tmp_sql + tmp_sql_offset, " `%s`.`%s` (%s) %s", + ev->get_flashback_review_dbname(), + ev->get_flashback_review_tablename(), + row[0], + print_event_info->delimiter); + } + fprintf(result_file, "%s\n", tmp_sql); + mysql_free_result(res); + mysql_close(conn); + } + else + { + char tmp_str[128]; + + if (flashback_review_dbname) + ev->set_flashback_review_dbname(flashback_review_dbname); + else + ev->set_flashback_review_dbname(map->get_db_name()); + + if (flashback_review_tablename) + ev->set_flashback_review_tablename(flashback_review_tablename); + else + { + memset(tmp_str, 0, sizeof(tmp_str)); + sprintf(tmp_str, "__%s", map->get_table_name()); + ev->set_flashback_review_tablename(tmp_str); + } + } + } +#endif + /* The Table map is to be printed, so it's just the time when we may print the kept Annotate event (if there is any). @@ -1294,6 +1444,38 @@ end: */ if (ev) { + /* Holding event output if needed */ + if (!ev->output_buf.is_empty()) + { + LEX_STRING tmp_str; + + tmp_str.length= ev->output_buf.length(); + tmp_str.str= ev->output_buf.release(); + + if (opt_flashback) + { + if (ev_type == STOP_EVENT) + stop_event_string.reset(tmp_str.str, tmp_str.length, tmp_str.length, + &my_charset_bin); + else + { + if (push_dynamic(&binlog_events, (uchar *) &tmp_str)) + { + error("Out of memory: can't allocate memory to store the flashback events."); + exit(1); + } + } + } + else + { + my_fwrite(result_file, (const uchar *) tmp_str.str, tmp_str.length, + MYF(MY_NABP)); + my_free(tmp_str.str); + } + } + + if (remote_opt) + ev->temp_buf= 0; if (destroy_evt) /* destroy it later if not set (ignored table map) */ delete ev; } @@ -1352,6 +1534,13 @@ static struct my_option my_options[] = "already have. NOTE: you will need a SUPER privilege to use this option.", &disable_log_bin, &disable_log_bin, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"flashback", 'B', "Flashback feature can rollback you committed data to a special time point.", +#ifdef WHEN_FLASHBACK_REVIEW_READY + "before Flashback feature writing a row, original row can insert to review-dbname.review-tablename," + "and mysqlbinlog will login mysql by user(-u) and password(-p) and host(-h).", +#endif + &opt_flashback, &opt_flashback, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, {"force-if-open", 'F', "Force if binlog was not closed properly.", &force_if_open_opt, &force_if_open_opt, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, @@ -1395,6 +1584,19 @@ static struct my_option my_options[] = "prefix for the file names.", &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef WHEN_FLASHBACK_REVIEW_READY + {"review", opt_flashback_review, "Print review sql in output file.", + &opt_flashback_review, &opt_flashback_review, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, + {"review-dbname", opt_flashback_flashback_review_dbname, + "Writing flashback original row data into this db", + &flashback_review_dbname, &flashback_review_dbname, + 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"review-tablename", opt_flashback_flashback_review_tablename, + "Writing flashback original row data into this table", + &flashback_review_tablename, &flashback_review_tablename, + 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"server-id", 0, "Extract only binlog entries created by the server having the given id.", &server_id, &server_id, 0, GET_ULONG, @@ -1458,6 +1660,9 @@ static struct my_option my_options[] = &stop_position, &stop_position, 0, GET_ULL, REQUIRED_ARG, (longlong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE, (ulonglong)(~(my_off_t)0), 0, 0, 0}, + {"table", 'T', "List entries for just this table (local log only).", + &table, &table, 0, GET_STR_ALLOC, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, {"to-last-log", 't', "Requires -R. Will not stop at the end of the \ requested binlog but rather continue printing until the end of the last \ binlog of the MySQL server. If you send the output to the same MySQL server, \ @@ -1567,6 +1772,7 @@ static void cleanup() { my_free(pass); my_free(database); + my_free(table); my_free(host); my_free(user); my_free(const_cast(dirname_for_local_load)); @@ -1637,6 +1843,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; #endif #include + case 'B': + opt_flashback= 1; + break; case 'd': one_database = 1; break; @@ -1658,10 +1867,18 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case 'R': remote_opt= 1; break; + case 'T': + one_table= 1; + break; case OPT_MYSQL_PROTOCOL: opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib, opt->name); break; +#ifdef WHEN_FLASHBACK_REVIEW_READY + case opt_flashback_review: + opt_flashback_review= 1; + break; +#endif case OPT_START_DATETIME: start_datetime= convert_str_to_timestamp(start_datetime_str); break; @@ -1862,7 +2079,7 @@ static Exit_status dump_log_entries(const char* logname) dump_local_log_entries(&print_event_info, logname)); /* Set delimiter back to semicolon */ - if (!opt_raw_mode) + if (!opt_raw_mode && !opt_flashback) fprintf(result_file, "DELIMITER ;\n"); strmov(print_event_info.delimiter, ";"); return rc; @@ -2660,6 +2877,9 @@ int main(int argc, char** argv) DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); + (void) my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024, + MYF(0)); + my_init_time(); // for time functions tzset(); // set tzname @@ -2795,6 +3015,29 @@ int main(int argc, char** argv) start_position= BIN_LOG_HEADER_SIZE; } + /* + If enable flashback, need to print the events from the end to the + beginning + */ + if (opt_flashback) + { + for (uint i= binlog_events.elements; i > 0; --i) + { + LEX_STRING *event_str= dynamic_element(&binlog_events, i - 1, + LEX_STRING*); + fprintf(result_file, "%s", event_str->str); + my_free(event_str->str); + } + fprintf(result_file, "COMMIT\n/*!*/;\n"); + } + delete_dynamic(&binlog_events); + + /* Set delimiter back to semicolon */ + if (!stop_event_string.is_empty()) + fprintf(result_file, "%s", stop_event_string.ptr()); + if (!opt_raw_mode && opt_flashback) + fprintf(result_file, "DELIMITER ;\n"); + if (!opt_raw_mode) { /* diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 2b62252a129..c6797eab5ae 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -208,6 +208,9 @@ The following options may be given as the first argument: --extra-port=# Extra port number to use for tcp connections in a one-thread-per-connection manner. 0 means don't use another port + --flashback Setup the server to use flashback. This enables binary + log in row mode and will enable extra logging for DDL's + needed by flashback feature --flush Flush MyISAM tables to disk between SQL commands --flush-time=# A dedicated thread is created to flush all tables at the given interval @@ -1233,6 +1236,7 @@ explicit-defaults-for-timestamp FALSE external-locking FALSE extra-max-connections 1 extra-port 0 +flashback FALSE flush FALSE flush-time 0 ft-boolean-syntax + -><()~*:""&| diff --git a/mysql-test/suite/binlog/r/flashback.result b/mysql-test/suite/binlog/r/flashback.result new file mode 100644 index 00000000000..94833c5224a --- /dev/null +++ b/mysql-test/suite/binlog/r/flashback.result @@ -0,0 +1,480 @@ +# +# Preparatory cleanup. +# +DROP TABLE IF EXISTS t1; +# +# We need a fixed timestamp to avoid varying results. +# +SET timestamp=1000000000; +# +# Delete all existing binary logs. +# +RESET MASTER; +CREATE TABLE t1 ( +c01 tinyint, +c02 smallint, +c03 mediumint, +c04 int, +c05 bigint, +c06 char(10), +c07 varchar(20), +c08 TEXT +) ENGINE=InnoDB; +# +# Insert data to t1 +# +INSERT INTO t1 VALUES(0,0,0,0,0,'','',''); +INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz"); +INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 255)); +# +# Update t1 +# +UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3; +# +# Clear t1 +# +DELETE FROM t1; +FLUSH LOGS; +# +# Show mysqlbinlog result without -B +# +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +DELIMITER /*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Start: binlog v 4, server v #.##.## created 010909 9:46:40 at startup +ROLLBACK/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Gtid list [] +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Binlog checkpoint master-bin.000001 +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX GTID 0-1-1 ddl +/*!100101 SET @@session.skip_parallel_replication=0*//*!*/; +/*!100001 SET @@session.gtid_domain_id=0*//*!*/; +/*!100001 SET @@session.server_id=1*//*!*/; +/*!100001 SET @@session.gtid_seq_no=1*//*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Query thread_id=# exec_time=# error_code=0 +use `test`/*!*/; +SET TIMESTAMP=1000000000/*!*/; +SET @@session.pseudo_thread_id=#/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; +SET @@session.sql_mode=1342177280/*!*/; +SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; +/*!\C latin1 *//*!*/; +SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; +SET @@session.lc_time_names=0/*!*/; +SET @@session.collation_database=DEFAULT/*!*/; +CREATE TABLE t1 ( +c01 tinyint, +c02 smallint, +c03 mediumint, +c04 int, +c05 bigint, +c06 char(10), +c07 varchar(20), +c08 TEXT +) ENGINE=InnoDB +/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX GTID 0-1-2 trans +/*!100001 SET @@session.gtid_seq_no=2*//*!*/; +BEGIN +/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Write_rows: table id # flags: STMT_END_F +### INSERT INTO `test`.`t1` +### SET +### @1=0 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +COMMIT/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX GTID 0-1-3 trans +/*!100001 SET @@session.gtid_seq_no=3*//*!*/; +BEGIN +/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Write_rows: table id # flags: STMT_END_F +### INSERT INTO `test`.`t1` +### SET +### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +COMMIT/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX GTID 0-1-4 trans +/*!100001 SET @@session.gtid_seq_no=4*//*!*/; +BEGIN +/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Write_rows: table id # flags: STMT_END_F +### INSERT INTO `test`.`t1` +### SET +### @1=127 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=32767 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=8388607 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=2147483647 /* INT meta=0 nullable=1 is_null=0 */ +### @5=9223372036854775807 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='aaaaaaaaaa' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='aaaaaaaaaaaaaaaaaaaa' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +COMMIT/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX GTID 0-1-5 trans +/*!100001 SET @@session.gtid_seq_no=5*//*!*/; +BEGIN +/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Update_rows: table id # flags: STMT_END_F +### UPDATE `test`.`t1` +### WHERE +### @1=0 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### SET +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### UPDATE `test`.`t1` +### WHERE +### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### SET +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +COMMIT/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX GTID 0-1-6 trans +/*!100001 SET @@session.gtid_seq_no=6*//*!*/; +BEGIN +/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Delete_rows: table id # flags: STMT_END_F +### DELETE FROM `test`.`t1` +### WHERE +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### DELETE FROM `test`.`t1` +### WHERE +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### DELETE FROM `test`.`t1` +### WHERE +### @1=127 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=32767 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=8388607 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=2147483647 /* INT meta=0 nullable=1 is_null=0 */ +### @5=9223372036854775807 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='aaaaaaaaaa' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='aaaaaaaaaaaaaaaaaaaa' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +COMMIT/*!*/; +# at # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Rotate to master-bin.000002 pos: 4 +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; +# +# Show mysqlbinlog result with -B +# +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/; +/*!40019 SET @@session.max_insert_delayed_threads=0*/; +/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; +DELIMITER /*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Start: binlog v 4, server v #.##.## created 010909 9:46:40 at startup +ROLLBACK/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Gtid list [] +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Binlog checkpoint master-bin.000001 +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Table_map: `test`.`t1` mapped to number # +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Rotate to master-bin.000002 pos: 4 +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +BEGIN/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Write_rows: table id # flags: STMT_END_F +### INSERT INTO `test`.`t1` +### SET +### @1=127 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=32767 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=8388607 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=2147483647 /* INT meta=0 nullable=1 is_null=0 */ +### @5=9223372036854775807 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='aaaaaaaaaa' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='aaaaaaaaaaaaaaaaaaaa' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### INSERT INTO `test`.`t1` +### SET +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### INSERT INTO `test`.`t1` +### SET +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +COMMIT +/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +BEGIN/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Update_rows: table id # flags: STMT_END_F +### UPDATE `test`.`t1` +### WHERE +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### SET +### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### UPDATE `test`.`t1` +### WHERE +### @1=100 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +### SET +### @1=0 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +COMMIT +/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +BEGIN/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Delete_rows: table id # flags: STMT_END_F +### DELETE FROM `test`.`t1` +### WHERE +### @1=127 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=32767 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=8388607 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=2147483647 /* INT meta=0 nullable=1 is_null=0 */ +### @5=9223372036854775807 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='aaaaaaaaaa' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='aaaaaaaaaaaaaaaaaaaa' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +COMMIT +/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +BEGIN/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Delete_rows: table id # flags: STMT_END_F +### DELETE FROM `test`.`t1` +### WHERE +### @1=1 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=2 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=3 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=4 /* INT meta=0 nullable=1 is_null=0 */ +### @5=5 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='abc' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='abcdefg' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='abcedfghijklmnopqrstuvwxyz' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +COMMIT +/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Xid = # +BEGIN/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Delete_rows: table id # flags: STMT_END_F +### DELETE FROM `test`.`t1` +### WHERE +### @1=0 /* TINYINT meta=0 nullable=1 is_null=0 */ +### @2=0 /* SHORTINT meta=0 nullable=1 is_null=0 */ +### @3=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ +### @4=0 /* INT meta=0 nullable=1 is_null=0 */ +### @5=0 /* LONGINT meta=0 nullable=1 is_null=0 */ +### @6='' /* STRING(10) meta=65034 nullable=1 is_null=0 */ +### @7='' /* VARSTRING(20) meta=20 nullable=1 is_null=0 */ +### @8='' /* BLOB/TEXT meta=2 nullable=1 is_null=0 */ +COMMIT +/*!*/; +#010909 9:46:40 server id 1 end_log_pos # CRC32 XXX Query thread_id=# exec_time=# error_code=0 +use `test`/*!*/; +SET TIMESTAMP=1000000000/*!*/; +SET @@session.pseudo_thread_id=#/*!*/; +SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/; +SET @@session.sql_mode=1342177280/*!*/; +SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/; +/*!\C latin1 *//*!*/; +SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/; +SET @@session.lc_time_names=0/*!*/; +SET @@session.collation_database=DEFAULT/*!*/; +COMMIT +/*!*/; +DELIMITER ; +# End of log file +ROLLBACK /* added by mysqlbinlog */; +/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; +/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; +# +# Insert data to t1 +# +TRUNCATE TABLE t1; +INSERT INTO t1 VALUES(0,0,0,0,0,'','',''); +INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz"); +INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 60)); +# +# Delete all existing binary logs. +# +RESET MASTER; +SELECT * FROM t1; +c01 c02 c03 c04 c05 c06 c07 c08 +0 0 0 0 0 +1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz +127 32767 8388607 2147483647 9223372036854775807 aaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +# +# Operate some data +# +UPDATE t1 SET c01=20; +UPDATE t1 SET c02=200; +UPDATE t1 SET c03=2000; +DELETE FROM t1; +FLUSH LOGS; +# +# Flashback & Check the result +# +SELECT * FROM t1; +c01 c02 c03 c04 c05 c06 c07 c08 +127 32767 8388607 2147483647 9223372036854775807 aaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz +0 0 0 0 0 +RESET MASTER; +# +# UPDATE multi-rows in one event +# +BEGIN; +UPDATE t1 SET c01=10 WHERE c01=0; +UPDATE t1 SET c01=20 WHERE c01=10; +COMMIT; +FLUSH LOGS; +# +# Flashback & Check the result +# +SELECT * FROM t1; +c01 c02 c03 c04 c05 c06 c07 c08 +127 32767 8388607 2147483647 9223372036854775807 aaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz +0 0 0 0 0 +DROP TABLE t1; +# +# Self-referencing foreign keys +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3); +COMMIT; +SELECT * FROM t1; +a b +1 NULL +2 1 +3 2 +4 3 +RESET MASTER; +DELETE FROM t1 ORDER BY a DESC; +FLUSH LOGS; +# +# Flashback & Check the result +# +SELECT * FROM t1; +a b +1 NULL +2 1 +3 2 +4 3 +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/flashback-master.opt b/mysql-test/suite/binlog/t/flashback-master.opt new file mode 100644 index 00000000000..476efbe20ab --- /dev/null +++ b/mysql-test/suite/binlog/t/flashback-master.opt @@ -0,0 +1,2 @@ +--flashback +--timezone=GMT-8 diff --git a/mysql-test/suite/binlog/t/flashback.test b/mysql-test/suite/binlog/t/flashback.test new file mode 100644 index 00000000000..2f395a2a7b1 --- /dev/null +++ b/mysql-test/suite/binlog/t/flashback.test @@ -0,0 +1,163 @@ +--source include/have_log_bin.inc +--source include/have_innodb.inc + +--echo # +--echo # Preparatory cleanup. +--echo # +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo # +--echo # We need a fixed timestamp to avoid varying results. +--echo # +SET timestamp=1000000000; + +--echo # +--echo # Delete all existing binary logs. +--echo # +RESET MASTER; + + +CREATE TABLE t1 ( + c01 tinyint, + c02 smallint, + c03 mediumint, + c04 int, + c05 bigint, + c06 char(10), + c07 varchar(20), + c08 TEXT +) ENGINE=InnoDB; + +--echo # +--echo # Insert data to t1 +--echo # +INSERT INTO t1 VALUES(0,0,0,0,0,'','',''); +INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz"); +INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 255)); + + +--echo # +--echo # Update t1 +--echo # +UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3; + +--echo # +--echo # Clear t1 +--echo # +DELETE FROM t1; + +FLUSH LOGS; + +--echo # +--echo # Show mysqlbinlog result without -B +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ +--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001 + +--echo # +--echo # Show mysqlbinlog result with -B +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/ +--exec $MYSQL_BINLOG -B --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001 + +--echo # +--echo # Insert data to t1 +--echo # +TRUNCATE TABLE t1; +INSERT INTO t1 VALUES(0,0,0,0,0,'','',''); +INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz"); +INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 60)); + +--echo # +--echo # Delete all existing binary logs. +--echo # +RESET MASTER; +SELECT * FROM t1; + +--echo # +--echo # Operate some data +--echo # + +UPDATE t1 SET c01=20; +UPDATE t1 SET c02=200; +UPDATE t1 SET c03=2000; + +DELETE FROM t1; + +FLUSH LOGS; + +--echo # +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql;" + +SELECT * FROM t1; + +RESET MASTER; + +--echo # +--echo # UPDATE multi-rows in one event +--echo # +BEGIN; +UPDATE t1 SET c01=10 WHERE c01=0; +UPDATE t1 SET c01=20 WHERE c01=10; +COMMIT; + +FLUSH LOGS; + +--echo # +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql;" + +SELECT * FROM t1; + +DROP TABLE t1; + +--echo # +--echo # Self-referencing foreign keys +--echo # +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB; + +BEGIN; +INSERT INTO t1 VALUES (1, NULL); +INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3); +COMMIT; + +SELECT * FROM t1; + +# New binlog +RESET MASTER; + +DELETE FROM t1 ORDER BY a DESC; + +FLUSH LOGS; + +--echo # +--echo # Flashback & Check the result +--echo # + +let $MYSQLD_DATADIR= `select @@datadir`; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql +--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql;" + +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result index 1ca90bd626d..a7bae638012 100644 --- a/mysql-test/suite/wsrep/r/binlog_format.result +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -8,20 +8,20 @@ Variable_name Value binlog_format ROW SET binlog_format=STATEMENT; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +Warning 1105 MariaDB Galera and flashback does not support binlog format: STATEMENT SHOW WARNINGS; Level Code Message -Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +Warning 1105 MariaDB Galera and flashback does not support binlog format: STATEMENT SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format STATEMENT CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; SET binlog_format=MIXED; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: MIXED +Warning 1105 MariaDB Galera and flashback does not support binlog format: MIXED SHOW WARNINGS; Level Code Message -Warning 1105 MariaDB Galera does not support binlog format: MIXED +Warning 1105 MariaDB Galera and flashback does not support binlog format: MIXED SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format MIXED diff --git a/sql/log_event.cc b/sql/log_event.cc index 0af348ab453..893781223fb 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -300,17 +300,34 @@ public: constructor, but it would be possible to create a subclass holding the IO_CACHE itself. */ - Write_on_release_cache(IO_CACHE *cache, FILE *file, flag_set flags = 0) - : m_cache(cache), m_file(file), m_flags(flags) + Write_on_release_cache(IO_CACHE *cache, FILE *file, flag_set flags = 0, Log_event *ev = NULL) + : m_cache(cache), m_file(file), m_flags(flags), m_ev(ev) { reinit_io_cache(m_cache, WRITE_CACHE, 0L, FALSE, TRUE); } ~Write_on_release_cache() { +#ifdef MYSQL_CLIENT + if(m_ev == NULL) + { + copy_event_cache_to_file_and_reinit(m_cache, m_file); + if (m_flags & FLUSH_F) + fflush(m_file); + } + else // if m_ev<>NULL, then storing the output in output_buf + { + LEX_STRING tmp_str; + if (copy_event_cache_to_string_and_reinit(m_cache, &tmp_str)) + exit(1); + m_ev->output_buf.append(tmp_str.str, tmp_str.length); + my_free(tmp_str.str); + } +#else /* MySQL_SERVER */ copy_event_cache_to_file_and_reinit(m_cache, m_file); if (m_flags & FLUSH_F) fflush(m_file); +#endif } /* @@ -340,6 +357,7 @@ private: IO_CACHE *m_cache; FILE *m_file; flag_set m_flags; + Log_event *m_ev; // Used for Flashback }; /* @@ -2760,7 +2778,7 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr, d= (ulong) (i64 / 1000000); t= (ulong) (i64 % 1000000); - my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d", + my_b_printf(file, "'%04d-%02d-%02d %02d:%02d:%02d'", (int) (d / 10000), (int) (d % 10000) / 100, (int) (d % 100), (int) (t / 10000), (int) (t % 10000) / 100, (int) t % 100); return 8; @@ -2994,22 +3012,30 @@ size_t Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, PRINT_EVENT_INFO *print_event_info, MY_BITMAP *cols_bitmap, - const uchar *value, const uchar *prefix) + const uchar *value, const uchar *prefix, + const my_bool no_fill_output) { const uchar *value0= value; const uchar *null_bits= value; uint null_bit_index= 0; char typestr[64]= ""; - + +#ifdef WHEN_FLASHBACK_REVIEW_READY + /* Storing the review SQL */ + IO_CACHE *review_sql= &print_event_info->review_sql_cache; + LEX_STRING review_str; +#endif + /* Skip metadata bytes which gives the information about nullabity of master columns. Master writes one bit for each affected column. */ value+= (bitmap_bits_set(cols_bitmap) + 7) / 8; - - my_b_printf(file, "%s", prefix); - + + if (!no_fill_output) + my_b_printf(file, "%s", prefix); + for (size_t i= 0; i < td->size(); i ++) { size_t size; @@ -3018,47 +3044,226 @@ Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td, if (bitmap_is_set(cols_bitmap, i) == 0) continue; - - my_b_printf(file, "### @%d=", static_cast(i + 1)); + + if (!no_fill_output) + my_b_printf(file, "### @%d=", static_cast(i + 1)); + if (!is_null) { size_t fsize= td->calc_field_size((uint)i, (uchar*) value); if (value + fsize > m_rows_end) { - my_b_printf(file, "***Corrupted replication event was detected." - " Not printing the value***\n"); + if (!no_fill_output) + my_b_printf(file, "***Corrupted replication event was detected." + " Not printing the value***\n"); value+= fsize; return 0; } } - if (!(size= log_event_print_value(file,is_null? NULL: value, - td->type(i), td->field_metadata(i), - typestr, sizeof(typestr)))) + + if (!no_fill_output) + { + size= log_event_print_value(file,is_null? NULL: value, + td->type(i), td->field_metadata(i), + typestr, sizeof(typestr)); +#ifdef WHEN_FLASHBACK_REVIEW_READY + if (need_flashback_review) + { + String tmp_str, hex_str; + IO_CACHE tmp_cache; + + // Using a tmp IO_CACHE to get the value output + open_cached_file(&tmp_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)); + size= log_event_print_value(&tmp_cache, is_null? NULL: value, + td->type(i), td->field_metadata(i), + typestr, sizeof(typestr)); + if (copy_event_cache_to_string_and_reinit(&tmp_cache, &review_str)) + exit(1); + close_cached_file(&tmp_cache); + + switch (td->type(i)) // Converting a string to HEX format + { + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_BLOB: + // Avoid write_pos changed to a new area + // tmp_str.free(); + tmp_str.append(review_str.str + 1, review_str.length - 2); // Removing quotation marks + if (hex_str.alloc(tmp_str.length()*2+1)) // If out of memory + { + fprintf(stderr, "\nError: Out of memory. " + "Could not print correct binlog event.\n"); + exit(1); + } + octet2hex((char*) hex_str.ptr(), tmp_str.ptr(), tmp_str.length()); + my_b_printf(review_sql, ", UNHEX('%s')", hex_str.ptr()); + break; + default: + tmp_str.free(); + tmp_str.append(review_str.str, review_str.length); + my_b_printf(review_sql, ", %s", tmp_str.ptr()); + break; + } + my_free(revieww_str.str); + } +#endif + } + else + { + IO_CACHE tmp_cache; + open_cached_file(&tmp_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)); + size= log_event_print_value(&tmp_cache,is_null? NULL: value, + td->type(i), td->field_metadata(i), + typestr, sizeof(typestr)); + close_cached_file(&tmp_cache); + } + + if (!size) return 0; if (!is_null) value+= size; - if (print_event_info->verbose > 1) + if (print_event_info->verbose > 1 && !no_fill_output) { my_b_write(file, (uchar*)" /* ", 4); my_b_printf(file, "%s ", typestr); - + my_b_printf(file, "meta=%d nullable=%d is_null=%d ", td->field_metadata(i), td->maybe_null(i), is_null); my_b_write(file, (uchar*)"*/", 2); } - - my_b_write_byte(file, '\n'); - + + if (!no_fill_output) + my_b_write_byte(file, '\n'); + null_bit_index++; } return value - value0; } +/** + Exchange the SET part and WHERE part for the Update events. + Revert the operations order for the Write and Delete events. + And then revert the events order from the last one to the first one. + + @param[in] print_event_info PRINT_EVENT_INFO + @param[in] rows_buff Packed event buff +*/ + +void Rows_log_event::change_to_flashback_event(PRINT_EVENT_INFO *print_event_info, + uchar *rows_buff, Log_event_type ev_type) +{ + Table_map_log_event *map; + table_def *td; + DYNAMIC_ARRAY rows_arr; + uchar *swap_buff1, *swap_buff2; + uchar *rows_pos= rows_buff + m_rows_before_size; + + if (!(map= print_event_info->m_table_map.get_table(m_table_id)) || + !(td= map->create_table_def())) + return; + + /* If the write rows event contained no values for the AI */ + if (((get_general_type_code() == WRITE_ROWS_EVENT) && (m_rows_buf==m_rows_end))) + goto end; + + (void) my_init_dynamic_array(&rows_arr, sizeof(LEX_STRING), 8, 8, MYF(0)); + + for (uchar *value= m_rows_buf; value < m_rows_end; ) + { + uchar *start_pos= value; + size_t length1= 0; + if (!(length1= print_verbose_one_row(NULL, td, print_event_info, + &m_cols, value, + (const uchar*) "", TRUE))) + { + fprintf(stderr, "\nError row length: %zu\n", length1); + exit(1); + } + value+= length1; + + swap_buff1= (uchar *) my_malloc(length1, MYF(0)); + if (!swap_buff1) + { + fprintf(stderr, "\nError: Out of memory. " + "Could not exchange to flashback event.\n"); + exit(1); + } + memcpy(swap_buff1, start_pos, length1); + + // For Update_event, we have the second part + size_t length2= 0; + if (ev_type == UPDATE_ROWS_EVENT || + ev_type == UPDATE_ROWS_EVENT_V1) + { + if (!(length2= print_verbose_one_row(NULL, td, print_event_info, + &m_cols, value, + (const uchar*) "", TRUE))) + { + fprintf(stderr, "\nError row length: %zu\n", length2); + exit(1); + } + value+= length2; + + swap_buff2= (uchar *) my_malloc(length2, MYF(0)); + if (!swap_buff2) + { + fprintf(stderr, "\nError: Out of memory. " + "Could not exchange to flashback event.\n"); + exit(1); + } + memcpy(swap_buff2, start_pos + length1, length2); // WHERE part + } + + if (ev_type == UPDATE_ROWS_EVENT || + ev_type == UPDATE_ROWS_EVENT_V1) + { + /* Swap SET and WHERE part */ + memcpy(start_pos, swap_buff2, length2); + memcpy(start_pos + length2, swap_buff1, length1); + } + + /* Free tmp buffers */ + my_free(swap_buff1); + if (ev_type == UPDATE_ROWS_EVENT || + ev_type == UPDATE_ROWS_EVENT_V1) + my_free(swap_buff2); + + /* Copying one row into a buff, and pushing into the array */ + LEX_STRING one_row; + + one_row.length= length1 + length2; + one_row.str= (char *) my_malloc(one_row.length, MYF(0)); + memcpy(one_row.str, start_pos, one_row.length); + if (one_row.str == NULL || push_dynamic(&rows_arr, (uchar *) &one_row)) + { + fprintf(stderr, "\nError: Out of memory. " + "Could not push flashback event into array.\n"); + exit(1); + } + } + + /* Copying rows from the end to the begining into event */ + for (uint i= rows_arr.elements; i > 0; --i) + { + LEX_STRING *one_row= dynamic_element(&rows_arr, i - 1, LEX_STRING*); + + memcpy(rows_pos, (uchar *)one_row->str, one_row->length); + rows_pos+= one_row->length; + my_free(one_row->str); + } + delete_dynamic(&rows_arr); + +end: + delete td; +} + + /** Print a row event into IO cache in human readable form (in SQL format) @@ -3071,8 +3276,12 @@ void Rows_log_event::print_verbose(IO_CACHE *file, Table_map_log_event *map; table_def *td; const char *sql_command, *sql_clause1, *sql_clause2; + const char *sql_command_short __attribute__((unused)); Log_event_type general_type_code= get_general_type_code(); - +#ifdef WHEN_FLASHBACK_REVIEW_READY + IO_CACHE *review_sql= &print_event_info->review_sql_cache; +#endif + if (m_extra_row_data) { uint8 extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET]; @@ -3102,19 +3311,23 @@ void Rows_log_event::print_verbose(IO_CACHE *file, sql_command= "INSERT INTO"; sql_clause1= "### SET\n"; sql_clause2= NULL; + sql_command_short= "I"; break; case DELETE_ROWS_EVENT: sql_command= "DELETE FROM"; sql_clause1= "### WHERE\n"; sql_clause2= NULL; + sql_command_short= "D"; break; case UPDATE_ROWS_EVENT: sql_command= "UPDATE"; sql_clause1= "### WHERE\n"; sql_clause2= "### SET\n"; + sql_command_short= "U"; break; default: sql_command= sql_clause1= sql_clause2= NULL; + sql_command_short= ""; DBUG_ASSERT(0); /* Not possible */ } @@ -3140,6 +3353,13 @@ void Rows_log_event::print_verbose(IO_CACHE *file, my_b_printf(file, "### %s %`s.%`s\n", sql_command, map->get_db_name(), map->get_table_name()); + +#ifdef WHEN_FLASHBACK_REVIEW_READY + if (need_flashback_review) + my_b_printf(review_sql, "\nINSERT INTO `%s`.`%s` VALUES ('%s'", + map->get_review_dbname(), map->get_review_tablename(), sql_command_short); +#endif + /* Print the first image */ if (!(length= print_verbose_one_row(file, td, print_event_info, &m_cols, value, @@ -3156,6 +3376,17 @@ void Rows_log_event::print_verbose(IO_CACHE *file, goto end; value+= length; } +#ifdef WHEN_FLASHBACK_REVIEW_READY + else + { + if (need_flashback_review) + for (size_t i= 0; i < td->size(); i ++) + my_b_printf(review_sql, ", NULL"); + } + + if (need_flashback_review) + my_b_printf(review_sql, ")%s\n", print_event_info->delimiter); +#endif } end: @@ -3171,7 +3402,7 @@ void Log_event::print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool more) { - const uchar *ptr= (const uchar *)temp_buf; + uchar *ptr= (uchar *)temp_buf; uint32 size= uint4korr(ptr + EVENT_LEN_OFFSET); DBUG_ENTER("Log_event::print_base64"); @@ -3183,6 +3414,51 @@ void Log_event::print_base64(IO_CACHE* file, DBUG_VOID_RETURN; } + if (is_flashback) + { + uint tmp_size= size; + Rows_log_event *ev= NULL; + Log_event_type ev_type = (enum Log_event_type) ptr[EVENT_TYPE_OFFSET]; + if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF && + checksum_alg != BINLOG_CHECKSUM_ALG_OFF) + tmp_size-= BINLOG_CHECKSUM_LEN; // checksum is displayed through the header + switch (ev_type) { + case WRITE_ROWS_EVENT: + ptr[EVENT_TYPE_OFFSET]= DELETE_ROWS_EVENT; + ev= new Delete_rows_log_event((const char*) ptr, tmp_size, + glob_description_event); + ev->change_to_flashback_event(print_event_info, ptr, ev_type); + break; + case WRITE_ROWS_EVENT_V1: + ptr[EVENT_TYPE_OFFSET]= DELETE_ROWS_EVENT_V1; + ev= new Delete_rows_log_event((const char*) ptr, tmp_size, + glob_description_event); + ev->change_to_flashback_event(print_event_info, ptr, ev_type); + break; + case DELETE_ROWS_EVENT: + ptr[EVENT_TYPE_OFFSET]= WRITE_ROWS_EVENT; + ev= new Write_rows_log_event((const char*) ptr, tmp_size, + glob_description_event); + ev->change_to_flashback_event(print_event_info, ptr, ev_type); + break; + case DELETE_ROWS_EVENT_V1: + ptr[EVENT_TYPE_OFFSET]= WRITE_ROWS_EVENT_V1; + ev= new Write_rows_log_event((const char*) ptr, tmp_size, + glob_description_event); + ev->change_to_flashback_event(print_event_info, ptr, ev_type); + break; + case UPDATE_ROWS_EVENT: + case UPDATE_ROWS_EVENT_V1: + ev= new Update_rows_log_event((const char*) ptr, tmp_size, + glob_description_event); + ev->change_to_flashback_event(print_event_info, ptr, ev_type); + break; + default: + break; + } + delete ev; + } + if (my_base64_encode(ptr, (size_t) size, tmp_str)) { DBUG_ASSERT(0); @@ -3198,8 +3474,12 @@ void Log_event::print_base64(IO_CACHE* file, if (!more) my_b_printf(file, "'%s\n", print_event_info->delimiter); } - + +#ifdef WHEN_FLASHBACK_REVIEW_READY + if (print_event_info->verbose || need_flashback_review) +#else if (print_event_info->verbose) +#endif { Rows_log_event *ev= NULL; Log_event_type et= (Log_event_type) ptr[EVENT_TYPE_OFFSET]; @@ -3207,7 +3487,7 @@ void Log_event::print_base64(IO_CACHE* file, if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF && checksum_alg != BINLOG_CHECKSUM_ALG_OFF) size-= BINLOG_CHECKSUM_LEN; // checksum is displayed through the header - + switch (et) { case TABLE_MAP_EVENT: @@ -3215,6 +3495,13 @@ void Log_event::print_base64(IO_CACHE* file, Table_map_log_event *map; map= new Table_map_log_event((const char*) ptr, size, glob_description_event); +#ifdef WHEN_FLASHBACK_REVIEW_READY + if (need_flashback_review) + { + map->set_review_dbname(m_review_dbname.ptr()); + map->set_review_tablename(m_review_tablename.ptr()); + } +#endif print_event_info->m_table_map.set_table(map->get_table_id(), map); break; } @@ -3263,14 +3550,27 @@ void Log_event::print_base64(IO_CACHE* file, default: break; } - + if (ev) { +#ifdef WHEN_FLASHBACK_REVIEW_READY + ev->need_flashback_review= need_flashback_review; + if (print_event_info->verbose) + ev->print_verbose(file, print_event_info); + else + { + IO_CACHE tmp_cache; + open_cached_file(&tmp_cache, NULL, NULL, 0, MYF(MY_WME | MY_NABP)); + ev->print_verbose(&tmp_cache, print_event_info); + close_cached_file(&tmp_cache); + } +#else ev->print_verbose(file, print_event_info); +#endif delete ev; } } - + my_free(tmp_str); DBUG_VOID_RETURN; } @@ -4631,7 +4931,7 @@ void Query_log_event::print_query_header(IO_CACHE* file, void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { - Write_on_release_cache cache(&print_event_info->head_cache, file); + Write_on_release_cache cache(&print_event_info->head_cache, file, 0, this); /** reduce the size of io cache so that the write function is called @@ -4640,8 +4940,24 @@ void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) DBUG_EXECUTE_IF ("simulate_file_write_error", {(&cache)->write_pos= (&cache)->write_end- 500;}); print_query_header(&cache, print_event_info); - my_b_write(&cache, (uchar*) query, q_len); - my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + if (!is_flashback) + { + my_b_write(&cache, (uchar*) query, q_len); + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + } + else // is_flashback == 1 + { + if (strcmp("BEGIN", query) == 0) + { + my_b_write(&cache, (uchar*) "COMMIT", 6); + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + } + else if (strcmp("COMMIT", query) == 0) + { + my_b_write(&cache, (uchar*) "BEGIN", 5); + my_b_printf(&cache, "\n%s\n", print_event_info->delimiter); + } + } } #endif /* MYSQL_CLIENT */ @@ -7351,11 +7667,11 @@ void Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, - Write_on_release_cache::FLUSH_F); + Write_on_release_cache::FLUSH_F, this); char buf[21]; char buf2[21]; - if (!print_event_info->short_form) + if (!print_event_info->short_form & !is_flashback) { print_header(&cache, print_event_info, FALSE); longlong10_to_str(seq_no, buf, 10); @@ -7401,11 +7717,12 @@ Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) print_event_info->server_id_printed= true; } - my_b_printf(&cache, "/*!100001 SET @@session.gtid_seq_no=%s*/%s\n", - buf, print_event_info->delimiter); + if (!is_flashback) + my_b_printf(&cache, "/*!100001 SET @@session.gtid_seq_no=%s*/%s\n", + buf, print_event_info->delimiter); } if (!(flags2 & FL_STANDALONE)) - my_b_printf(&cache, "BEGIN\n%s\n", print_event_info->delimiter); + my_b_printf(&cache, is_flashback ? "COMMIT\n%s\n" : "BEGIN\n%s\n", print_event_info->delimiter); } #endif /* MYSQL_SERVER */ @@ -8047,7 +8364,7 @@ bool Xid_log_event::write() void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, - Write_on_release_cache::FLUSH_F); + Write_on_release_cache::FLUSH_F, this); if (!print_event_info->short_form) { @@ -8057,7 +8374,7 @@ void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) print_header(&cache, print_event_info, FALSE); my_b_printf(&cache, "\tXid = %s\n", buf); } - my_b_printf(&cache, "COMMIT%s\n", print_event_info->delimiter); + my_b_printf(&cache, is_flashback ? "BEGIN%s\n" : "COMMIT%s\n", print_event_info->delimiter); } #endif /* MYSQL_CLIENT */ @@ -8706,7 +9023,7 @@ void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info) { Write_on_release_cache cache(&print_event_info->head_cache, file, - Write_on_release_cache::FLUSH_F); + Write_on_release_cache::FLUSH_F, this); if (print_event_info->short_form) return; @@ -10042,6 +10359,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len, m_rows_end= m_rows_buf + data_size; m_rows_cur= m_rows_end; memcpy(m_rows_buf, ptr_rows_data, data_size); + m_rows_before_size= ptr_rows_data - (const uchar *) buf; // Get the size that before SET part } else m_cols.bitmap= 0; // to not free it @@ -10958,6 +11276,10 @@ void Rows_log_event::print_helper(FILE *file, { IO_CACHE *const head= &print_event_info->head_cache; IO_CACHE *const body= &print_event_info->body_cache; +#ifdef WHEN_FLASHBACK_REVIEW_READY + IO_CACHE *const sql= &print_event_info->review_sql_cache; +#endif + if (!print_event_info->short_form) { bool const last_stmt_event= get_flags(STMT_END_F); @@ -10970,8 +11292,19 @@ void Rows_log_event::print_helper(FILE *file, if (get_flags(STMT_END_F)) { - copy_event_cache_to_file_and_reinit(head, file); - copy_event_cache_to_file_and_reinit(body, file); + reinit_io_cache(head, READ_CACHE, 0L, FALSE, FALSE); + output_buf.append(head, head->end_of_file); + reinit_io_cache(head, WRITE_CACHE, 0, FALSE, TRUE); + + reinit_io_cache(body, READ_CACHE, 0L, FALSE, FALSE); + output_buf.append(body, body->end_of_file); + reinit_io_cache(body, WRITE_CACHE, 0, FALSE, TRUE); + +#ifdef WHEN_FLASHBACK_REVIEW_READY + reinit_io_cache(sql, READ_CACHE, 0L, FALSE, FALSE); + output_buf.append(sql, sql->end_of_file); + reinit_io_cache(sql, WRITE_CACHE, 0, FALSE, TRUE); +#endif } } #endif @@ -12374,7 +12707,7 @@ void Write_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { DBUG_EXECUTE_IF("simulate_cache_read_error", {DBUG_SET("+d,simulate_my_b_fill_error");}); - Rows_log_event::print_helper(file, print_event_info, "Write_rows"); + Rows_log_event::print_helper(file, print_event_info, is_flashback ? "Delete_rows" : "Write_rows"); } void Write_rows_compressed_log_event::print(FILE *file, @@ -13048,7 +13381,7 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi) void Delete_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info) { - Rows_log_event::print_helper(file, print_event_info, "Delete_rows"); + Rows_log_event::print_helper(file, print_event_info, is_flashback ? "Write_rows" : "Delete_rows"); } void Delete_rows_compressed_log_event::print(FILE *file, @@ -13600,6 +13933,9 @@ st_print_event_info::st_print_event_info() myf const flags = MYF(MY_WME | MY_NABP); open_cached_file(&head_cache, NULL, NULL, 0, flags); open_cached_file(&body_cache, NULL, NULL, 0, flags); +#ifdef WHEN_FLASHBACK_REVIEW_READY + open_cached_file(&review_sql_cache, NULL, NULL, 0, flags); +#endif } #endif diff --git a/sql/log_event.h b/sql/log_event.h index 7b8704636af..c2829a9bb10 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -41,6 +41,7 @@ #include "rpl_utility.h" #include "hash.h" #include "rpl_tblmap.h" +#include "sql_string.h" #endif #ifdef MYSQL_SERVER @@ -52,7 +53,9 @@ #include "rpl_gtid.h" /* Forward declarations */ +#ifndef MYSQL_CLIENT class String; +#endif #define PREFIX_SQL_LOAD "SQL_LOAD-" #define LONG_FIND_ROW_THRESHOLD 60 /* seconds */ @@ -845,9 +848,16 @@ typedef struct st_print_event_info ~st_print_event_info() { close_cached_file(&head_cache); close_cached_file(&body_cache); +#ifdef WHEN_FLASHBACK_REVIEW_READY + close_cached_file(&review_sql_cache); +#endif } bool init_ok() /* tells if construction was successful */ - { return my_b_inited(&head_cache) && my_b_inited(&body_cache); } + { return my_b_inited(&head_cache) && my_b_inited(&body_cache) +#ifdef WHEN_FLASHBACK_REVIEW_READY + && my_b_inited(&review_sql_cache) +#endif + ; } /* Settings on how to print the events */ @@ -875,6 +885,10 @@ typedef struct st_print_event_info */ IO_CACHE head_cache; IO_CACHE body_cache; +#ifdef WHEN_FLASHBACK_REVIEW_READY + /* Storing the SQL for reviewing */ + IO_CACHE review_sql_cache; +#endif } PRINT_EVENT_INFO; #endif @@ -1223,6 +1237,37 @@ public: void print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info, bool is_more); #endif + + /* The following code used for Flashback */ +#ifdef MYSQL_CLIENT + my_bool is_flashback; + my_bool need_flashback_review; + String output_buf; // Storing the event output +#ifdef WHEN_FLASHBACK_REVIEW_READY + String m_review_dbname; + String m_review_tablename; + + void set_review_dbname(const char *name) + { + if (name) + { + m_review_dbname.free(); + m_review_dbname.append(name); + } + } + void set_review_tablename(const char *name) + { + if (name) + { + m_review_tablename.free(); + m_review_tablename.append(name); + } + } + const char *get_review_dbname() const { return m_review_dbname.ptr(); } + const char *get_review_tablename() const { return m_review_tablename.ptr(); } +#endif +#endif + /* read_log_event() functions read an event from a binlog or relay log; used by SHOW BINLOG EVENTS, the binlog_dump thread on the @@ -4362,12 +4407,14 @@ public: #ifdef MYSQL_CLIENT /* not for direct call, each derived has its own ::print() */ virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info)= 0; + void change_to_flashback_event(PRINT_EVENT_INFO *print_event_info, uchar *rows_buff, Log_event_type ev_type); void print_verbose(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info); size_t print_verbose_one_row(IO_CACHE *file, table_def *td, PRINT_EVENT_INFO *print_event_info, MY_BITMAP *cols_bitmap, - const uchar *ptr, const uchar *prefix); + const uchar *ptr, const uchar *prefix, + const my_bool no_fill_output= 0); // if no_fill_output=1, then print result is unnecessary #endif #ifdef MYSQL_SERVER @@ -4506,6 +4553,8 @@ protected: uchar *m_rows_cur; /* One-after the end of the data */ uchar *m_rows_end; /* One-after the end of the allocated space */ + size_t m_rows_before_size; /* The length before m_rows_buf */ + flag_set m_flags; /* Flags for row-level events */ Log_event_type m_type; /* Actual event type */ @@ -5040,6 +5089,29 @@ public: }; +static inline bool copy_event_cache_to_string_and_reinit(IO_CACHE *cache, LEX_STRING *to) +{ + String tmp; + + reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE); + if (tmp.append(cache, cache->end_of_file)) + goto err; + reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE); + + /* + Can't change the order, because the String::release() will clear the + length. + */ + to->length= tmp.length(); + to->str= tmp.release(); + + return false; + +err: + perror("Out of memory: can't allocate memory in copy_event_cache_to_string_and_reinit()."); + return true; +} + static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8930bf930d1..23ac568d95e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -393,7 +393,7 @@ bool opt_bin_log_compress; uint opt_bin_log_compress_min_len; my_bool opt_log, debug_assert_if_crashed_table= 0, opt_help= 0; my_bool debug_assert_on_not_freed_memory= 0; -my_bool disable_log_notes; +my_bool disable_log_notes, opt_support_flashback= 0; static my_bool opt_abort; ulonglong log_output_options; my_bool opt_userstat_running; @@ -7413,6 +7413,10 @@ struct my_option my_long_options[]= 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, /* We must always support the next option to make scripts like mysqltest easier to do */ + {"flashback", 0, + "Setup the server to use flashback. This enables binary log in row mode and will enable extra logging for DDL's needed by flashback feature", + &opt_support_flashback, &opt_support_flashback, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"gdb", 0, "Set up signals usable for debugging. Deprecated, use --debug-gdb instead.", &opt_debugging, &opt_debugging, @@ -9587,6 +9591,18 @@ static int get_options(int *argc_ptr, char ***argv_ptr) else global_system_variables.option_bits&= ~OPTION_BIG_SELECTS; + if (opt_support_flashback) + { + /* Force binary logging */ + if (!opt_bin_logname) + opt_bin_logname= (char*) ""; // Use default name + opt_bin_log= opt_bin_log_used= 1; + + /* Force format to row */ + binlog_format_used= 1; + global_system_variables.binlog_format= BINLOG_FORMAT_ROW; + } + if (!opt_bootstrap && WSREP_PROVIDER_EXISTS && global_system_variables.binlog_format != BINLOG_FORMAT_ROW) { diff --git a/sql/mysqld.h b/sql/mysqld.h index 96944c012ce..9022b8cef03 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -114,6 +114,7 @@ extern uint opt_bin_log_compress_min_len; extern my_bool opt_log, opt_bootstrap; extern my_bool opt_backup_history_log; extern my_bool opt_backup_progress_log; +extern my_bool opt_support_flashback; extern ulonglong log_output_options; extern ulong log_backup_output_options; extern my_bool opt_log_queries_not_using_indexes; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 56913092354..057e18f8f06 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -449,16 +449,17 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) /* MariaDB Galera does not support STATEMENT or MIXED binlog format currently. */ - if (WSREP(thd) && var->save_result.ulonglong_value != BINLOG_FORMAT_ROW) + if ((WSREP(thd) || opt_support_flashback) && + var->save_result.ulonglong_value != BINLOG_FORMAT_ROW) { // Push a warning to the error log. push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, - "MariaDB Galera does not support binlog format: %s", + "MariaDB Galera and flashback does not support binlog format: %s", binlog_format_names[var->save_result.ulonglong_value]); if (var->type == OPT_GLOBAL) { - WSREP_ERROR("MariaDB Galera does not support binlog format: %s", + WSREP_ERROR("MariaDB Galera and flashback does not support binlog format: %s", binlog_format_names[var->save_result.ulonglong_value]); return true; } From 4a14356efdc5e62b3e13cbe7a56ffd1a4717a524 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 22 Jan 2017 03:15:46 +0200 Subject: [PATCH 099/167] Disable vcol.vcol_keys_myisam until MDEV-11836 is fixed --- mysql-test/suite/vcol/disabled.def | 1 + 1 file changed, 1 insertion(+) create mode 100644 mysql-test/suite/vcol/disabled.def diff --git a/mysql-test/suite/vcol/disabled.def b/mysql-test/suite/vcol/disabled.def new file mode 100644 index 00000000000..86480ca3a4c --- /dev/null +++ b/mysql-test/suite/vcol/disabled.def @@ -0,0 +1 @@ +vcol_keys_myisam : MDEV-11836 From beeacd228792a082bbb6c2c12c9fea543a7a2394 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 22 Jan 2017 03:32:20 +0200 Subject: [PATCH 100/167] Follow-up for MDEV-11065 - add tests for compressed+encrypted binlog --- .../binlog_encryption/binlog_row_annotate.combinations | 6 ++++++ mysql-test/suite/binlog_encryption/mysqlbinlog.combinations | 6 ++++++ .../suite/binlog_encryption/rpl_gtid_basic.combinations | 6 ++++++ 3 files changed, 18 insertions(+) create mode 100644 mysql-test/suite/binlog_encryption/binlog_row_annotate.combinations create mode 100644 mysql-test/suite/binlog_encryption/mysqlbinlog.combinations create mode 100644 mysql-test/suite/binlog_encryption/rpl_gtid_basic.combinations diff --git a/mysql-test/suite/binlog_encryption/binlog_row_annotate.combinations b/mysql-test/suite/binlog_encryption/binlog_row_annotate.combinations new file mode 100644 index 00000000000..710c53d0ace --- /dev/null +++ b/mysql-test/suite/binlog_encryption/binlog_row_annotate.combinations @@ -0,0 +1,6 @@ +[cmpr] +log-bin-compress=1 +log-bin-compress-min-len=10 + +[ncmpr] +log-bin-compress=0 diff --git a/mysql-test/suite/binlog_encryption/mysqlbinlog.combinations b/mysql-test/suite/binlog_encryption/mysqlbinlog.combinations new file mode 100644 index 00000000000..710c53d0ace --- /dev/null +++ b/mysql-test/suite/binlog_encryption/mysqlbinlog.combinations @@ -0,0 +1,6 @@ +[cmpr] +log-bin-compress=1 +log-bin-compress-min-len=10 + +[ncmpr] +log-bin-compress=0 diff --git a/mysql-test/suite/binlog_encryption/rpl_gtid_basic.combinations b/mysql-test/suite/binlog_encryption/rpl_gtid_basic.combinations new file mode 100644 index 00000000000..710c53d0ace --- /dev/null +++ b/mysql-test/suite/binlog_encryption/rpl_gtid_basic.combinations @@ -0,0 +1,6 @@ +[cmpr] +log-bin-compress=1 +log-bin-compress-min-len=10 + +[ncmpr] +log-bin-compress=0 From 31031a52da6e88d27c3149b06d9beb9704d0b96c Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 22 Jan 2017 17:46:33 +0200 Subject: [PATCH 101/167] MDEV-11870 Message "MariaDB Galera and flashback does not support" Fixed the typo, updated result file and suppression in the test file which did not work anyway --- mysql-test/suite/wsrep/r/binlog_format.result | 10 +++++----- mysql-test/suite/wsrep/t/binlog_format.test | 2 +- sql/sys_vars.cc | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/wsrep/r/binlog_format.result b/mysql-test/suite/wsrep/r/binlog_format.result index a7bae638012..83af2b67762 100644 --- a/mysql-test/suite/wsrep/r/binlog_format.result +++ b/mysql-test/suite/wsrep/r/binlog_format.result @@ -1,4 +1,4 @@ -call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); +call mtr.add_suppression("WSREP: MariaDB Galera and flashback do not support binlog format.*"); call mtr.add_suppression("WSREP: Cannot get fake transaction ID from storage engine."); # # MDEV-4227: Galera server should stop crashing on setting binlog_format STATEMENT @@ -8,20 +8,20 @@ Variable_name Value binlog_format ROW SET binlog_format=STATEMENT; Warnings: -Warning 1105 MariaDB Galera and flashback does not support binlog format: STATEMENT +Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT SHOW WARNINGS; Level Code Message -Warning 1105 MariaDB Galera and flashback does not support binlog format: STATEMENT +Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format STATEMENT CREATE TABLE IF NOT EXISTS test.t1 AS SELECT * FROM information_schema.routines WHERE 1 = 0; SET binlog_format=MIXED; Warnings: -Warning 1105 MariaDB Galera and flashback does not support binlog format: MIXED +Warning 1105 MariaDB Galera and flashback do not support binlog format: MIXED SHOW WARNINGS; Level Code Message -Warning 1105 MariaDB Galera and flashback does not support binlog format: MIXED +Warning 1105 MariaDB Galera and flashback do not support binlog format: MIXED SHOW VARIABLES LIKE 'binlog_format'; Variable_name Value binlog_format MIXED diff --git a/mysql-test/suite/wsrep/t/binlog_format.test b/mysql-test/suite/wsrep/t/binlog_format.test index 85864256862..02602b9cb2b 100644 --- a/mysql-test/suite/wsrep/t/binlog_format.test +++ b/mysql-test/suite/wsrep/t/binlog_format.test @@ -1,7 +1,7 @@ --source include/have_wsrep_provider.inc --source include/have_binlog_format_row.inc -call mtr.add_suppression("WSREP: MariaDB Galera does not support binlog format.*"); +call mtr.add_suppression("WSREP: MariaDB Galera and flashback do not support binlog format.*"); call mtr.add_suppression("WSREP: Cannot get fake transaction ID from storage engine."); --echo # diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 057e18f8f06..c21fc4f7f49 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -454,12 +454,12 @@ static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) { // Push a warning to the error log. push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, - "MariaDB Galera and flashback does not support binlog format: %s", + "MariaDB Galera and flashback do not support binlog format: %s", binlog_format_names[var->save_result.ulonglong_value]); if (var->type == OPT_GLOBAL) { - WSREP_ERROR("MariaDB Galera and flashback does not support binlog format: %s", + WSREP_ERROR("MariaDB Galera and flashback do not support binlog format: %s", binlog_format_names[var->save_result.ulonglong_value]); return true; } From 45e40892c5bcd541cd93aebe8ba15b7a27289621 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 23 Jan 2017 22:25:29 +0400 Subject: [PATCH 102/167] MDEV-11134 Assertion `fixed' failed in Item::const_charset_converter(THD*, CHARSET_INFO*, bool, const char*) Problem: Item_param::basic_const_item() returned true when fixed==false. This unexpected combination made Item::const_charset_converter() crash on asserts. Fix: - Changing all Item_param::set_xxx() to set "fixed" to true. This fixes the problem. - Additionally, changing all Item_param::set_xxx() to set Item_param::item_type, to avoid duplicate code, and for consistency, to make the code symmetric between different constant types. Before this patch only set_null() set item_type. - Moving Item_param::state and Item_param::item_type from public to private, to make sure easier that these members are in sync with "fixed" and to each other. - Adding a new argument "unsigned_arg" to Item::set_decimal(), and reusing it in two places instead of duplicate code. - Adding a new method Item_param::fix_temporal() and reusing it in two places. - Adding methods has_no_value(), has_long_data_value(), has_int_value(), instead of direct access to Item_param::state. --- mysql-test/r/default.result | 38 +++++++++++++++++++ mysql-test/t/default.test | 30 +++++++++++++++ sql/item.cc | 69 ++++++++++++++++++--------------- sql/item.h | 76 ++++++++++++++++++++++++++++++++++--- sql/sql_prepare.cc | 35 ++++++----------- 5 files changed, 188 insertions(+), 60 deletions(-) diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index ac449d44fee..ded0bbb3cbd 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -3278,6 +3278,44 @@ INSERT INTO t1 VALUES (1),(2),(3); EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING DEFAULT,DEFAULT; ERROR HY000: Default/ignore value is not supported for such parameter usage DROP TABLE t1; +# +# MDEV-11134 Assertion `fixed' failed in Item::const_charset_converter(THD*, CHARSET_INFO*, bool, const char*) +# +SET NAMES utf8; +PREPARE stmt FROM "CREATE OR REPLACE TABLE t1 (c CHAR(8) DEFAULT ?)"; +SET @a=''; +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(8) DEFAULT '' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET @a='A'; +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(8) DEFAULT 'A' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET @a=_utf8 0xC380; +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c` char(8) DEFAULT 'À' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +SET @a=_utf8 0xD18F; +EXECUTE stmt USING @a; +ERROR 42000: Invalid default value for 'c' +EXECUTE stmt USING @a; +ERROR 42000: Invalid default value for 'c' +DEALLOCATE PREPARE stmt; # end of 10.2 test set sql_mode=ansi_quotes; create table t1 (a int, b int default (a+1)); diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index 9ae088405fa..af089f8dc94 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -2013,6 +2013,36 @@ EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING DEFA DROP TABLE t1; +--echo # +--echo # MDEV-11134 Assertion `fixed' failed in Item::const_charset_converter(THD*, CHARSET_INFO*, bool, const char*) +--echo # + +SET NAMES utf8; +PREPARE stmt FROM "CREATE OR REPLACE TABLE t1 (c CHAR(8) DEFAULT ?)"; +SET @a=''; +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET @a='A'; +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET @a=_utf8 0xC380; # LATIN CAPITAL LETTER A WITH GRAVE +EXECUTE stmt USING @a; +EXECUTE stmt USING @a; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET @a=_utf8 0xD18F; # Cyrillic letter into a latin1 column +--error ER_INVALID_DEFAULT +EXECUTE stmt USING @a; +--error ER_INVALID_DEFAULT +EXECUTE stmt USING @a; +DEALLOCATE PREPARE stmt; + + + --echo # end of 10.2 test # diff --git a/sql/item.cc b/sql/item.cc index 8698b0f7fa4..bab49115482 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3309,9 +3309,9 @@ Item_param::Item_param(THD *thd, uint pos_in_query_arg): Rewritable_query_parameter(pos_in_query_arg, 1), Type_handler_hybrid_field_type(MYSQL_TYPE_VARCHAR), state(NO_VALUE), - indicators(0), indicator(STMT_INDICATOR_NONE), /* Don't pretend to be a literal unless value for this item is set. */ item_type(PARAM_ITEM), + indicators(0), indicator(STMT_INDICATOR_NONE), set_param_func(default_set_param_func), m_out_param_info(NULL) { @@ -3338,7 +3338,7 @@ void Item_param::set_null() max_length= 0; decimals= 0; state= NULL_VALUE; - item_type= Item::NULL_ITEM; + fix_type(Item::NULL_ITEM); DBUG_VOID_RETURN; } @@ -3350,6 +3350,7 @@ void Item_param::set_int(longlong i, uint32 max_length_arg) max_length= max_length_arg; decimals= 0; maybe_null= 0; + fix_type(Item::INT_ITEM); DBUG_VOID_RETURN; } @@ -3361,6 +3362,7 @@ void Item_param::set_double(double d) max_length= DBL_DIG + 8; decimals= NOT_FIXED_DEC; maybe_null= 0; + fix_type(Item::REAL_ITEM); DBUG_VOID_RETURN; } @@ -3390,21 +3392,41 @@ void Item_param::set_decimal(const char *str, ulong length) my_decimal_precision_to_length_no_truncation(decimal_value.precision(), decimals, unsigned_flag); maybe_null= 0; + fix_type(Item::DECIMAL_ITEM); DBUG_VOID_RETURN; } -void Item_param::set_decimal(const my_decimal *dv) +void Item_param::set_decimal(const my_decimal *dv, bool unsigned_arg) { state= DECIMAL_VALUE; my_decimal2decimal(dv, &decimal_value); decimals= (uint8) decimal_value.frac; - unsigned_flag= !decimal_value.sign(); + unsigned_flag= unsigned_arg; max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, decimals, unsigned_flag); + fix_type(Item::DECIMAL_ITEM); } + +void Item_param::fix_temporal(uint32 max_length_arg, uint decimals_arg) +{ + state= TIME_VALUE; + max_length= max_length_arg; + decimals= decimals_arg; + fix_type(Item::DATE_ITEM); +} + + +void Item_param::set_time(const MYSQL_TIME *tm, + uint32 max_length_arg, uint decimals_arg) +{ + value.time= *tm; + fix_temporal(max_length_arg, decimals_arg); +} + + /** Set parameter value from MYSQL_TIME value. @@ -3433,11 +3455,9 @@ void Item_param::set_time(MYSQL_TIME *tm, timestamp_type time_type, &str, time_type, 0); set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR); } - - state= TIME_VALUE; maybe_null= 0; - max_length= max_length_arg; - decimals= tm->second_part > 0 ? TIME_SECOND_PART_DIGITS : 0; + fix_temporal(max_length_arg, + tm->second_part > 0 ? TIME_SECOND_PART_DIGITS : 0); DBUG_VOID_RETURN; } @@ -3458,6 +3478,7 @@ bool Item_param::set_str(const char *str, ulong length) maybe_null= 0; /* max_length and decimals are set after charset conversion */ /* sic: str may be not null-terminated, don't add DBUG_PRINT here */ + fix_type(Item::STRING_ITEM); DBUG_RETURN(FALSE); } @@ -3489,6 +3510,7 @@ bool Item_param::set_longdata(const char *str, ulong length) DBUG_RETURN(TRUE); state= LONG_DATA_VALUE; maybe_null= 0; + fix_type(Item::STRING_ITEM); DBUG_RETURN(FALSE); } @@ -3547,7 +3569,6 @@ bool Item_param::set_from_item(THD *thd, Item *item) { unsigned_flag= item->unsigned_flag; set_int(val, MY_INT64_NUM_DECIMAL_DIGITS); - item_type= Item::INT_ITEM; set_handler_by_result_type(item->result_type()); DBUG_RETURN(!unsigned_flag && value.integer < 0 ? 1 : 0); } @@ -3559,12 +3580,10 @@ bool Item_param::set_from_item(THD *thd, Item *item) switch (item->cmp_type()) { case REAL_RESULT: set_double(tmp.value.m_double); - item_type= Item::REAL_ITEM; set_handler_by_field_type(MYSQL_TYPE_DOUBLE); break; case INT_RESULT: set_int(tmp.value.m_longlong, MY_INT64_NUM_DECIMAL_DIGITS); - item_type= Item::INT_ITEM; set_handler_by_field_type(MYSQL_TYPE_LONGLONG); break; case STRING_RESULT: @@ -3574,7 +3593,6 @@ bool Item_param::set_from_item(THD *thd, Item *item) Exact value of max_length is not known unless data is converted to charset of connection, so we have to set it later. */ - item_type= Item::STRING_ITEM; set_handler_by_field_type(MYSQL_TYPE_VARCHAR); if (set_str(tmp.m_string.ptr(), tmp.m_string.length())) @@ -3583,24 +3601,13 @@ bool Item_param::set_from_item(THD *thd, Item *item) } case DECIMAL_RESULT: { - const my_decimal *ent_value= &tmp.m_decimal; - my_decimal2decimal(ent_value, &decimal_value); - state= DECIMAL_VALUE; - decimals= ent_value->frac; - max_length= - my_decimal_precision_to_length_no_truncation(ent_value->precision(), - decimals, unsigned_flag); - item_type= Item::DECIMAL_ITEM; + set_decimal(&tmp.m_decimal, unsigned_flag); set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL); break; } case TIME_RESULT: { - value.time= tmp.value.m_time; - state= TIME_VALUE; - max_length= item->max_length; - decimals= item->decimals; - item_type= Item::DATE_ITEM; + set_time(&tmp.value.m_time, item->max_length, item->decimals); set_handler(item->type_handler()); break; } @@ -3641,6 +3648,7 @@ void Item_param::reset() state= NO_VALUE; maybe_null= 1; null_value= 0; + fixed= false; /* Don't reset item_type to PARAM_ITEM: it's only needed to guard us from item optimizations at prepare stage, when item doesn't yet @@ -3978,6 +3986,7 @@ bool Item_param::convert_str_value(THD *thd) bool Item_param::basic_const_item() const { + DBUG_ASSERT(fixed || state == NO_VALUE); if (state == NO_VALUE || state == TIME_VALUE) return FALSE; return TRUE; @@ -4112,6 +4121,7 @@ Item_param::set_param_type_and_swap_value(Item_param *src) maybe_null= src->maybe_null; null_value= src->null_value; state= src->state; + fixed= src->fixed; value= src->value; decimal_value.swap(src->decimal_value); @@ -4123,6 +4133,7 @@ Item_param::set_param_type_and_swap_value(Item_param *src) void Item_param::set_default() { state= DEFAULT_VALUE; + fixed= true; /* When Item_param is set to DEFAULT_VALUE: - its val_str() and val_decimal() return NULL @@ -4137,6 +4148,7 @@ void Item_param::set_default() void Item_param::set_ignore() { state= IGNORE_VALUE; + fixed= true; null_value= true; } @@ -4182,18 +4194,15 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it) str_value.charset()); collation.set(str_value.charset(), DERIVATION_COERCIBLE); decimals= 0; - item_type= Item::STRING_ITEM; break; } case REAL_RESULT: set_double(arg->val_real()); - item_type= Item::REAL_ITEM; break; case INT_RESULT: set_int(arg->val_int(), arg->max_length); - item_type= Item::INT_ITEM; break; case DECIMAL_RESULT: @@ -4204,8 +4213,7 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it) if (!dv) return TRUE; - set_decimal(dv); - item_type= Item::DECIMAL_ITEM; + set_decimal(dv, !dv->sign()); break; } @@ -4215,7 +4223,6 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it) DBUG_ASSERT(TRUE); // Abort in debug mode. set_null(); // Set to NULL in release mode. - item_type= Item::NULL_ITEM; return FALSE; } diff --git a/sql/item.h b/sql/item.h index 1f3e0f02971..f9efd104b04 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2762,7 +2762,47 @@ class Item_param :public Item_basic_value, public Rewritable_query_parameter, public Type_handler_hybrid_field_type { -public: + /* + NO_VALUE is a special value meaning that the parameter has not been + assigned yet. Item_param::state is assigned to NO_VALUE in constructor + and is used at prepare time. + + 1. At prepare time + Item_param::fix_fields() sets "fixed" to true, + but as Item_param::state is still NO_VALUE, + Item_param::basic_const_item() returns false. This prevents various + optimizations to happen at prepare time fix_fields(). + For example, in this query: + PREPARE stmt FROM 'SELECT FORMAT(10000,2,?)'; + Item_param::basic_const_item() is tested from + Item_func_format::fix_length_and_dec(). + + 2. At execute time: + When Item_param gets a value + (or a pseudo-value like DEFAULT_VALUE or IGNORE_VALUE): + - Item_param::state changes from NO_VALUE to something else + - Item_param::fixed is changed to true + All Item_param::set_xxx() make sure to do so. + In the state with an assigned value: + - Item_param::basic_const_item() returns true + - Item::type() returns NULL_ITEM, INT_ITEM, REAL_ITEM, DECIMAL_ITEM, + DATE_ITEM, STRING_ITEM, depending on the value assigned. + So in this state Item_param behaves in many cases like a literal. + + When Item_param::cleanup() is called: + - Item_param::state does not change + - Item_param::fixed changes to false + Note, this puts Item_param into an inconsistent state: + - Item_param::basic_const_item() still returns "true" + - Item_param::type() still pretends to be a basic constant Item + Both are not expected in combination with fixed==false. + However, these methods are not really called in this state, + see asserts in Item_param::basic_const_item() and Item_param::type(). + + When Item_param::reset() is called: + - Item_param::state changes to NO_VALUE + - Item_param::fixed changes to false + */ enum enum_item_param_state { NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, @@ -2770,6 +2810,17 @@ public: DECIMAL_VALUE, DEFAULT_VALUE, IGNORE_VALUE } state; + enum Type item_type; + + void fix_type(Type type) + { + item_type= type; + fixed= true; + } + + void fix_temporal(uint32 max_length_arg, uint decimals_arg); + +public: struct CONVERSION_INFO { /* @@ -2838,8 +2889,6 @@ public: MYSQL_TIME time; } value; - enum Type item_type; - enum_field_types field_type() const { return Type_handler_hybrid_field_type::field_type(); } enum Item_result result_type () const @@ -2849,7 +2898,11 @@ public: Item_param(THD *thd, uint pos_in_query_arg); - enum Type type() const { return item_type; } + enum Type type() const + { + DBUG_ASSERT(fixed || state == NO_VALUE); + return item_type; + } double val_real(); longlong val_int(); @@ -2864,10 +2917,11 @@ public: void set_int(longlong i, uint32 max_length_arg); void set_double(double i); void set_decimal(const char *str, ulong length); - void set_decimal(const my_decimal *dv); + void set_decimal(const my_decimal *dv, bool unsigned_arg); bool set_str(const char *str, ulong length); bool set_longdata(const char *str, ulong length); void set_time(MYSQL_TIME *tm, timestamp_type type, uint32 max_length_arg); + void set_time(const MYSQL_TIME *tm, uint32 max_length_arg, uint decimals_arg); bool set_from_item(THD *thd, Item *item); void reset(); /* @@ -2893,6 +2947,18 @@ public: bool is_null() { DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; } bool basic_const_item() const; + bool has_no_value() const + { + return state == NO_VALUE; + } + bool has_long_data_value() const + { + return state == LONG_DATA_VALUE; + } + bool has_int_value() const + { + return state == INT_VALUE; + } /* This method is used to make a copy of a basic constant item when propagating constants in the optimizer. The reason to create a new diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d7a23a41002..735bdb73d58 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -742,45 +742,35 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, switch (param_type) { case MYSQL_TYPE_TINY: param->set_param_func= set_param_tiny; - param->item_type= Item::INT_ITEM; break; case MYSQL_TYPE_SHORT: param->set_param_func= set_param_short; - param->item_type= Item::INT_ITEM; break; case MYSQL_TYPE_LONG: param->set_param_func= set_param_int32; - param->item_type= Item::INT_ITEM; break; case MYSQL_TYPE_LONGLONG: param->set_param_func= set_param_int64; - param->item_type= Item::INT_ITEM; break; case MYSQL_TYPE_FLOAT: param->set_param_func= set_param_float; - param->item_type= Item::REAL_ITEM; break; case MYSQL_TYPE_DOUBLE: param->set_param_func= set_param_double; - param->item_type= Item::REAL_ITEM; break; case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: param->set_param_func= set_param_decimal; - param->item_type= Item::DECIMAL_ITEM; break; case MYSQL_TYPE_TIME: param->set_param_func= set_param_time; - param->item_type= Item::STRING_ITEM; break; case MYSQL_TYPE_DATE: param->set_param_func= set_param_date; - param->item_type= Item::STRING_ITEM; break; case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: param->set_param_func= set_param_datetime; - param->item_type= Item::STRING_ITEM; break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: @@ -792,7 +782,6 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, thd->variables.character_set_client; DBUG_ASSERT(thd->variables.character_set_client); param->value.cs_info.final_character_set_of_str_value= &my_charset_bin; - param->item_type= Item::STRING_ITEM; break; default: /* @@ -821,7 +810,6 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, Exact value of max_length is not known unless data is converted to charset of connection, so we have to set it later. */ - param->item_type= Item::STRING_ITEM; } } param->set_handler_by_field_type((enum enum_field_types) param_type); @@ -892,7 +880,7 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, for (Item_param **it= begin; it < end; ++it) { Item_param *param= *it; - if (param->state != Item_param::LONG_DATA_VALUE) + if (!param->has_long_data_value()) { if (is_param_null(null_array, (uint) (it - begin))) param->set_null(); @@ -901,13 +889,12 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array, if (read_pos >= data_end) DBUG_RETURN(1); param->set_param_func(param, &read_pos, (uint) (data_end - read_pos)); - if (param->state == Item_param::NO_VALUE) + if (param->has_no_value()) DBUG_RETURN(1); - if (param->limit_clause_param && param->state != Item_param::INT_VALUE) + if (param->limit_clause_param && !param->has_int_value()) { param->set_int(param->val_int(), MY_INT64_NUM_DECIMAL_DIGITS); - param->item_type= Item::INT_ITEM; if (!param->unsigned_flag && param->value.integer < 0) DBUG_RETURN(1); } @@ -947,7 +934,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, for (Item_param **it= begin; it < end; ++it) { Item_param *param= *it; - if (param->state != Item_param::LONG_DATA_VALUE) + if (!param->has_long_data_value()) { if (is_param_null(null_array, (uint) (it - begin))) param->set_null(); @@ -956,7 +943,7 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, if (read_pos >= data_end) DBUG_RETURN(1); param->set_param_func(param, &read_pos, (uint) (data_end - read_pos)); - if (param->state == Item_param::NO_VALUE) + if (param->has_no_value()) DBUG_RETURN(1); } } @@ -989,7 +976,7 @@ static bool insert_bulk_params(Prepared_statement *stmt, Item_param *param= *it; if (reset) param->reset(); - if (param->state != Item_param::LONG_DATA_VALUE) + if (!param->has_long_data_value()) { if (param->indicators) param->indicator= (enum_indicator_type) *((*read_pos)++); @@ -1003,7 +990,7 @@ static bool insert_bulk_params(Prepared_statement *stmt, if ((*read_pos) >= data_end) DBUG_RETURN(1); param->set_param_func(param, read_pos, (uint) (data_end - (*read_pos))); - if (param->state == Item_param::NO_VALUE) + if (param->has_no_value()) DBUG_RETURN(1); break; case STMT_INDICATOR_NULL: @@ -1093,7 +1080,7 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query) { Item_param *param= *it; setup_one_conversion_function(thd, param, client_param->buffer_type); - if (param->state != Item_param::LONG_DATA_VALUE) + if (!param->has_long_data_value()) { if (*client_param->is_null) param->set_null(); @@ -1105,7 +1092,7 @@ static bool emb_insert_params(Prepared_statement *stmt, String *expanded_query) client_param->length ? *client_param->length : client_param->buffer_length); - if (param->state == Item_param::NO_VALUE) + if (param->has_no_value()) DBUG_RETURN(1); } } @@ -1129,7 +1116,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, String *query) { Item_param *param= *it; setup_one_conversion_function(thd, param, client_param->buffer_type); - if (param->state != Item_param::LONG_DATA_VALUE) + if (!param->has_long_data_value()) { if (*client_param->is_null) param->set_null(); @@ -1141,7 +1128,7 @@ static bool emb_insert_params_with_log(Prepared_statement *stmt, String *query) client_param->length ? *client_param->length : client_param->buffer_length); - if (param->state == Item_param::NO_VALUE) + if (param->has_no_value()) DBUG_RETURN(1); } } From 1f3ad6a4ba63074c51c84dff449c35a8314a7f36 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 24 Jan 2017 01:21:43 +0530 Subject: [PATCH 103/167] MDEV-11108: Assertion `uniq_tuple_length_arg <= table->file->max_key_length()' failed in SJ_TMP_TABLE::create_sj_weedout_tmp_table Removed the assert from the if clause to the else clause. --- mysql-test/r/subselect_sj2.result | 13 +++++++++++++ mysql-test/t/subselect_sj2.test | 15 +++++++++++++++ sql/opt_subselect.cc | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result index 8f37c09efcf..948be5766a2 100644 --- a/mysql-test/r/subselect_sj2.result +++ b/mysql-test/r/subselect_sj2.result @@ -1318,5 +1318,18 @@ id 1 2 drop table t1,t2,t3; +# +# MDEV-11108: Assertion `uniq_tuple_length_arg <= table->file->max_key_length()' failed in SJ_TMP_TABLE::create_sj_weedout_tmp_table +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (pk BLOB, b INT, PRIMARY KEY(pk(1000))) ENGINE=InnoDB; +CREATE TABLE t3 (c INT) ENGINE=InnoDB; +CREATE OR REPLACE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3; +INSERT INTO t3 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +SELECT * FROM t1, t2 +WHERE a IN ( SELECT b FROM t2 LEFT JOIN v3 ON ( c = b ) ) ; +a pk b +DROP TABLE t1,t2,t3; +DROP VIEW v3; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/mysql-test/t/subselect_sj2.test b/mysql-test/t/subselect_sj2.test index 5d6639a6d5a..a948b086a85 100644 --- a/mysql-test/t/subselect_sj2.test +++ b/mysql-test/t/subselect_sj2.test @@ -1449,5 +1449,20 @@ SELECT * FROM t1 WHERE t1.id IN ( drop table t1,t2,t3; +--echo # +--echo # MDEV-11108: Assertion `uniq_tuple_length_arg <= table->file->max_key_length()' failed in SJ_TMP_TABLE::create_sj_weedout_tmp_table +--echo # + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (pk BLOB, b INT, PRIMARY KEY(pk(1000))) ENGINE=InnoDB; +CREATE TABLE t3 (c INT) ENGINE=InnoDB; +CREATE OR REPLACE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3; + +INSERT INTO t3 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +SELECT * FROM t1, t2 +WHERE a IN ( SELECT b FROM t2 LEFT JOIN v3 ON ( c = b ) ) ; +DROP TABLE t1,t2,t3; +DROP VIEW v3; + --echo # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index a9222cbca42..43b9bdd6255 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -4053,13 +4053,13 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) share->db_plugin= ha_lock_engine(0, TMP_ENGINE_HTON); table->file= get_new_handler(share, &table->mem_root, share->db_type()); - DBUG_ASSERT(uniq_tuple_length_arg <= table->file->max_key_length()); } else { share->db_plugin= ha_lock_engine(0, heap_hton); table->file= get_new_handler(share, &table->mem_root, share->db_type()); + DBUG_ASSERT(uniq_tuple_length_arg <= table->file->max_key_length()); } if (!table->file) goto err; From 0d107a85b3dd6969e66cc9cb4bd29e1cc92a7d18 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 24 Jan 2017 02:29:04 +0400 Subject: [PATCH 104/167] MDEV-11042 Implement GeoJSON functions. ST_AsGeoJSON and ST_GeomFromGeoJSON functions implemented. --- mysql-test/r/gis-json.result | 66 +++ mysql-test/t/gis-json.test | 28 ++ sql/item_create.cc | 125 ++++++ sql/item_geofunc.cc | 90 +++++ sql/item_geofunc.h | 34 ++ sql/item_jsonfunc.cc | 6 +- sql/share/errmsg-utf8.txt | 6 + sql/spatial.cc | 760 ++++++++++++++++++++++++++++++++++- sql/spatial.h | 35 ++ strings/json_lib.c | 5 +- 10 files changed, 1147 insertions(+), 8 deletions(-) create mode 100644 mysql-test/r/gis-json.result create mode 100644 mysql-test/t/gis-json.test diff --git a/mysql-test/r/gis-json.result b/mysql-test/r/gis-json.result new file mode 100644 index 00000000000..14b532784f7 --- /dev/null +++ b/mysql-test/r/gis-json.result @@ -0,0 +1,66 @@ +select st_asgeojson(geomfromtext('POINT(1 1)')); +st_asgeojson(geomfromtext('POINT(1 1)')) +{"type": "POINT", "coordinates": [1, 1]} +select st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')); +st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')) +{"type": "LINESTRING", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} +select st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')); +st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')) +{"type": "POLYGON", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} +select st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')); +st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')) +{"type": "MULTIPOLYGON", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]} +select st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')); +st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')) +{"type": "MULTILINESTRING", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} +select st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')); +st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')) +{"type": "MULTIPOINT", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} +select st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')); +st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')) +{"type": "GEOMETRYCOLLECTION", "geometries": [{"type": "POINT", "coordinates": [100, 0]}, {"type": "LINESTRING", "coordinates": [[101, 0], [102, 1]]}]} +SELECT st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')); +st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')) +POINT(1 2) +SELECT st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')); +st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')) +LINESTRING(1 2,4 5,7 8) +SELECT st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); +st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) +POLYGON((10 10,20 10,20 20,10 20,10 10)) +SELECT st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')); +st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')) +MULTIPOINT(1 2,4 5,7 8) +SELECT st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); +st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')) +MULTILINESTRING((10 10,20 10,20 20,10 20,10 10)) +SELECT st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')); +st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')) +MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10))) +SELECT st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')); +st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')) +GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1)) +SELECT st_astext(st_geomfromgeojson('{"type":"point"}')); +st_astext(st_geomfromgeojson('{"type":"point"}')) +NULL +Warnings: +Warning 4048 Incorrect GeoJSON format specified for st_geomfromgeojson function. +SELECT st_astext(st_geomfromgeojson('{"type":"point"')); +st_astext(st_geomfromgeojson('{"type":"point"')) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'st_geomfromgeojson' +SELECT st_astext(st_geomfromgeojson('{"type""point"}')); +st_astext(st_geomfromgeojson('{"type""point"}')) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'st_geomfromgeojson' at position 7 +SELECT st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')); +st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')) +POINT(102 0.5) +SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')); +st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')) +GEOMETRYCOLLECTION(POINT(102 0.5)) +# +# End of 10.2 tests +# diff --git a/mysql-test/t/gis-json.test b/mysql-test/t/gis-json.test new file mode 100644 index 00000000000..645c21bf011 --- /dev/null +++ b/mysql-test/t/gis-json.test @@ -0,0 +1,28 @@ +-- source include/have_geometry.inc + +select st_asgeojson(geomfromtext('POINT(1 1)')); +select st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')); +select st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')); +select st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')); +select st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')); +select st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')); +select st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')); + +SELECT st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')); +SELECT st_astext(st_geomfromgeojson('{"type":"LineString","coordinates":[[1,2],[4,5],[7,8]]}')); +SELECT st_astext(st_geomfromgeojson('{"type": "polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); +SELECT st_astext(st_geomfromgeojson('{"type":"multipoint","coordinates":[[1,2],[4,5],[7,8]]}')); +SELECT st_astext(st_geomfromgeojson('{"type": "multilinestring", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]}')); +SELECT st_astext(st_geomfromgeojson('{"type": "multipolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]}')); +SELECT st_astext(st_geomfromgeojson('{"type": "GeometryCollection", "geometries": [{"type": "Point","coordinates": [100.0, 0.0]}, {"type": "LineString","coordinates": [[101.0, 0.0],[102.0, 1.0]]}]}')); + +SELECT st_astext(st_geomfromgeojson('{"type":"point"}')); +SELECT st_astext(st_geomfromgeojson('{"type":"point"')); +SELECT st_astext(st_geomfromgeojson('{"type""point"}')); + +SELECT st_astext(st_geomfromgeojson('{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] } }')); +SELECT st_astext(st_geomfromgeojson('{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [102.0, 0.5] }, "properties": { "prop0": "value0" } }]}')); + +--echo # +--echo # End of 10.2 tests +--echo # diff --git a/sql/item_create.cc b/sql/item_create.cc index a506ab948d1..add8da67810 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -1261,6 +1261,34 @@ protected: #endif +#ifdef HAVE_SPATIAL +class Create_func_geometry_from_json : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_geometry_from_json s_singleton; + +protected: + Create_func_geometry_from_json() {} + virtual ~Create_func_geometry_from_json() {} +}; + + +class Create_func_as_geojson : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, LEX_STRING name, List *item_list); + + static Create_func_as_geojson s_singleton; + +protected: + Create_func_as_geojson() {} + virtual ~Create_func_as_geojson() {} +}; +#endif /*HAVE_SPATIAL*/ + + #ifdef HAVE_SPATIAL class Create_func_geometry_type : public Create_func_arg1 { @@ -4532,6 +4560,101 @@ Create_func_geometry_from_wkb::create_native(THD *thd, LEX_STRING name, #endif +#ifdef HAVE_SPATIAL +Create_func_geometry_from_json Create_func_geometry_from_json::s_singleton; + +Item* +Create_func_geometry_from_json::create_native(THD *thd, LEX_STRING name, + List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *json= item_list->pop(); + func= new (thd->mem_root) Item_func_geometry_from_json(thd, json); + thd->lex->uncacheable(UNCACHEABLE_RAND); + break; + } + case 2: + { + Item *json= item_list->pop(); + Item *options= item_list->pop(); + func= new (thd->mem_root) Item_func_geometry_from_json(thd, json, options); + break; + } + case 3: + { + Item *json= item_list->pop(); + Item *options= item_list->pop(); + Item *srid= item_list->pop(); + func= new (thd->mem_root) Item_func_geometry_from_json(thd, json, options, + srid); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} + + +Create_func_as_geojson Create_func_as_geojson::s_singleton; + +Item* +Create_func_as_geojson::create_native(THD *thd, LEX_STRING name, + List *item_list) +{ + Item *func= NULL; + int arg_count= 0; + + if (item_list != NULL) + arg_count= item_list->elements; + + switch (arg_count) { + case 1: + { + Item *geom= item_list->pop(); + func= new (thd->mem_root) Item_func_as_geojson(thd, geom); + thd->lex->uncacheable(UNCACHEABLE_RAND); + break; + } + case 2: + { + Item *geom= item_list->pop(); + Item *max_dec= item_list->pop(); + func= new (thd->mem_root) Item_func_as_geojson(thd, geom, max_dec); + break; + } + case 3: + { + Item *geom= item_list->pop(); + Item *max_dec= item_list->pop(); + Item *options= item_list->pop(); + func= new (thd->mem_root) Item_func_as_geojson(thd, geom, max_dec, options); + break; + } + default: + { + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str); + break; + } + } + + return func; +} +#endif /*HAVE_SPATIAL*/ + + #ifdef HAVE_SPATIAL Create_func_geometry_type Create_func_geometry_type::s_singleton; @@ -6723,6 +6846,7 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("STR_TO_DATE") }, BUILDER(Create_func_str_to_date)}, { { C_STRING_WITH_LEN("ST_AREA") }, GEOM_BUILDER(Create_func_area)}, { { C_STRING_WITH_LEN("ST_ASBINARY") }, GEOM_BUILDER(Create_func_as_wkb)}, + { { C_STRING_WITH_LEN("ST_ASGEOJSON") }, GEOM_BUILDER(Create_func_as_geojson)}, { { C_STRING_WITH_LEN("ST_ASTEXT") }, GEOM_BUILDER(Create_func_as_wkt)}, { { C_STRING_WITH_LEN("ST_ASWKB") }, GEOM_BUILDER(Create_func_as_wkb)}, { { C_STRING_WITH_LEN("ST_ASWKT") }, GEOM_BUILDER(Create_func_as_wkt)}, @@ -6748,6 +6872,7 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("ST_GEOMETRYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)}, { { C_STRING_WITH_LEN("ST_GEOMETRYN") }, GEOM_BUILDER(Create_func_geometryn)}, { { C_STRING_WITH_LEN("ST_GEOMETRYTYPE") }, GEOM_BUILDER(Create_func_geometry_type)}, + { { C_STRING_WITH_LEN("ST_GEOMFROMGEOJSON") }, GEOM_BUILDER(Create_func_geometry_from_json)}, { { C_STRING_WITH_LEN("ST_GEOMFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)}, { { C_STRING_WITH_LEN("ST_GEOMFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)}, #ifndef DBUG_OFF diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index c856aa985b3..7ac2e054e8c 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -121,6 +121,65 @@ String *Item_func_geometry_from_wkb::val_str(String *str) } +void report_json_error_ex(String *js, json_engine_t *je, + const char *fname, int n_param, + Sql_condition::enum_warning_level lv); + +String *Item_func_geometry_from_json::val_str(String *str) +{ + DBUG_ASSERT(fixed == 1); + Geometry_buffer buffer; + String *js= args[0]->val_str_ascii(&tmp_js); + uint32 srid= 0; + json_engine_t je; + + if ((null_value= args[0]->null_value)) + return 0; + + if ((arg_count == 2) && !args[1]->null_value) + srid= (uint32)args[1]->val_int(); + + str->set_charset(&my_charset_bin); + if (str->reserve(SRID_SIZE, 512)) + return 0; + str->length(0); + str->q_append(srid); + + json_scan_start(&je, js->charset(), (const uchar *) js->ptr(), + (const uchar *) js->end()); + + if ((null_value= !Geometry::create_from_json(&buffer, &je, str))) + { + int code= 0; + + switch (je.s.error) + { + case Geometry::GEOJ_INCORRECT_GEOJSON: + code= ER_GEOJSON_INCORRECT; + break; + case Geometry::GEOJ_TOO_FEW_POINTS: + code= ER_GEOJSON_TOO_FEW_POINTS; + break; + case Geometry::GEOJ_POLYGON_NOT_CLOSED: + code= ER_GEOJSON_NOT_CLOSED; + break; + default: + report_json_error_ex(js, &je, func_name(), 0, Sql_condition::WARN_LEVEL_WARN); + return NULL; + } + + if (code) + { + THD *thd= current_thd; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, code, + ER_THD(thd, code)); + } + return 0; + } + return str; +} + + String *Item_func_as_wkt::val_str_ascii(String *str) { DBUG_ASSERT(fixed == 1); @@ -170,6 +229,37 @@ String *Item_func_as_wkb::val_str(String *str) } +void Item_func_as_geojson::fix_length_and_dec() +{ + collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); + max_length=MAX_BLOB_WIDTH; + maybe_null= 1; +} + + +String *Item_func_as_geojson::val_str_ascii(String *str) +{ + DBUG_ASSERT(fixed == 1); + String arg_val; + String *swkb= args[0]->val_str(&arg_val); + Geometry_buffer buffer; + Geometry *geom= NULL; + const char *dummy; + + if ((null_value= + (args[0]->null_value || + !(geom= Geometry::construct(&buffer, swkb->ptr(), swkb->length()))))) + return 0; + + str->length(0); + str->set_charset(&my_charset_latin1); + if ((null_value= geom->as_json(str, FLOATING_POINT_DECIMALS, &dummy))) + return 0; + + return str; +} + + String *Item_func_geometry_type::val_str_ascii(String *str) { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 1584090c29e..a164f9dec89 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -67,6 +67,23 @@ public: { return get_item_copy(thd, mem_root, this); } }; + +class Item_func_geometry_from_json: public Item_geometry_func +{ + String tmp_js; +public: + Item_func_geometry_from_json(THD *thd, Item *js): Item_geometry_func(thd, js) {} + Item_func_geometry_from_json(THD *thd, Item *js, Item *opt): + Item_geometry_func(thd, js, opt) {} + Item_func_geometry_from_json(THD *thd, Item *js, Item *opt, Item *srid): + Item_geometry_func(thd, js, opt, srid) {} + const char *func_name() const { return "st_geomfromgeojson"; } + String *val_str(String *); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy(thd, mem_root, this); } +}; + + class Item_func_as_wkt: public Item_str_ascii_func { public: @@ -89,6 +106,23 @@ public: { return get_item_copy(thd, mem_root, this); } }; + +class Item_func_as_geojson: public Item_str_ascii_func +{ +public: + Item_func_as_geojson(THD *thd, Item *js): Item_str_ascii_func(thd, js) {} + Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits): + Item_str_ascii_func(thd, js, max_dec_digits) {} + Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt): + Item_str_ascii_func(thd, js, max_dec_digits, opt) {} + const char *func_name() const { return "st_asgeojson"; } + void fix_length_and_dec(); + String *val_str_ascii(String *); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy(thd, mem_root, this); } +}; + + class Item_func_geometry_type: public Item_str_ascii_func { public: diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index a500170ead0..b0576fbdaba 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -117,9 +117,9 @@ static int st_append_escaped(String *s, const String *a) report_json_error_ex(js, je, func_name(), n_param, \ Sql_condition::WARN_LEVEL_WARN) -static void report_json_error_ex(String *js, json_engine_t *je, - const char *fname, int n_param, - Sql_condition::enum_warning_level lv) +void report_json_error_ex(String *js, json_engine_t *je, + const char *fname, int n_param, + Sql_condition::enum_warning_level lv) { THD *thd= current_thd; int position= (const char *) je->s.c_str - js->ptr(); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index eea7f19d1f5..7f5df13ad97 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7440,3 +7440,9 @@ ER_JSON_ONE_OR_ALL eng "Argument 2 to function '%s' must be "one" or "all"." ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE eng "CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or KEY_BLOCK_SIZE." +ER_GEOJSON_INCORRECT + eng "Incorrect GeoJSON format specified for st_geomfromgeojson function." +ER_GEOJSON_TOO_FEW_POINTS + eng "Incorrect GeoJSON format - too few points for linestring specified." +ER_GEOJSON_NOT_CLOSED + eng "Incorrect GeoJSON format - polygon not closed." diff --git a/sql/spatial.cc b/sql/spatial.cc index 9c4fe168fe3..ef9c24dcef4 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -230,6 +230,50 @@ int Geometry::as_wkt(String *wkt, const char **end) } +static const uchar type_keyname[]= "type"; +static const int type_keyname_len= 4; +static const uchar coord_keyname[]= "coordinates"; +static const int coord_keyname_len= 11; +static const uchar geometries_keyname[]= "geometries"; +static const int geometries_keyname_len= 10; +static const uchar features_keyname[]= "features"; +static const int features_keyname_len= 8; +static const uchar geometry_keyname[]= "geometry"; +static const int geometry_keyname_len= 8; + +static const int max_keyname_len= 11; /*'coordinates' keyname is the longest.*/ + +static const uchar feature_type[]= "feature"; +static const int feature_type_len= 7; +static const uchar feature_coll_type[]= "featurecollection"; +static const int feature_coll_type_len= 17; + + +int Geometry::as_json(String *wkt, uint max_dec_digits, const char **end) +{ + uint32 len= (uint) get_class_info()->m_name.length; + if (wkt->reserve(4 + type_keyname_len + 2 + len + 2 + 2 + + coord_keyname_len + 4, 512)) + return 1; + wkt->qs_append("{\"", 2); + wkt->qs_append((const char *) type_keyname, type_keyname_len); + wkt->qs_append("\": \"", 4); + wkt->qs_append(get_class_info()->m_name.str, len); + wkt->qs_append("\", \"", 4); + if (get_class_info() == &geometrycollection_class) + wkt->qs_append((const char *) geometries_keyname, geometries_keyname_len); + else + wkt->qs_append((const char *) coord_keyname, coord_keyname_len); + + wkt->qs_append("\": ", 3); + if (get_data_as_json(wkt, max_dec_digits, end) || + wkt->reserve(1)) + return 1; + wkt->qs_append('}'); + return 0; +} + + static double wkb_get_double(const char *ptr, Geometry::wkbByteOrder bo) { double res; @@ -291,6 +335,196 @@ Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer, } +Geometry *Geometry::create_from_json(Geometry_buffer *buffer, + json_engine_t *je, String *res) +{ + Class_info *ci= NULL; + const uchar *coord_start= NULL, *geom_start= NULL, + *features_start= NULL, *geometry_start= NULL; + Geometry *result; + uchar key_buf[max_keyname_len]; + uint key_len; + int fcoll_type_found= 0, feature_type_found= 0; + + + if (json_read_value(je)) + goto err_return; + + if (je->value_type != JSON_VALUE_OBJECT) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + goto err_return; + } + + while (json_scan_next(je) == 0 && je->state != JST_OBJ_END) + { + DBUG_ASSERT(je->state == JST_KEY); + + key_len=0; + while (json_read_keyname_chr(je) == 0) + { + if (je->s.c_next > 127 || key_len >= max_keyname_len) + { + /* Symbol out of range, or keyname too long. No need to compare.. */ + key_len=0; + break; + } + key_buf[key_len++]= je->s.c_next | 0x20; /* make it lowercase. */ + } + + if (je->s.error) + goto err_return; + + if (key_len == type_keyname_len && + memcmp(key_buf, type_keyname, type_keyname_len) == 0) + { + /* + Found the "type" key. Let's check it's a string and remember + the feature's type. + */ + if (json_read_value(je)) + goto err_return; + + if (je->value_type == JSON_VALUE_STRING) + { + if ((ci= find_class((const char *) je->value, je->value_len))) + { + if ((coord_start= + (ci == &geometrycollection_class) ? geom_start : coord_start)) + goto create_geom; + } + else if (je->value_len == feature_coll_type_len && + my_strnncoll(&my_charset_latin1, je->value, je->value_len, + feature_coll_type, feature_coll_type_len) == 0) + { + /* + 'FeatureCollection' type found. Handle the 'Featurecollection'/'features' + GeoJSON construction. + */ + if (features_start) + goto handle_feature_collection; + fcoll_type_found= 1; + } + else if (je->value_len == feature_type_len && + my_strnncoll(&my_charset_latin1, je->value, je->value_len, + feature_type, feature_type_len) == 0) + { + if (geometry_start) + goto handle_geometry_key; + feature_type_found= 1; + } + } + } + else if (key_len == coord_keyname_len && + memcmp(key_buf, coord_keyname, coord_keyname_len) == 0) + { + /* + Found the "coordinates" key. Let's check it's an array + and remember where it starts. + */ + if (json_read_value(je)) + goto err_return; + + if (je->value_type == JSON_VALUE_ARRAY) + { + coord_start= je->value_begin; + if (ci && ci != &geometrycollection_class) + goto create_geom; + } + } + else if (key_len == geometries_keyname_len && + memcmp(key_buf, geometries_keyname, geometries_keyname_len) == 0) + { + /* + Found the "geometries" key. Let's check it's an array + and remember where it starts. + */ + if (json_read_value(je)) + goto err_return; + + if (je->value_type == JSON_VALUE_ARRAY) + { + geom_start= je->value_begin; + if (ci == &geometrycollection_class) + { + coord_start= geom_start; + goto create_geom; + } + } + } + else if (key_len == features_keyname_len && + memcmp(key_buf, features_keyname, features_keyname_len) == 0) + { + /* + 'features' key found. Handle the 'Featurecollection'/'features' + GeoJSON construction. + */ + if (json_read_value(je)) + goto err_return; + if (je->value_type == JSON_VALUE_ARRAY) + { + features_start= je->value_begin; + if (fcoll_type_found) + goto handle_feature_collection; + } + } + else if (key_len == geometry_keyname_len && + memcmp(key_buf, geometry_keyname, geometry_keyname_len) == 0) + { + if (json_read_value(je)) + goto err_return; + if (je->value_type == JSON_VALUE_OBJECT) + { + geometry_start= je->value_begin; + if (feature_type_found) + goto handle_geometry_key; + } + } + else + { + if (json_skip_key(je)) + goto err_return; + } + } + + if (je->s.error == 0) + { + /* + We didn't find all the required keys. That are "type" and "coordinates" + or "geometries" for GeometryCollection. + */ + je->s.error= GEOJ_INCORRECT_GEOJSON; + } + goto err_return; + +handle_feature_collection: + ci= &geometrycollection_class; + coord_start= features_start; + +create_geom: + + json_scan_start(je, je->s.cs, coord_start, je->s.str_end); + + if (res->reserve(1 + 4, 512)) + goto err_return; + + result= (*ci->m_create_func)(buffer->data); + res->q_append((char) wkb_ndr); + res->q_append((uint32) result->get_class_info()->m_type_id); + if (result->init_from_json(je, res)) + goto err_return; + + return result; + +handle_geometry_key: + json_scan_start(je, je->s.cs, geometry_start, je->s.str_end); + return create_from_json(buffer, je, res); + +err_return: + return NULL; +} + + Geometry *Geometry::create_from_opresult(Geometry_buffer *g_buf, String *res, Gcalc_result_receiver &rr) { @@ -429,6 +663,47 @@ const char *Geometry::append_points(String *txt, uint32 n_points, } +static void append_json_point(String *txt, uint max_dec, const char *data) +{ + double x,y; + get_point(&x, &y, data); + txt->qs_append('['); + txt->qs_append(x); + txt->qs_append(", ", 2); + txt->qs_append(y); + txt->qs_append(']'); +} + + +/* + Append N points from packed format to json + + SYNOPSIS + append_json_points() + txt Append points here + n_points Number of points + data Packed data + offset Offset between points + + RETURN + # end of data +*/ + +static const char *append_json_points(String *txt, uint max_dec, + uint32 n_points, const char *data, uint32 offset) +{ + txt->qs_append('['); + while (n_points--) + { + data+= offset; + append_json_point(txt, max_dec, data); + data+= POINT_DATA_SIZE; + txt->qs_append(", ", 2); + } + txt->length(txt->length() - 2);// Remove ending ', ' + txt->qs_append(']'); + return data; +} /* Get most bounding rectangle (mbr) for X points @@ -502,6 +777,58 @@ uint Gis_point::init_from_wkb(const char *wkb, uint len, } +static int read_point_from_json(json_engine_t *je, double *x, double *y) +{ + int n_coord= 0, err; + double tmp, *d; + char *endptr; + + while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) + { + DBUG_ASSERT(je->state == JST_VALUE); + if (json_read_value(je)) + return 1; + + if (je->value_type != JSON_VALUE_NUMBER) + goto bad_coordinates; + + d= (n_coord == 0) ? x : ((n_coord == 1) ? y : &tmp); + *d= my_strntod(je->s.cs, (char *) je->value, + je->value_len, &endptr, &err); + if (err) + goto bad_coordinates; + n_coord++; + } + + return 0; +bad_coordinates: + je->s.error= Geometry::GEOJ_INCORRECT_GEOJSON; + return 1; +} + + +bool Gis_point::init_from_json(json_engine_t *je, String *wkb) +{ + double x, y; + if (json_read_value(je)) + return TRUE; + + if (je->value_type != JSON_VALUE_ARRAY) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + return TRUE; + } + + if (read_point_from_json(je, &x, &y) || + wkb->reserve(POINT_DATA_SIZE)) + return TRUE; + + wkb->q_append(x); + wkb->q_append(y); + return FALSE; +} + + bool Gis_point::get_data_as_wkt(String *txt, const char **end) const { double x, y; @@ -517,6 +844,17 @@ bool Gis_point::get_data_as_wkt(String *txt, const char **end) const } +bool Gis_point::get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const +{ + if (txt->reserve(MAX_DIGITS_IN_DOUBLE * 2 + 4)) + return 1; + append_json_point(txt, max_dec_digits, m_data); + *end= m_data+ POINT_DATA_SIZE; + return 0; +} + + bool Gis_point::get_mbr(MBR *mbr, const char **end) const { double x, y; @@ -630,6 +968,43 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len, } +bool Gis_line_string::init_from_json(json_engine_t *je, String *wkb) +{ + uint32 n_points= 0; + uint32 np_pos= wkb->length(); + Gis_point p; + + if (json_read_value(je)) + return TRUE; + + if (je->value_type != JSON_VALUE_ARRAY) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + return TRUE; + } + + if (wkb->reserve(4, 512)) + return TRUE; + wkb->length(wkb->length()+4); // Reserve space for n_points + + while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) + { + DBUG_ASSERT(je->state == JST_VALUE); + + if (p.init_from_json(je, wkb)) + return TRUE; + n_points++; + } + if (n_points < 1) + { + je->s.error= GEOJ_TOO_FEW_POINTS; + return TRUE; + } + wkb->write_at_position(np_pos, n_points); + return FALSE; +} + + bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const { uint32 n_points; @@ -661,6 +1036,28 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const } +bool Gis_line_string::get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const +{ + uint32 n_points; + const char *data= m_data; + + if (no_data(data, 4)) + return 1; + n_points= uint4korr(data); + data += 4; + + if (n_points < 1 || + not_enough_points(data, n_points) || + txt->reserve((MAX_DIGITS_IN_DOUBLE*2 + 6) * n_points + 2)) + return 1; + + *end= append_json_points(txt, max_dec_digits, n_points, data, 0); + + return 0; +} + + bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const { return (*end=get_mbr_for_points(mbr, m_data, 0)) == 0; @@ -854,7 +1251,7 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb) if (wkb->reserve(4, 512)) return 1; - wkb->length(wkb->length()+4); // Reserve space for points + wkb->length(wkb->length()+4); // Reserve space for n_rings for (;;) { Gis_line_string ls; @@ -964,6 +1361,46 @@ uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, } +bool Gis_polygon::init_from_json(json_engine_t *je, String *wkb) +{ + uint32 n_linear_rings= 0; + uint32 lr_pos= wkb->length(); + int closed; + + if (json_read_value(je)) + return TRUE; + + if (je->value_type != JSON_VALUE_ARRAY) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + return TRUE; + } + + if (wkb->reserve(4, 512)) + return TRUE; + wkb->length(wkb->length()+4); // Reserve space for n_rings + + while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) + { + Gis_line_string ls; + DBUG_ASSERT(je->state == JST_VALUE); + + uint32 ls_pos=wkb->length(); + if (ls.init_from_json(je, wkb)) + return TRUE; + ls.set_data_ptr(wkb->ptr() + ls_pos, wkb->length() - ls_pos); + if (ls.is_closed(&closed) || !closed) + { + je->s.error= GEOJ_POLYGON_NOT_CLOSED; + return TRUE; + } + n_linear_rings++; + } + wkb->write_at_position(lr_pos, n_linear_rings); + return FALSE; +} + + bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_linear_rings; @@ -996,6 +1433,39 @@ bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const } +bool Gis_polygon::get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const +{ + uint32 n_linear_rings; + const char *data= m_data; + + if (no_data(data, 4) || txt->reserve(1, 512)) + return 1; + + n_linear_rings= uint4korr(data); + data+= 4; + + txt->qs_append('['); + while (n_linear_rings--) + { + uint32 n_points; + if (no_data(data, 4)) + return 1; + n_points= uint4korr(data); + data+= 4; + if (not_enough_points(data, n_points) || + txt->reserve(4 + (MAX_DIGITS_IN_DOUBLE * 2 + 6) * n_points)) + return 1; + data= append_json_points(txt, max_dec_digits, n_points, data, 0); + txt->qs_append(", ", 2); + } + txt->length(txt->length() - 2);// Remove ending ', ' + txt->qs_append(']'); + *end= data; + return 0; +} + + bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const { uint32 n_linear_rings; @@ -1382,6 +1852,44 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, } +bool Gis_multi_point::init_from_json(json_engine_t *je, String *wkb) +{ + uint32 n_points= 0; + uint32 np_pos= wkb->length(); + Gis_point p; + + if (json_read_value(je)) + return TRUE; + + if (je->value_type != JSON_VALUE_ARRAY) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + return TRUE; + } + + if (wkb->reserve(4, 512)) + return TRUE; + wkb->length(wkb->length()+4); // Reserve space for n_points + + while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) + { + DBUG_ASSERT(je->state == JST_VALUE); + + if (wkb->reserve(1 + 4, 512)) + return TRUE; + wkb->q_append((char) wkb_ndr); + wkb->q_append((uint32) wkb_point); + + if (p.init_from_json(je, wkb)) + return TRUE; + n_points++; + } + + wkb->write_at_position(np_pos, n_points); + return FALSE; +} + + bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const { uint32 n_points; @@ -1399,6 +1907,24 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const } +bool Gis_multi_point::get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const +{ + uint32 n_points; + if (no_data(m_data, 4)) + return 1; + + n_points= uint4korr(m_data); + if (n_points > max_n_points || + not_enough_points(m_data+4, n_points, WKB_HEADER_SIZE) || + txt->reserve((MAX_DIGITS_IN_DOUBLE * 2 + 6) * n_points + 2)) + return 1; + *end= append_json_points(txt, max_dec_digits, n_points, m_data+4, + WKB_HEADER_SIZE); + return 0; +} + + bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const { return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0; @@ -1594,6 +2120,44 @@ uint Gis_multi_line_string::init_from_wkb(const char *wkb, uint len, } +bool Gis_multi_line_string::init_from_json(json_engine_t *je, String *wkb) +{ + uint32 n_line_strings= 0; + uint32 ls_pos= wkb->length(); + + if (json_read_value(je)) + return TRUE; + + if (je->value_type != JSON_VALUE_ARRAY) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + return TRUE; + } + + if (wkb->reserve(4, 512)) + return TRUE; + wkb->length(wkb->length()+4); // Reserve space for n_rings + + while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) + { + Gis_line_string ls; + DBUG_ASSERT(je->state == JST_VALUE); + + if (wkb->reserve(1 + 4, 512)) + return TRUE; + wkb->q_append((char) wkb_ndr); + wkb->q_append((uint32) wkb_linestring); + + if (ls.init_from_json(je, wkb)) + return TRUE; + + n_line_strings++; + } + wkb->write_at_position(ls_pos, n_line_strings); + return FALSE; +} + + bool Gis_multi_line_string::get_data_as_wkt(String *txt, const char **end) const { @@ -1626,6 +2190,38 @@ bool Gis_multi_line_string::get_data_as_wkt(String *txt, } +bool Gis_multi_line_string::get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const +{ + uint32 n_line_strings; + const char *data= m_data; + + if (no_data(data, 4) || txt->reserve(1, 512)) + return 1; + n_line_strings= uint4korr(data); + data+= 4; + + txt->qs_append('['); + while (n_line_strings--) + { + uint32 n_points; + if (no_data(data, (WKB_HEADER_SIZE + 4))) + return 1; + n_points= uint4korr(data + WKB_HEADER_SIZE); + data+= WKB_HEADER_SIZE + 4; + if (not_enough_points(data, n_points) || + txt->reserve(2 + (MAX_DIGITS_IN_DOUBLE * 2 + 6) * n_points)) + return 1; + data= append_json_points(txt, max_dec_digits, n_points, data, 0); + txt->qs_append(", ", 2); + } + txt->length(txt->length() - 2); + txt->qs_append(']'); + *end= data; + return 0; +} + + bool Gis_multi_line_string::get_mbr(MBR *mbr, const char **end) const { uint32 n_line_strings; @@ -1912,6 +2508,44 @@ uint Gis_multi_polygon::init_from_opresult(String *bin, } +bool Gis_multi_polygon::init_from_json(json_engine_t *je, String *wkb) +{ + uint32 n_polygons= 0; + int np_pos= wkb->length(); + Gis_polygon p; + + if (json_read_value(je)) + return TRUE; + + if (je->value_type != JSON_VALUE_ARRAY) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + return TRUE; + } + + if (wkb->reserve(4, 512)) + return TRUE; + wkb->length(wkb->length()+4); // Reserve space for n_rings + + while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) + { + DBUG_ASSERT(je->state == JST_VALUE); + + if (wkb->reserve(1 + 4, 512)) + return TRUE; + wkb->q_append((char) wkb_ndr); + wkb->q_append((uint32) wkb_polygon); + + if (p.init_from_json(je, wkb)) + return TRUE; + + n_polygons++; + } + wkb->write_at_position(np_pos, n_polygons); + return FALSE; +} + + bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const { uint32 n_polygons; @@ -1956,6 +2590,51 @@ bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const } +bool Gis_multi_polygon::get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const +{ + uint32 n_polygons; + const char *data= m_data; + + if (no_data(data, 4) || txt->reserve(1, 512)) + return 1; + n_polygons= uint4korr(data); + data+= 4; + + txt->q_append('['); + while (n_polygons--) + { + uint32 n_linear_rings; + if (no_data(data, 4 + WKB_HEADER_SIZE) || + txt->reserve(1, 512)) + return 1; + n_linear_rings= uint4korr(data+WKB_HEADER_SIZE); + data+= 4 + WKB_HEADER_SIZE; + txt->q_append('['); + + while (n_linear_rings--) + { + if (no_data(data, 4)) + return 1; + uint32 n_points= uint4korr(data); + data+= 4; + if (not_enough_points(data, n_points) || + txt->reserve(2 + (MAX_DIGITS_IN_DOUBLE * 2 + 6) * n_points, + 512)) + return 1; + data= append_json_points(txt, max_dec_digits, n_points, data, 0); + txt->qs_append(", ", 2); + } + txt->length(txt->length() - 2); + txt->qs_append("], ", 3); + } + txt->length(txt->length() - 2); + txt->q_append(']'); + *end= data; + return 0; +} + + bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const { uint32 n_polygons; @@ -2304,6 +2983,47 @@ uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len, } +bool Gis_geometry_collection::init_from_json(json_engine_t *je, String *wkb) +{ + uint32 n_objects= 0; + uint32 no_pos= wkb->length(); + Geometry_buffer buffer; + Geometry *g; + + if (json_read_value(je)) + return TRUE; + + if (je->value_type != JSON_VALUE_ARRAY) + { + je->s.error= GEOJ_INCORRECT_GEOJSON; + return TRUE; + } + + if (wkb->reserve(4, 512)) + return TRUE; + wkb->length(wkb->length()+4); // Reserve space for n_objects + + while (json_scan_next(je) == 0 && je->state != JST_ARRAY_END) + { + json_engine_t sav_je= *je; + + DBUG_ASSERT(je->state == JST_VALUE); + + if (!(g= create_from_json(&buffer, je, wkb))) + return TRUE; + + *je= sav_je; + if (json_skip_array_item(je)) + return TRUE; + + n_objects++; + } + + wkb->write_at_position(no_pos, n_objects); + return FALSE; +} + + bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end) const { @@ -2348,6 +3068,44 @@ exit: } +bool Gis_geometry_collection::get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const +{ + uint32 n_objects; + Geometry_buffer buffer; + Geometry *geom; + const char *data= m_data; + + if (no_data(data, 4) || txt->reserve(1, 512)) + return 1; + n_objects= uint4korr(data); + data+= 4; + + txt->qs_append('['); + while (n_objects--) + { + uint32 wkb_type; + + if (no_data(data, WKB_HEADER_SIZE)) + return 1; + wkb_type= uint4korr(data + 1); + data+= WKB_HEADER_SIZE; + + if (!(geom= create_by_typeid(&buffer, wkb_type))) + return 1; + geom->set_data_ptr(data, (uint) (m_data_end - data)); + if (geom->as_json(txt, max_dec_digits, &data) || + txt->append(STRING_WITH_LEN(", "), 512)) + return 1; + } + txt->length(txt->length() - 2); + txt->qs_append(']'); + + *end= data; + return 0; +} + + bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const { uint32 n_objects; diff --git a/sql/spatial.h b/sql/spatial.h index 2e449844d47..926f66d5357 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -20,6 +20,7 @@ #include "sql_string.h" /* String, LEX_STRING */ #include +#include #ifdef HAVE_SPATIAL @@ -249,6 +250,13 @@ public: wkb_xdr= 0, /* Big Endian */ wkb_ndr= 1 /* Little Endian */ }; + enum geojson_errors + { + GEOJ_INCORRECT_GEOJSON= 1, + GEOJ_TOO_FEW_POINTS= 2, + GEOJ_POLYGON_NOT_CLOSED= 3, + }; + /** Callback which creates Geometry objects on top of a given placement. */ typedef Geometry *(*create_geom_t)(char *); @@ -271,8 +279,11 @@ public: virtual uint init_from_opresult(String *bin, const char *opres, uint res_len) { return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; } + virtual bool init_from_json(json_engine_t *je, String *wkb) {return true;} virtual bool get_data_as_wkt(String *txt, const char **end) const=0; + virtual bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const=0; virtual bool get_mbr(MBR *mbr, const char **end) const=0; virtual bool dimension(uint32 *dim, const char **end) const=0; virtual int get_x(double *x) const { return -1; } @@ -302,9 +313,12 @@ public: bool init_stream=1); static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb, uint32 len, String *res); + static Geometry *create_from_json(Geometry_buffer *buffer, + json_engine_t *je, String *res); static Geometry *create_from_opresult(Geometry_buffer *g_buf, String *res, Gcalc_result_receiver &rr); int as_wkt(String *wkt, const char **end); + int as_json(String *wkt, uint max_dec_digits, const char **end); inline void set_data_ptr(const char *data, uint32 data_len) { @@ -379,7 +393,10 @@ public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); + bool init_from_json(json_engine_t *je, String *wkb); bool get_data_as_wkt(String *txt, const char **end) const; + bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int get_xy(double *x, double *y) const @@ -431,7 +448,10 @@ public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); + bool init_from_json(json_engine_t *je, String *wkb); bool get_data_as_wkt(String *txt, const char **end) const; + bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int geom_length(double *len, const char **end) const; int area(double *ar, const char **end) const; @@ -462,7 +482,10 @@ public: bool init_from_wkt(Gis_read_stream *trs, String *wkb); uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); uint init_from_opresult(String *bin, const char *opres, uint res_len); + bool init_from_json(json_engine_t *je, String *wkb); bool get_data_as_wkt(String *txt, const char **end) const; + bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int area(double *ar, const char **end) const; int exterior_ring(String *result) const; @@ -496,7 +519,10 @@ public: bool init_from_wkt(Gis_read_stream *trs, String *wkb); uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); uint init_from_opresult(String *bin, const char *opres, uint res_len); + bool init_from_json(json_engine_t *je, String *wkb); bool get_data_as_wkt(String *txt, const char **end) const; + bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; int geometry_n(uint32 num, String *result) const; @@ -522,7 +548,10 @@ public: bool init_from_wkt(Gis_read_stream *trs, String *wkb); uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); uint init_from_opresult(String *bin, const char *opres, uint res_len); + bool init_from_json(json_engine_t *je, String *wkb); bool get_data_as_wkt(String *txt, const char **end) const; + bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; int geometry_n(uint32 num, String *result) const; @@ -549,7 +578,10 @@ public: uint32 get_data_size() const; bool init_from_wkt(Gis_read_stream *trs, String *wkb); uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); + bool init_from_json(json_engine_t *je, String *wkb); bool get_data_as_wkt(String *txt, const char **end) const; + bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int num_geometries(uint32 *num) const; int geometry_n(uint32 num, String *result) const; @@ -578,7 +610,10 @@ public: bool init_from_wkt(Gis_read_stream *trs, String *wkb); uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res); uint init_from_opresult(String *bin, const char *opres, uint res_len); + bool init_from_json(json_engine_t *je, String *wkb); bool get_data_as_wkt(String *txt, const char **end) const; + bool get_data_as_json(String *txt, uint max_dec_digits, + const char **end) const; bool get_mbr(MBR *mbr, const char **end) const; int area(double *ar, const char **end) const; int geom_length(double *len, const char **end) const; diff --git a/strings/json_lib.c b/strings/json_lib.c index 47a3e37fa4c..16d7436ab6e 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1231,10 +1231,7 @@ int json_key_matches(json_engine_t *je, json_string_t *k) return 0; } - if (json_read_string_const_chr(k)) - return 1; - - return 0; + return json_read_string_const_chr(k); } From 6495806e59cc27313375fa8d431b7b8e777f73ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 24 Jan 2017 14:40:58 +0200 Subject: [PATCH 105/167] MDEV-11254: innodb-use-trim has no effect in 10.2 Problem was that implementation merged from 10.1 was incompatible with InnoDB 5.7. buf0buf.cc: Add functions to return should we punch hole and how big. buf0flu.cc: Add written page to IORequest fil0fil.cc: Remove unneeded status call and add test is sparse files and punch hole supported by file system when tablespace is created. Add call to get file system block size. Used file node is added to IORequest. Added functions to check is punch hole supported and setting punch hole. ha_innodb.cc: Remove unneeded status variables (trim512-32768) and trim_op_saved. Deprecate innodb_use_trim and set it ON by default. Add function to set innodb-use-trim dynamically. dberr.h: Add error code DB_IO_NO_PUNCH_HOLE if punch hole operation fails. fil0fil.h: Add punch_hole variable to fil_space_t and block size to fil_node_t. os0api.h: Header to helper functions on buf0buf.cc and fil0fil.cc for os0file.h os0file.h: Remove unneeded m_block_size from IORequest and add bpage to IORequest to know actual size of the block and m_fil_node to know tablespace file system block size and does it support punch hole. os0file.cc: Add function punch_hole() to IORequest to do punch_hole operation, get the file system block size and determine does file system support sparse files (for punch hole). page0size.h: remove implicit copy disable and use this implicit copy to implement copy_from() function. buf0dblwr.cc, buf0flu.cc, buf0rea.cc, fil0fil.cc, fil0fil.h, os0file.h, os0file.cc, log0log.cc, log0recv.cc: Remove unneeded write_size parameter from fil_io calls. srv0mon.h, srv0srv.h, srv0mon.cc: Remove unneeded trim512-trim32678 status variables. Removed these from monitor tests. --- .../t/innodb-discard-import-change.opt | 1 + .../innodb/include/have_innodb_punchhole.inc | 4 + mysql-test/suite/innodb/r/innodb-trim.result | 20 + .../suite/innodb/r/innodb_monitor.result | 8 - .../r/innodb_skip_innodb_is_tables.result | 8 - mysql-test/suite/innodb/t/innodb-trim.opt | 1 + mysql-test/suite/innodb/t/innodb-trim.test | 44 ++ .../r/innodb_monitor_disable_basic.result | 8 - .../r/innodb_monitor_enable_basic.result | 8 - .../r/innodb_monitor_reset_all_basic.result | 8 - .../r/innodb_monitor_reset_basic.result | 8 - .../sys_vars/r/innodb_use_trim_basic.result | 8 +- .../suite/sys_vars/r/sysvars_innodb.result | 6 +- storage/innobase/buf/buf0buf.cc | 27 + storage/innobase/buf/buf0dblwr.cc | 18 +- storage/innobase/buf/buf0flu.cc | 4 +- storage/innobase/buf/buf0rea.cc | 2 +- storage/innobase/fil/fil0fil.cc | 87 +++- storage/innobase/handler/ha_innodb.cc | 46 +- storage/innobase/include/db0err.h | 3 + storage/innobase/include/fil0fil.h | 18 +- storage/innobase/include/os0api.h | 75 +++ storage/innobase/include/os0file.h | 203 +++++++- storage/innobase/include/os0file.ic | 8 +- storage/innobase/include/page0size.h | 8 +- storage/innobase/include/srv0mon.h | 8 - storage/innobase/include/srv0srv.h | 32 -- storage/innobase/include/univ.i | 6 + storage/innobase/log/log0log.cc | 10 +- storage/innobase/log/log0recv.cc | 2 +- storage/innobase/os/os0file.cc | 461 +++++++++++++++--- storage/innobase/srv/srv0mon.cc | 64 --- storage/innobase/srv/srv0srv.cc | 5 +- storage/innobase/ut/ut0ut.cc | 2 + 34 files changed, 885 insertions(+), 336 deletions(-) create mode 100644 mysql-test/suite/encryption/t/innodb-discard-import-change.opt create mode 100644 mysql-test/suite/innodb/include/have_innodb_punchhole.inc create mode 100644 mysql-test/suite/innodb/r/innodb-trim.result create mode 100644 mysql-test/suite/innodb/t/innodb-trim.opt create mode 100644 mysql-test/suite/innodb/t/innodb-trim.test create mode 100644 storage/innobase/include/os0api.h diff --git a/mysql-test/suite/encryption/t/innodb-discard-import-change.opt b/mysql-test/suite/encryption/t/innodb-discard-import-change.opt new file mode 100644 index 00000000000..ebf13f41150 --- /dev/null +++ b/mysql-test/suite/encryption/t/innodb-discard-import-change.opt @@ -0,0 +1 @@ +--loose-innodb-use-trim=0 \ No newline at end of file diff --git a/mysql-test/suite/innodb/include/have_innodb_punchhole.inc b/mysql-test/suite/innodb/include/have_innodb_punchhole.inc new file mode 100644 index 00000000000..74cd5c4e0f2 --- /dev/null +++ b/mysql-test/suite/innodb/include/have_innodb_punchhole.inc @@ -0,0 +1,4 @@ +if (!`SELECT COUNT(*) FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE LOWER(variable_name) = 'innodb_have_punch_hole' AND variable_value = 'ON'`) +{ + --skip Test requires InnoDB compiled with fallocate(FALLOC_PUNCH_HOLE| FALLOC_KEEP_SIZE) +} diff --git a/mysql-test/suite/innodb/r/innodb-trim.result b/mysql-test/suite/innodb/r/innodb-trim.result new file mode 100644 index 00000000000..40eac2f8b40 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-trim.result @@ -0,0 +1,20 @@ +set global innodb_compression_algorithm = 1; +create table innodb_page_compressed (c1 int not null primary key auto_increment, b char(200), c char(200), d char(200)) engine=innodb page_compressed=1 page_compression_level=9; +show warnings; +Level Code Message +create procedure innodb_insert_proc (repeat_count int) +begin +declare current_num int; +set current_num = 0; +while current_num < repeat_count do +insert into innodb_page_compressed values (NULL,repeat('A',150),repeat('AB',75),repeat('B', 175)); +set current_num = current_num + 1; +end while; +end// +commit; +set autocommit=0; +call innodb_insert_proc(16000); +commit; +set autocommit=1; +DROP PROCEDURE innodb_insert_proc; +DROP TABLE innodb_page_compressed; diff --git a/mysql-test/suite/innodb/r/innodb_monitor.result b/mysql-test/suite/innodb/r/innodb_monitor.result index 0a163193b58..263da6070b2 100644 --- a/mysql-test/suite/innodb/r/innodb_monitor.result +++ b/mysql-test/suite/innodb/r/innodb_monitor.result @@ -181,16 +181,8 @@ compress_pages_decompressed disabled compression_pad_increments disabled compression_pad_decrements disabled compress_saved disabled -compress_trim_sect512 disabled -compress_trim_sect1024 disabled -compress_trim_sect2048 disabled -compress_trim_sect4096 disabled -compress_trim_sect8192 disabled -compress_trim_sect16384 disabled -compress_trim_sect32768 disabled compress_pages_page_compressed disabled compress_page_compressed_trim_op disabled -compress_page_compressed_trim_op_saved disabled compress_pages_page_decompressed disabled compress_pages_page_compression_error disabled compress_pages_encrypted disabled diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index 4875dfaeb2a..f515cb047f1 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -216,16 +216,8 @@ compress_pages_decompressed compression 0 NULL NULL NULL 0 NULL NULL NULL NULL N compression_pad_increments compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of times padding is incremented to avoid compression failures compression_pad_decrements compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of times padding is decremented due to good compressibility compress_saved compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of bytes saved by page compression -compress_trim_sect512 compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of sect-512 TRIMed by page compression -compress_trim_sect1024 compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of sect-1024 TRIMed by page compression -compress_trim_sect2048 compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of sect-2048 TRIMed by page compression -compress_trim_sect4096 compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of sect-4K TRIMed by page compression -compress_trim_sect8192 compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of sect-8K TRIMed by page compression -compress_trim_sect16384 compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of sect-16K TRIMed by page compression -compress_trim_sect32768 compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of sect-32K TRIMed by page compression compress_pages_page_compressed compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of pages compressed by page compression compress_page_compressed_trim_op compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of TRIM operation performed by page compression -compress_page_compressed_trim_op_saved compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of TRIM operation saved by page compression compress_pages_page_decompressed compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of pages decompressed by page compression compress_pages_page_compression_error compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of page compression errors compress_pages_encrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of pages encrypted diff --git a/mysql-test/suite/innodb/t/innodb-trim.opt b/mysql-test/suite/innodb/t/innodb-trim.opt new file mode 100644 index 00000000000..c33d075b002 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-trim.opt @@ -0,0 +1 @@ +--loose-innodb-use-trim=1 diff --git a/mysql-test/suite/innodb/t/innodb-trim.test b/mysql-test/suite/innodb/t/innodb-trim.test new file mode 100644 index 00000000000..1b64321116c --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-trim.test @@ -0,0 +1,44 @@ +--source include/have_innodb.inc +--source include/have_innodb_punchhole.inc + +--disable_query_log +--disable_warnings +let $innodb_compression_algorithm_orig=`SELECT @@innodb_compression_algorithm`; +--enable_warnings +--enable_query_log + +# zlib +set global innodb_compression_algorithm = 1; + +create table innodb_page_compressed (c1 int not null primary key auto_increment, b char(200), c char(200), d char(200)) engine=innodb page_compressed=1 page_compression_level=9; +show warnings; + +delimiter //; +create procedure innodb_insert_proc (repeat_count int) +begin + declare current_num int; + set current_num = 0; + while current_num < repeat_count do + insert into innodb_page_compressed values (NULL,repeat('A',150),repeat('AB',75),repeat('B', 175)); + set current_num = current_num + 1; + end while; +end// +delimiter ;// +commit; + +set autocommit=0; +call innodb_insert_proc(16000); +commit; +set autocommit=1; + +let $wait_condition= SELECT variable_value > 5 FROM information_schema.global_status WHERE variable_name = 'innodb_num_page_compressed_trim_op'; +--source include/wait_condition.inc + +DROP PROCEDURE innodb_insert_proc; +DROP TABLE innodb_page_compressed; + +--disable_query_log +--disable_warnings +EVAL SET GLOBAL innodb_compression_algorithm = $innodb_compression_algorithm_orig; +--enable_warnings +--enable_query_log diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result index 2a66a0d0931..ccd8e482756 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_disable_basic.result @@ -181,16 +181,8 @@ compress_pages_decompressed disabled compression_pad_increments disabled compression_pad_decrements disabled compress_saved disabled -compress_trim_sect512 disabled -compress_trim_sect1024 disabled -compress_trim_sect2048 disabled -compress_trim_sect4096 disabled -compress_trim_sect8192 disabled -compress_trim_sect16384 disabled -compress_trim_sect32768 disabled compress_pages_page_compressed disabled compress_page_compressed_trim_op disabled -compress_page_compressed_trim_op_saved disabled compress_pages_page_decompressed disabled compress_pages_page_compression_error disabled compress_pages_encrypted disabled diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result index 2a66a0d0931..ccd8e482756 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_enable_basic.result @@ -181,16 +181,8 @@ compress_pages_decompressed disabled compression_pad_increments disabled compression_pad_decrements disabled compress_saved disabled -compress_trim_sect512 disabled -compress_trim_sect1024 disabled -compress_trim_sect2048 disabled -compress_trim_sect4096 disabled -compress_trim_sect8192 disabled -compress_trim_sect16384 disabled -compress_trim_sect32768 disabled compress_pages_page_compressed disabled compress_page_compressed_trim_op disabled -compress_page_compressed_trim_op_saved disabled compress_pages_page_decompressed disabled compress_pages_page_compression_error disabled compress_pages_encrypted disabled diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result index 2a66a0d0931..ccd8e482756 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_all_basic.result @@ -181,16 +181,8 @@ compress_pages_decompressed disabled compression_pad_increments disabled compression_pad_decrements disabled compress_saved disabled -compress_trim_sect512 disabled -compress_trim_sect1024 disabled -compress_trim_sect2048 disabled -compress_trim_sect4096 disabled -compress_trim_sect8192 disabled -compress_trim_sect16384 disabled -compress_trim_sect32768 disabled compress_pages_page_compressed disabled compress_page_compressed_trim_op disabled -compress_page_compressed_trim_op_saved disabled compress_pages_page_decompressed disabled compress_pages_page_compression_error disabled compress_pages_encrypted disabled diff --git a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result index 2a66a0d0931..ccd8e482756 100644 --- a/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_monitor_reset_basic.result @@ -181,16 +181,8 @@ compress_pages_decompressed disabled compression_pad_increments disabled compression_pad_decrements disabled compress_saved disabled -compress_trim_sect512 disabled -compress_trim_sect1024 disabled -compress_trim_sect2048 disabled -compress_trim_sect4096 disabled -compress_trim_sect8192 disabled -compress_trim_sect16384 disabled -compress_trim_sect32768 disabled compress_pages_page_compressed disabled compress_page_compressed_trim_op disabled -compress_page_compressed_trim_op_saved disabled compress_pages_page_decompressed disabled compress_pages_page_compression_error disabled compress_pages_encrypted disabled diff --git a/mysql-test/suite/sys_vars/r/innodb_use_trim_basic.result b/mysql-test/suite/sys_vars/r/innodb_use_trim_basic.result index 63292f5d3c8..6ab0a19fb57 100644 --- a/mysql-test/suite/sys_vars/r/innodb_use_trim_basic.result +++ b/mysql-test/suite/sys_vars/r/innodb_use_trim_basic.result @@ -1,12 +1,14 @@ SET @start_use_trim = @@global.innodb_use_trim; SELECT @start_use_trim; @start_use_trim -0 +1 SELECT COUNT(@@GLOBAL.innodb_use_trim); COUNT(@@GLOBAL.innodb_use_trim) 1 1 Expected SET @@GLOBAL.innodb_use_trim=1; +Warnings: +Warning 131 Using innodb_use_trim is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SELECT COUNT(@@GLOBAL.innodb_use_trim); COUNT(@@GLOBAL.innodb_use_trim) 1 @@ -28,6 +30,8 @@ COUNT(VARIABLE_VALUE) 1 1 Expected SET @@global.innodb_use_trim = @start_use_trim; +Warnings: +Warning 131 Using innodb_use_trim is deprecated and the parameter may be removed in future releases. See http://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html SELECT @@global.innodb_use_trim; @@global.innodb_use_trim -0 +1 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index b4c7b2cc1fb..5954b057d2f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -2612,12 +2612,12 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT NONE VARIABLE_NAME INNODB_USE_TRIM SESSION_VALUE NULL -GLOBAL_VALUE OFF +GLOBAL_VALUE ON GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE OFF +DEFAULT_VALUE ON VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT Use trim. Default FALSE. +VARIABLE_COMMENT Deallocate (punch_hole|trim) unused portions of the page compressed page (on by default) NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 315c951a9fe..0f1d170b172 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -35,6 +35,7 @@ Created 11/5/1995 Heikki Tuuri #include "page0size.h" #include "buf0buf.h" +#include "os0api.h" #ifdef UNIV_NONINL #include "buf0buf.ic" @@ -7659,4 +7660,30 @@ buf_page_decrypt_after_read( return (success); } + +/** +Should we punch hole to deallocate unused portion of the page. +@param[in] bpage Page control block +@return true if punch hole should be used, false if not */ +bool +buf_page_should_punch_hole( + const buf_page_t* bpage) +{ + return (bpage->real_size != bpage->size.physical()); +} + +/** +Calculate the length of trim (punch_hole) operation. +@param[in] bpage Page control block +@param[in] write_length Write length +@return length of the trim or zero. */ +ulint +buf_page_get_trim_length( + const buf_page_t* bpage, + ulint write_length) +{ + return (bpage->size.physical() - write_length); +} + + #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 4deee54d97f..4f83921a553 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -591,7 +591,7 @@ buf_dblwr_process(void) dberr_t err = fil_io( request, true, page_id, page_size, - 0, page_size.physical(), read_buf, NULL, NULL); + 0, page_size.physical(), read_buf, NULL); if (err != DB_SUCCESS) { ib::warn() @@ -679,7 +679,7 @@ buf_dblwr_process(void) fil_io(write_request, true, page_id, page_size, 0, page_size.physical(), - const_cast(page), NULL, NULL); + const_cast(page), NULL); ib::info() << "Recovered page " << page_id << " from the doublewrite buffer."; @@ -912,7 +912,7 @@ buf_dblwr_write_block_to_datafile( type |= IORequest::DO_NOT_WAKE; } - IORequest request(type); + IORequest request(type, const_cast(bpage)); /* We request frame here to get correct buffer in case of encryption and/or page compression */ @@ -924,7 +924,7 @@ buf_dblwr_write_block_to_datafile( fil_io(request, sync, bpage->id, bpage->size, 0, bpage->size.physical(), (void*) frame, - (void*) bpage, NULL); + (void*) bpage); } else { ut_ad(!bpage->size.is_compressed()); @@ -938,8 +938,8 @@ buf_dblwr_write_block_to_datafile( buf_dblwr_check_page_lsn(block->frame); fil_io(request, - sync, bpage->id, bpage->size, 0, bpage->size.physical(), - frame, block, (ulint *)&bpage->write_size); + sync, bpage->id, bpage->size, 0, bpage->real_size, + frame, block); } } @@ -1041,7 +1041,7 @@ try_again: fil_io(IORequestWrite, true, page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), univ_page_size, - 0, len, (void*) write_buf, NULL, NULL); + 0, len, (void*) write_buf, NULL); if (buf_dblwr->first_free <= TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { /* No unwritten pages in the second block. */ @@ -1057,7 +1057,7 @@ try_again: fil_io(IORequestWrite, true, page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), univ_page_size, - 0, len, (void*) write_buf, NULL, NULL); + 0, len, (void*) write_buf, NULL); flush: /* increment the doublewrite flushed pages counter */ @@ -1292,7 +1292,6 @@ retry: 0, univ_page_size.physical(), (void *)(buf_dblwr->write_buf + univ_page_size.physical() * i), - NULL, NULL); } else { /* It is a regular page. Write it directly to the @@ -1304,7 +1303,6 @@ retry: 0, univ_page_size.physical(), (void*) frame, - NULL, NULL); } diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 2738fbd0ec7..5fdb735e0d3 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1093,11 +1093,11 @@ buf_flush_write_block_low( ulint type = IORequest::WRITE | IORequest::DO_NOT_WAKE; - IORequest request(type); + IORequest request(type, bpage); fil_io(request, sync, bpage->id, bpage->size, 0, bpage->size.physical(), - frame, bpage, NULL); + frame, bpage); } else { if (flush_type == BUF_FLUSH_SINGLE_PAGE) { buf_dblwr_write_single_page(bpage, sync); diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index ea3c1ceccf9..4d68ad5ac51 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -182,7 +182,7 @@ buf_read_page_low( *err = fil_io( request, sync, page_id, page_size, 0, page_size.physical(), - dst, bpage, NULL); + dst, bpage); if (sync) { thd_wait_end(NULL); diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index a0442808eaa..75067bc075e 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -58,6 +58,7 @@ Created 10/25/1995 Heikki Tuuri #include "srv0start.h" #include "trx0purge.h" #include "ut0new.h" +#include "os0api.h" /** Tries to close a file in the LRU list. The caller must hold the fil_sys mutex. @@ -280,7 +281,7 @@ fil_read( void* buf) { return(fil_io(IORequestRead, true, page_id, page_size, - byte_offset, len, buf, NULL, NULL)); + byte_offset, len, buf, NULL)); } /** Writes data to a space from a buffer. Remember that the possible incomplete @@ -308,7 +309,7 @@ fil_write( ut_ad(!srv_read_only_mode); return(fil_io(IORequestWrite, true, page_id, page_size, - byte_offset, len, buf, NULL, NULL)); + byte_offset, len, buf, NULL)); } /*******************************************************************//** @@ -524,20 +525,6 @@ fil_node_create_low( node->space = space; - os_file_stat_t stat_info; - -#ifdef UNIV_DEBUG - dberr_t err = -#endif /* UNIV_DEBUG */ - - os_file_get_status( - node->name, &stat_info, false, - fsp_is_system_temporary(space->id) ? true : srv_read_only_mode); - - ut_ad(err == DB_SUCCESS); - - node->block_size = stat_info.block_size; - node->atomic_write = atomic_write; UT_LIST_ADD_LAST(space->chain, node); @@ -1043,7 +1030,7 @@ fil_write_zeros( err = os_aio( request, OS_AIO_SYNC, node->name, node->handle, buf, offset, n_bytes, read_only_mode, - NULL, NULL, NULL); + NULL, NULL); if (err != DB_SUCCESS) { break; @@ -3758,12 +3745,31 @@ fil_ibd_create( success = true; } #endif /* HAVE_POSIX_FALLOCATE */ - if (!success) - { + + if (!success) { success = os_file_set_size( path, file, size * UNIV_PAGE_SIZE, srv_read_only_mode); } + /* Note: We are actually punching a hole, previous contents will + be lost after this call, if it succeeds. In this case the file + should be full of NULs. */ + + bool punch_hole = os_is_sparse_file_supported(path, file); + + if (punch_hole) { + + dberr_t punch_err; + + punch_err = os_file_punch_hole(file, 0, size * UNIV_PAGE_SIZE); + + if (punch_err != DB_SUCCESS) { + punch_hole = false; + } + } + + ulint block_size = os_file_get_block_size(file, path); + if (!success) { os_file_close(file); os_file_delete(innodb_data_file_key, path); @@ -3866,7 +3872,13 @@ fil_ibd_create( space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE, crypt_data, true); - if (!fil_node_create_low(path, size, space, false, true)) { + fil_node_t* node = NULL; + + if (space) { + node = fil_node_create_low(path, size, space, false, true); + } + + if (!space || !node) { if (crypt_data) { free(crypt_data); } @@ -3883,6 +3895,9 @@ fil_ibd_create( fil_name_write(space, 0, file, &mtr); mtr.commit(); + node->block_size = block_size; + space->punch_hole = punch_hole; + err = DB_SUCCESS; } @@ -5038,8 +5053,6 @@ fil_report_invalid_page_access( aligned @param[in] message message for aio handler if non-sync aio used, else ignored -@param[in] write_size actual payload size when written - to avoid extra punch holes in compression @return DB_SUCCESS, DB_TABLESPACE_DELETED or DB_TABLESPACE_TRUNCATED if we are trying to do i/o on a tablespace which does not exist */ dberr_t @@ -5051,8 +5064,7 @@ fil_io( ulint byte_offset, ulint len, void* buf, - void* message, - ulint* write_size) + void* message) { os_offset_t offset; IORequest req_type(type); @@ -5285,7 +5297,7 @@ fil_io( const char* name = node->name == NULL ? space->name : node->name; - req_type.block_size(node->block_size); + req_type.set_fil_node(node); /* Queue the aio request */ dberr_t err = os_aio( @@ -5293,7 +5305,7 @@ fil_io( mode, name, node->handle, buf, offset, len, space->purpose != FIL_TYPE_TEMPORARY && srv_read_only_mode, - node, message, write_size); + node, message); /* We an try to recover the page from the double write buffer if the decompression fails or the page is corrupt. */ @@ -6973,3 +6985,26 @@ fil_system_exit(void) ut_ad(mutex_own(&fil_system->mutex)); mutex_exit(&fil_system->mutex); } + +/** +Get should we punch hole to tablespace. +@param[in] node File node +@return true, if punch hole should be tried, false if not. */ +bool +fil_node_should_punch_hole( + const fil_node_t* node) +{ + return (node->space->punch_hole); +} + +/** +Set punch hole to tablespace to given value. +@param[in] node File node +@param[in] val value to be set. */ +void +fil_space_set_punch_hole( + fil_node_t* node, + bool val) +{ + node->space->punch_hole = val; +} diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a5fd7788af2..271abc3e86d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -927,6 +927,7 @@ static ibool innodb_have_lz4=IF_LZ4(1, 0); static ibool innodb_have_lzma=IF_LZMA(1, 0); static ibool innodb_have_bzip2=IF_BZIP2(1, 0); static ibool innodb_have_snappy=IF_SNAPPY(1, 0); +static ibool innodb_have_punch_hole=IF_PUNCH_HOLE(1, 0); static int @@ -1134,20 +1135,6 @@ static SHOW_VAR innodb_status_variables[]= { /* Status variables for page compression */ {"page_compression_saved", (char*) &export_vars.innodb_page_compression_saved, SHOW_LONGLONG}, - {"page_compression_trim_sect512", - (char*) &export_vars.innodb_page_compression_trim_sect512, SHOW_LONGLONG}, - {"page_compression_trim_sect1024", - (char*) &export_vars.innodb_page_compression_trim_sect1024, SHOW_LONGLONG}, - {"page_compression_trim_sect2048", - (char*) &export_vars.innodb_page_compression_trim_sect2048, SHOW_LONGLONG}, - {"page_compression_trim_sect4096", - (char*) &export_vars.innodb_page_compression_trim_sect4096, SHOW_LONGLONG}, - {"page_compression_trim_sect8192", - (char*) &export_vars.innodb_page_compression_trim_sect8192, SHOW_LONGLONG}, - {"page_compression_trim_sect16384", - (char*) &export_vars.innodb_page_compression_trim_sect16384, SHOW_LONGLONG}, - {"page_compression_trim_sect32768", - (char*) &export_vars.innodb_page_compression_trim_sect32768, SHOW_LONGLONG}, {"num_index_pages_written", (char*) &export_vars.innodb_index_pages_written, SHOW_LONGLONG}, {"num_non_index_pages_written", @@ -1156,8 +1143,6 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_pages_page_compressed, SHOW_LONGLONG}, {"num_page_compressed_trim_op", (char*) &export_vars.innodb_page_compressed_trim_op, SHOW_LONGLONG}, - {"num_page_compressed_trim_op_saved", - (char*) &export_vars.innodb_page_compressed_trim_op_saved, SHOW_LONGLONG}, {"num_pages_page_decompressed", (char*) &export_vars.innodb_pages_page_decompressed, SHOW_LONGLONG}, {"num_pages_page_compression_error", @@ -1176,6 +1161,8 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &innodb_have_bzip2, SHOW_BOOL}, {"have_snappy", (char*) &innodb_have_snappy, SHOW_BOOL}, + {"have_punch_hole", + (char*) &innodb_have_punch_hole, SHOW_BOOL}, /* Defragmentation */ {"defragment_compression_failures", @@ -3830,6 +3817,10 @@ static const char* deprecated_file_format_check static const char* deprecated_file_format_max = DEPRECATED_FORMAT_PARAMETER("innodb_file_format_max"); +/** Deprecation message about innodb_use_trim */ +static const char* deprecated_use_trim + = DEPRECATED_FORMAT_PARAMETER("innodb_use_trim"); + /** Update log_checksum_algorithm_ptr with a pointer to the function corresponding to whether checksums are enabled. @param[in] check whether redo log block checksums are enabled */ @@ -20660,6 +20651,25 @@ wsrep_fake_trx_id( #endif /* WITH_WSREP */ +/** Update the innodb_use_trim parameter. +@param[in] thd thread handle +@param[in] var system variable +@param[out] var_ptr current value +@param[in] save immediate result from check function */ +static +void +innodb_use_trim_update( + THD* thd, + struct st_mysql_sys_var* var, + void* var_ptr, + const void* save) +{ + srv_use_trim = *static_cast(save); + + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + HA_ERR_WRONG_COMMAND, deprecated_use_trim); +} + /* plugin options */ static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm, @@ -21761,8 +21771,8 @@ static MYSQL_SYSVAR_BOOL(force_primary_key, static MYSQL_SYSVAR_BOOL(use_trim, srv_use_trim, PLUGIN_VAR_OPCMDARG, - "Use trim. Default FALSE.", - NULL, NULL, FALSE); + "Deallocate (punch_hole|trim) unused portions of the page compressed page (on by default)", + NULL, innodb_use_trim_update, TRUE); static const char *page_compression_algorithms[]= { "none", "zlib", "lz4", "lzo", "lzma", "bzip2", "snappy", 0 }; static TYPELIB page_compression_algorithms_typelib= diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index 316d90bec34..972d99553b9 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -160,6 +160,9 @@ enum dberr_t { placed on the base column of stored column */ + DB_IO_NO_PUNCH_HOLE, /*!< Punch hole not supported by + file system. */ + /* The following are partial failure codes */ DB_FAIL = 1000, DB_OVERFLOW, diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 7428ff2c936..bd6067fbbee 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -185,6 +185,10 @@ struct fil_space_t { @param[in] n_reserved number of reserved extents */ void release_free_extents(ulint n_reserved); + /** True if file system storing this tablespace supports + punch hole */ + bool punch_hole; + ulint magic_n;/*!< FIL_SPACE_MAGIC_N */ }; @@ -229,12 +233,12 @@ struct fil_node_t { /** link to the fil_system->LRU list (keeping track of open files) */ UT_LIST_NODE_T(fil_node_t) LRU; - /** block size to use for punching holes */ - ulint block_size; - /** whether this file could use atomic write (data file) */ bool atomic_write; + /** Filesystem block size */ + ulint block_size; + /** FIL_NODE_MAGIC_N */ ulint magic_n; }; @@ -1129,11 +1133,6 @@ fil_space_get_n_reserved_extents( aligned @param[in] message message for aio handler if non-sync aio used, else ignored -@param[in,out] write_size Actual write size initialized - after fist successfull trim - operation for this page and if - nitialized we do not trim again if - Actual page @return DB_SUCCESS, DB_TABLESPACE_DELETED or DB_TABLESPACE_TRUNCATED if we are trying to do i/o on a tablespace which does not exist */ @@ -1146,8 +1145,7 @@ fil_io( ulint byte_offset, ulint len, void* buf, - void* message, - ulint* write_size); + void* message); /**********************************************************************//** Waits for an aio operation to complete. This function is used to write the handler for completed requests. The aio array of pending requests is divided diff --git a/storage/innobase/include/os0api.h b/storage/innobase/include/os0api.h new file mode 100644 index 00000000000..ea2a113bdec --- /dev/null +++ b/storage/innobase/include/os0api.h @@ -0,0 +1,75 @@ +/*********************************************************************** + +Copyright (c) 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 Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + +***********************************************************************/ + +/**************************************************//** +@file os0api.h +The interface to the helper functions. +These functions are used on os0file.h where +including full full header is not feasible and +implemented on buf0buf.cc and fil0fil.cc. +*******************************************************/ + +#ifndef OS_API_H +#define OS_API_H 1 + +/** Page control block */ +struct buf_page_t; + +/** File Node */ +struct fil_node_t; + +/** +Should we punch hole to deallocate unused portion of the page. +@param[in] bpage Page control block +@return true if punch hole should be used, false if not */ +bool +buf_page_should_punch_hole( + const buf_page_t* bpage) + MY_ATTRIBUTE((warn_unused_result)); + +/** +Calculate the length of trim (punch_hole) operation. +@param[in] bpage Page control block +@param[in] write_length Write length +@return length of the trim or zero. */ +ulint +buf_page_get_trim_length( + const buf_page_t* bpage, + ulint write_length) + MY_ATTRIBUTE((warn_unused_result)); + +/** +Get should we punch hole to tablespace. +@param[in] space Tablespace +@return true, if punch hole should be tried, false if not. */ +bool +fil_node_should_punch_hole( + const fil_node_t* node) + MY_ATTRIBUTE((warn_unused_result)); + +/** +Set punch hole to tablespace to given value. +@param[in] space Tablespace +@param[in] val value to be set. */ +void +fil_space_set_punch_hole( + fil_node_t* node, + bool val); + +#endif /* OS_API_H */ diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 57ee015dfdd..6a97ff3aa53 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -36,7 +36,8 @@ Created 10/21/1995 Heikki Tuuri #ifndef os0file_h #define os0file_h -#include "univ.i" +#include "page0size.h" +#include "os0api.h" #ifndef _WIN32 #include @@ -46,8 +47,10 @@ Created 10/21/1995 Heikki Tuuri /** File node of a tablespace or the log data space */ struct fil_node_t; +struct fil_space_t; extern bool os_has_said_disk_full; +extern my_bool srv_use_trim; /** Number of pending read operations */ extern ulint os_n_pending_reads; @@ -177,6 +180,8 @@ static const ulint OS_FILE_ERROR_MAX = 200; #define IORequestLogRead IORequest(IORequest::LOG | IORequest::READ) #define IORequestLogWrite IORequest(IORequest::LOG | IORequest::WRITE) + + /** The IO Context that is passed down to the low level IO code */ class IORequest { @@ -211,12 +216,16 @@ public: /** Ignore failed reads of non-existent pages */ IGNORE_MISSING = 128, + + /** Use punch hole if available*/ + PUNCH_HOLE = 256, }; /** Default constructor */ IORequest() : - m_block_size(UNIV_SECTOR_SIZE), + m_bpage(NULL), + m_fil_node(NULL), m_type(READ) { /* No op */ @@ -227,9 +236,32 @@ public: ORed from the above enum */ explicit IORequest(ulint type) : - m_block_size(UNIV_SECTOR_SIZE), + m_bpage(NULL), + m_fil_node(NULL), m_type(static_cast(type)) { + if (!is_punch_hole_supported() || !srv_use_trim) { + clear_punch_hole(); + } + } + + /** + @param[in] type Request type, can be a value that is + ORed from the above enum + @param[in] bpage Page to be written */ + IORequest(ulint type, buf_page_t* bpage) + : + m_bpage(bpage), + m_fil_node(NULL), + m_type(static_cast(type)) + { + if (bpage && buf_page_should_punch_hole(bpage)) { + set_punch_hole(); + } + + if (!is_punch_hole_supported() || !srv_use_trim) { + clear_punch_hole(); + } } /** Destructor */ @@ -270,6 +302,12 @@ public: return((m_type & DO_NOT_WAKE) == 0); } + /** Clear the punch hole flag */ + void clear_punch_hole() + { + m_type &= ~PUNCH_HOLE; + } + /** @return true if partial read warning disabled */ bool is_partial_io_warning_disabled() const MY_ATTRIBUTE((warn_unused_result)) @@ -291,6 +329,13 @@ public: return(ignore_missing(m_type)); } + /** @return true if punch hole should be used */ + bool punch_hole() const + MY_ATTRIBUTE((warn_unused_result)) + { + return((m_type & PUNCH_HOLE) == PUNCH_HOLE); + } + /** @return true if the read should be validated */ bool validate() const MY_ATTRIBUTE((warn_unused_result)) @@ -298,24 +343,30 @@ public: return(is_read() ^ is_write()); } + /** Set the punch hole flag */ + void set_punch_hole() + { + if (is_punch_hole_supported() && srv_use_trim) { + m_type |= PUNCH_HOLE; + } + } + /** Clear the do not wake flag */ void clear_do_not_wake() { m_type &= ~DO_NOT_WAKE; } - /** @return the block size to use for IO */ - ulint block_size() const - MY_ATTRIBUTE((warn_unused_result)) + /** Set the pointer to file node for IO + @param[in] node File node */ + void set_fil_node(fil_node_t* node) { - return(m_block_size); - } + if (!srv_use_trim || + (node && !fil_node_should_punch_hole(node))) { + clear_punch_hole(); + } - /** Set the block size for IO - @param[in] block_size Block size to set */ - void block_size(ulint block_size) - { - m_block_size = static_cast(block_size); + m_fil_node = node; } /** Compare two requests @@ -338,9 +389,59 @@ public: return((m_type & DBLWR_RECOVER) == DBLWR_RECOVER); } + /** @return true if punch hole is supported */ + static bool is_punch_hole_supported() + { + + /* In this debugging mode, we act as if punch hole is supported, + and then skip any calls to actually punch a hole here. + In this way, Transparent Page Compression is still being tested. */ + DBUG_EXECUTE_IF("ignore_punch_hole", + return(true); + ); + +#if defined(HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32) + return(true); +#else + return(false); +#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE || _WIN32 */ + } + + ulint get_trim_length(ulint write_length) const + { + return (m_bpage ? + buf_page_get_trim_length(m_bpage, write_length) + : 0); + } + + bool should_punch_hole() const { + return (m_fil_node ? + fil_node_should_punch_hole(m_fil_node) + : false); + } + + void space_no_punch_hole() const { + if (m_fil_node) { + fil_space_set_punch_hole(m_fil_node, false); + } + } + + /** Punch a hole in the file if it was a write + @param[in] fh Open file handle + @param[in] len Compressed buffer length for write + @return DB_SUCCESS or error code */ + + dberr_t punch_hole( + os_file_t fh, + ulint offset, + ulint len); + private: - /* File system best block size */ - uint32_t m_block_size; + /** Page to be written on write operation. */ + buf_page_t* m_bpage; + + /** File node */ + fil_node_t* m_fil_node; /** Request type bit flags */ uint16_t m_type; @@ -706,10 +807,10 @@ The wrapper functions have the prefix of "innodb_". */ # define os_file_close(file) \ pfs_os_file_close_func(file, __FILE__, __LINE__) -# define os_aio(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize) \ - pfs_os_aio_func(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize, \ +# define os_aio(type, mode, name, file, buf, offset, \ + n, read_only, message1, message2) \ + pfs_os_aio_func(type, mode, name, file, buf, offset, \ + n, read_only, message1, message2, \ __FILE__, __LINE__) # define os_file_read(type, file, buf, offset, n) \ @@ -721,7 +822,7 @@ The wrapper functions have the prefix of "innodb_". */ # define os_file_write(type, name, file, buf, offset, n) \ pfs_os_file_write_func(type, name, file, buf, offset, \ - n, __FILE__, __LINE__) + n,__FILE__, __LINE__) # define os_file_flush(file) \ pfs_os_file_flush_func(file, __FILE__, __LINE__) @@ -926,7 +1027,6 @@ pfs_os_aio_func( bool read_only, fil_node_t* m1, void* m2, - ulint* wsize, const char* src_file, ulint src_line); @@ -1051,9 +1151,9 @@ to original un-instrumented file I/O APIs */ # define os_file_close(file) os_file_close_func(file) # define os_aio(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize) \ + n, read_only, message1, message2) \ os_aio_func(type, mode, name, file, buf, offset, \ - n, read_only, message1, message2, wsize) + n, read_only, message1, message2) # define os_file_read(type, file, buf, offset, n) \ os_file_read_func(type, file, buf, offset, n) @@ -1061,7 +1161,7 @@ to original un-instrumented file I/O APIs */ # define os_file_read_no_error_handling(type, file, buf, offset, n, o) \ os_file_read_no_error_handling_func(type, file, buf, offset, n, o) -# define os_file_write(type, name, file, buf, offset, n) \ +# define os_file_write(type, name, file, buf, offset, n) \ os_file_write_func(type, name, file, buf, offset, n) # define os_file_flush(file) os_file_flush_func(file) @@ -1324,8 +1424,7 @@ os_aio_func( ulint n, bool read_only, fil_node_t* m1, - void* m2, - ulint* wsize); + void* m2); /** Wakes up all async i/o threads so that they know to exit themselves in shutdown. */ @@ -1427,6 +1526,48 @@ innobase_mysql_tmpfile( void os_file_set_umask(ulint umask); +/** Check if the file system supports sparse files. + +Warning: On POSIX systems we try and punch a hole from offset 0 to +the system configured page size. This should only be called on an empty +file. + +Note: On Windows we use the name and on Unices we use the file handle. + +@param[in] name File name +@param[in] fh File handle for the file - if opened +@return true if the file system supports sparse files */ +bool +os_is_sparse_file_supported( + const char* path, + os_file_t fh) + MY_ATTRIBUTE((warn_unused_result)); + +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return DB_SUCCESS or error code */ +dberr_t +os_file_punch_hole( + IORequest& type, + os_file_t fh, + os_offset_t off, + os_offset_t len) + MY_ATTRIBUTE((warn_unused_result)); + +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return DB_SUCCESS or error code */ +dberr_t +os_file_punch_hole( + os_file_t fh, + os_offset_t off, + os_offset_t len) + MY_ATTRIBUTE((warn_unused_result)); + /** Normalizes a directory path for the current OS: On Windows, we convert '/' to '\', else we convert '\' to '/'. @param[in,out] str A null-terminated directory and file path */ @@ -1454,6 +1595,16 @@ is_absolute_path( return(false); } +/***********************************************************************//** +Try to get number of bytes per sector from file system. +@return file block size */ +UNIV_INTERN +ulint +os_file_get_block_size( +/*===================*/ + os_file_t file, /*!< in: handle to a file */ + const char* name); /*!< in: file name */ + #ifndef UNIV_NONINL #include "os0file.ic" #endif /* UNIV_NONINL */ diff --git a/storage/innobase/include/os0file.ic b/storage/innobase/include/os0file.ic index 3e78b87a177..5c7c4d45ca6 100644 --- a/storage/innobase/include/os0file.ic +++ b/storage/innobase/include/os0file.ic @@ -219,11 +219,6 @@ an asynchronous i/o operation. @param[in,out] m2 message for the AIO handler (can be used to identify a completed AIO operation); ignored if mode is OS_AIO_SYNC -@param[in,out] write_size Actual write size initialized - after fist successfull trim - operation for this page and if - initialized we do not trim again if - actual page size @param[in] src_file file name where func invoked @param[in] src_line line where the func invoked @return DB_SUCCESS if request was queued successfully, FALSE if fail */ @@ -240,7 +235,6 @@ pfs_os_aio_func( bool read_only, fil_node_t* m1, void* m2, - ulint* write_size, const char* src_file, ulint src_line) { @@ -256,7 +250,7 @@ pfs_os_aio_func( src_file, src_line); dberr_t result = os_aio_func( - type, mode, name, file, buf, offset, n, read_only, m1, m2, write_size); + type, mode, name, file, buf, offset, n, read_only, m1, m2); register_pfs_file_io_end(locker, n); diff --git a/storage/innobase/include/page0size.h b/storage/innobase/include/page0size.h index ab917e1ff05..ca173db9b6d 100644 --- a/storage/innobase/include/page0size.h +++ b/storage/innobase/include/page0size.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -139,9 +140,7 @@ public: @param[in] src page size object whose values to fetch */ inline void copy_from(const page_size_t& src) { - m_physical = src.physical(); - m_logical = src.logical(); - m_is_compressed = src.is_compressed(); + *this = src; } /** Check if a given page_size_t object is equal to the current one. @@ -156,9 +155,6 @@ public: private: - /* Disable implicit copying. */ - void operator=(const page_size_t&); - /* For non compressed tablespaces, physical page size is equal to the logical page size and the data is stored in buf_page_t::frame (and is also always equal to univ_page_size (--innodb-page-size=)). diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index e4e1394c2d3..5c19e735806 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -343,16 +343,8 @@ enum monitor_id_t { MONITOR_PAD_DECREMENTS, /* New monitor variables for page compression */ MONITOR_OVLD_PAGE_COMPRESS_SAVED, - MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT512, - MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT1024, - MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT2048, - MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT4096, - MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT8192, - MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT16384, - MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT32768, MONITOR_OVLD_PAGES_PAGE_COMPRESSED, MONITOR_OVLD_PAGE_COMPRESSED_TRIM_OP, - MONITOR_OVLD_PAGE_COMPRESSED_TRIM_OP_SAVED, MONITOR_OVLD_PAGES_PAGE_DECOMPRESSED, MONITOR_OVLD_PAGES_PAGE_COMPRESSION_ERROR, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 227bcfb7781..ca81ad46b8b 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -114,20 +114,6 @@ struct srv_stats_t { /** Number of bytes saved by page compression */ ulint_ctr_64_t page_compression_saved; - /** Number of 512Byte TRIM by page compression */ - ulint_ctr_64_t page_compression_trim_sect512; - /** Number of 1K TRIM by page compression */ - ulint_ctr_64_t page_compression_trim_sect1024; - /** Number of 2K TRIM by page compression */ - ulint_ctr_64_t page_compression_trim_sect2048; - /** Number of 4K TRIM by page compression */ - ulint_ctr_64_t page_compression_trim_sect4096; - /** Number of 8K TRIM by page compression */ - ulint_ctr_64_t page_compression_trim_sect8192; - /** Number of 16K TRIM by page compression */ - ulint_ctr_64_t page_compression_trim_sect16384; - /** Number of 32K TRIM by page compression */ - ulint_ctr_64_t page_compression_trim_sect32768; /* Number of index pages written */ ulint_ctr_64_t index_pages_written; /* Number of non index pages written */ @@ -136,8 +122,6 @@ struct srv_stats_t { ulint_ctr_64_t pages_page_compressed; /* Number of TRIM operations induced by page compression */ ulint_ctr_64_t page_compressed_trim_op; - /* Number of TRIM operations saved by using actual write size knowledge */ - ulint_ctr_64_t page_compressed_trim_op_saved; /* Number of pages decompressed with page compression */ ulint_ctr_64_t pages_page_decompressed; /* Number of page compression errors */ @@ -1059,20 +1043,6 @@ struct export_var_t{ int64_t innodb_page_compression_saved;/*!< Number of bytes saved by page compression */ - int64_t innodb_page_compression_trim_sect512;/*!< Number of 512b TRIM - by page compression */ - int64_t innodb_page_compression_trim_sect1024;/*!< Number of 1K TRIM - by page compression */ - int64_t innodb_page_compression_trim_sect2048;/*!< Number of 2K TRIM - by page compression */ - int64_t innodb_page_compression_trim_sect4096;/*!< Number of 4K byte TRIM - by page compression */ - int64_t innodb_page_compression_trim_sect8192;/*!< Number of 8K TRIM - by page compression */ - int64_t innodb_page_compression_trim_sect16384;/*!< Number of 16K TRIM - by page compression */ - int64_t innodb_page_compression_trim_sect32768;/*!< Number of 32K TRIM - by page compression */ int64_t innodb_index_pages_written; /*!< Number of index pages written */ int64_t innodb_non_index_pages_written; /*!< Number of non index pages @@ -1081,8 +1051,6 @@ struct export_var_t{ compressed by page compression */ int64_t innodb_page_compressed_trim_op;/*!< Number of TRIM operations induced by page compression */ - int64_t innodb_page_compressed_trim_op_saved;/*!< Number of TRIM operations - saved by page compression */ int64_t innodb_pages_page_decompressed;/*!< Number of pages decompressed by page compression */ diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 35ea9fd51be..908fb60e956 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -366,6 +366,12 @@ typedef enum innodb_file_formats_enum innodb_file_formats_t; #define IF_SNAPPY(A,B) B #endif +#if defined (HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE) || defined(_WIN32) +#define IF_PUNCH_HOLE(A,B) A +#else +#define IF_PUNCH_HOLE(A,B) B +#endif + /** The universal page size of the database */ #define UNIV_PAGE_SIZE ((ulint) srv_page_size) diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index cf7825bd542..39afc4e9680 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -1019,7 +1019,7 @@ log_group_file_header_flush( page_id_t(group->space_id, page_no), univ_page_size, (ulint) (dest_offset % univ_page_size.physical()), - OS_FILE_LOG_BLOCK_SIZE, buf, group, NULL); + OS_FILE_LOG_BLOCK_SIZE, buf, group); srv_stats.os_log_pending_writes.dec(); } @@ -1144,7 +1144,7 @@ loop: page_id_t(group->space_id, page_no), univ_page_size, (ulint) (next_offset % UNIV_PAGE_SIZE), write_len, buf, - group, NULL); + group); srv_stats.os_log_pending_writes.dec(); @@ -1664,7 +1664,7 @@ log_group_checkpoint( (log_sys->next_checkpoint_no & 1) ? LOG_CHECKPOINT_2 : LOG_CHECKPOINT_1, OS_FILE_LOG_BLOCK_SIZE, - buf, (byte*) group + 1, NULL); + buf, (byte*) group + 1); ut_ad(((ulint) group & 0x1UL) == 0); } @@ -1686,7 +1686,7 @@ log_group_header_read( fil_io(IORequestLogRead, true, page_id_t(group->space_id, header / univ_page_size.physical()), univ_page_size, header % univ_page_size.physical(), - OS_FILE_LOG_BLOCK_SIZE, log_sys->checkpoint_buf, NULL, NULL); + OS_FILE_LOG_BLOCK_SIZE, log_sys->checkpoint_buf, NULL); } /** Write checkpoint info to the log header and invoke log_mutex_exit(). @@ -2038,7 +2038,7 @@ loop: page_id_t(group->space_id, page_no), univ_page_size, (ulint) (source_offset % univ_page_size.physical()), - len, buf, NULL, NULL); + len, buf, NULL); #ifdef DEBUG_CRYPT fprintf(stderr, "BEFORE DECRYPT: block: %lu checkpoint: %lu %.8lx %.8lx offset %lu\n", diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index e5aab543f5d..ce5b37565af 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -869,7 +869,7 @@ recv_log_format_0_recover(lsn_t lsn) univ_page_size, (ulint) ((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1)) % univ_page_size.physical()), - OS_FILE_LOG_BLOCK_SIZE, buf, NULL, NULL); + OS_FILE_LOG_BLOCK_SIZE, buf, NULL); if (log_block_calc_checksum_format_0(buf) != log_block_get_checksum(buf)) { diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 71a9a856571..f305de38e01 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -44,6 +44,11 @@ Created 10/21/1995 Heikki Tuuri #include "os0file.ic" #endif +#ifdef UNIV_LINUX +#include +#include +#endif + #include "srv0srv.h" #include "srv0start.h" #include "fil0fil.h" @@ -63,17 +68,23 @@ Created 10/21/1995 Heikki Tuuri #include #endif /* LINUX_NATIVE_AIO */ -#ifdef HAVE_LZ4 -#include -#endif - -#include +#ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE +# include +# include +#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE */ #ifdef UNIV_DEBUG /** Set when InnoDB has invoked exit(). */ bool innodb_calling_exit; #endif /* UNIV_DEBUG */ +#if defined(UNIV_LINUX) && defined(HAVE_SYS_IOCTL_H) +# include +# ifndef DFS_IOCTL_ATOMIC_WRITE_SET +# define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) +# endif +#endif + #if defined(UNIV_LINUX) && defined(HAVE_SYS_STATVFS_H) #include #endif @@ -82,12 +93,8 @@ bool innodb_calling_exit; #include #endif -#ifdef HAVE_LZO -#include "lzo/lzo1x.h" -#endif - -#ifdef HAVE_SNAPPY -#include "snappy-c.h" +#ifdef _WIN32 +#include #endif /** Insert buffer segment id */ @@ -216,8 +223,6 @@ struct Slot { /** buffer used in i/o */ byte* buf; - ulint is_log; /*!< 1 if OS_FILE_LOG or 0 */ - ulint page_size; /*!< UNIV_PAGE_SIZE or zip_size */ /** Buffer pointer used for actual IO. We advance this when partial IO is required and not buf */ @@ -286,7 +291,6 @@ struct Slot { /** Length of the block before it was compressed */ uint32 original_len; - ulint* write_size; }; /** The asynchronous i/o array structure */ @@ -328,8 +332,7 @@ public: const char* name, void* buf, os_offset_t offset, - ulint len, - ulint* write_size) + ulint len) MY_ATTRIBUTE((warn_unused_result)); /** @return number of reserved slots */ @@ -759,6 +762,107 @@ os_aio_simulated_handler( void** m2, IORequest* type); +#ifdef _WIN32 +static HANDLE win_get_syncio_event(); +#endif + +#ifdef _WIN32 +/** + Wrapper around Windows DeviceIoControl() function. + + Works synchronously, also in case for handle opened + for async access (i.e with FILE_FLAG_OVERLAPPED). + + Accepts the same parameters as DeviceIoControl(),except + last parameter (OVERLAPPED). +*/ +static +BOOL +os_win32_device_io_control( + HANDLE handle, + DWORD code, + LPVOID inbuf, + DWORD inbuf_size, + LPVOID outbuf, + DWORD outbuf_size, + LPDWORD bytes_returned +) +{ + OVERLAPPED overlapped = { 0 }; + overlapped.hEvent = win_get_syncio_event(); + BOOL result = DeviceIoControl(handle, code, inbuf, inbuf_size, outbuf, + outbuf_size, bytes_returned, &overlapped); + + if (!result && (GetLastError() == ERROR_IO_PENDING)) { + /* Wait for async io to complete */ + result = GetOverlappedResult(handle, &overlapped, bytes_returned, TRUE); + } + + return result; +} + +#endif + +/***********************************************************************//** +Try to get number of bytes per sector from file system. +@return file block size */ +UNIV_INTERN +ulint +os_file_get_block_size( +/*===================*/ + os_file_t file, /*!< in: handle to a file */ + const char* name) /*!< in: file name */ +{ + ulint fblock_size = 512; + +#if defined(UNIV_LINUX) + struct stat local_stat; + int err; + + err = fstat((int)file, &local_stat); + + if (err != 0) { + os_file_handle_error_no_exit(name, "fstat()", FALSE); + } else { + fblock_size = local_stat.st_blksize; + } +#endif /* UNIV_LINUX */ +#ifdef _WIN32 + DWORD outsize; + STORAGE_PROPERTY_QUERY storageQuery; + memset(&storageQuery, 0, sizeof(storageQuery)); + storageQuery.PropertyId = StorageAccessAlignmentProperty; + storageQuery.QueryType = PropertyStandardQuery; + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment; + + BOOL result = os_win32_device_io_control(file, + IOCTL_STORAGE_QUERY_PROPERTY, + &storageQuery, + sizeof(STORAGE_PROPERTY_QUERY), + &diskAlignment, + sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), + &outsize); + + if (!result) { + os_file_handle_error_no_exit(name, "DeviceIoControl()", FALSE); + fblock_size = 0; + } + + fblock_size = diskAlignment.BytesPerPhysicalSector; +#endif /* _WIN32 */ + + /* Currently we support file block size up to 4Kb */ + if (fblock_size > 4096 || fblock_size < 512) { + if (fblock_size < 512) { + fblock_size = 512; + } else { + fblock_size = 4096; + } + } + + return fblock_size; +} + #ifdef WIN_ASYNC_IO /** This function is only used in Windows asynchronous i/o. Waits for an aio operation to complete. This function is used to wait the @@ -1443,6 +1547,48 @@ SyncFileIO::execute(const IORequest& request) return(n_bytes); } +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return DB_SUCCESS or error code */ +static +dberr_t +os_file_punch_hole_posix( + os_file_t fh, + os_offset_t off, + os_offset_t len) +{ + +#ifdef HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE + const int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE; + + int ret = fallocate(fh, mode, off, len); + + if (ret == 0) { + return(DB_SUCCESS); + } + + if (errno == ENOTSUP) { + return(DB_IO_NO_PUNCH_HOLE); + } + + ib::warn() + << "fallocate(" + <<", FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, " + << off << ", " << len << ") returned errno: " + << errno; + + return(DB_IO_ERROR); + +#elif defined(UNIV_SOLARIS) + + // Use F_FREESP + +#endif /* HAVE_FALLOC_PUNCH_HOLE_AND_KEEP_SIZE */ + + return(DB_IO_NO_PUNCH_HOLE); +} #if defined(LINUX_NATIVE_AIO) @@ -1734,7 +1880,18 @@ LinuxAIOHandler::collect() /* We have not overstepped to next segment. */ ut_a(slot->pos < end_pos); - slot->err = DB_SUCCESS; + /* Deallocate unused blocks from file system. + This is newer done to page 0 or to log files.*/ + if (slot->offset > 0 + && !slot->skip_punch_hole + && !slot->type.is_log() + && slot->type.is_write() + && slot->type.punch_hole()) { + + slot->err = AIOHandler::io_complete(slot); + } else { + slot->err = DB_SUCCESS; + } /* Mark this request as completed. The error handling will be done in the calling function. */ @@ -3353,6 +3510,76 @@ struct WinIoInit /* Ensures proper initialization and shutdown */ static WinIoInit win_io_init; +/** Check if the file system supports sparse files. +@param[in] name File name +@return true if the file system supports sparse files */ +static +bool +os_is_sparse_file_supported_win32(const char* filename) +{ + char volname[MAX_PATH]; + BOOL result = GetVolumePathName(filename, volname, MAX_PATH); + + if (!result) { + + ib::error() + << "os_is_sparse_file_supported: " + << "Failed to get the volume path name for: " + << filename + << "- OS error number " << GetLastError(); + + return(false); + } + + DWORD flags; + + result = GetVolumeInformation( + volname, NULL, MAX_PATH, NULL, NULL, + &flags, NULL, MAX_PATH); + + + if (!result) { + ib::error() + << "os_is_sparse_file_supported: " + << "Failed to get the volume info for: " + << volname + << "- OS error number " << GetLastError(); + + return(false); + } + + return(flags & FILE_SUPPORTS_SPARSE_FILES) ? true : false; +} + +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] page_size Tablespace page size +@param[in] block_size File system block size +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return 0 on success or errno */ +static +dberr_t +os_file_punch_hole_win32( + os_file_t fh, + os_offset_t off, + os_offset_t len) +{ + FILE_ZERO_DATA_INFORMATION punch; + + punch.FileOffset.QuadPart = off; + punch.BeyondFinalZero.QuadPart = off + len; + + /* If lpOverlapped is NULL, lpBytesReturned cannot be NULL, + therefore we pass a dummy parameter. */ + DWORD temp; + BOOL success = os_win32_device_io_control( + fh, FSCTL_SET_ZERO_DATA, &punch, sizeof(punch), + NULL, 0, &temp); + + return(success ? DB_SUCCESS: DB_IO_NO_PUNCH_HOLE); +} + /** Check the existence and type of the given file. @param[in] path path name of file @param[out] exists true if the file exists @@ -3661,9 +3888,9 @@ os_file_create_simple_func( /* This is a best effort use case, if it fails then we will find out when we try and punch the hole. */ - DeviceIoControl( + os_win32_device_io_control( file, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, - &temp, NULL); + &temp); } } while (retry); @@ -4020,9 +4247,9 @@ os_file_create_func( /* This is a best effort use case, if it fails then we will find out when we try and punch the hole. */ - DeviceIoControl( + os_win32_device_io_control( file, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, - &temp, NULL); + &temp); } } while (retry); @@ -4459,28 +4686,6 @@ os_file_get_status_win32( } stat_info->block_size = bytesPerSector * sectorsPerCluster; - - /* On Windows the block size is not used as the allocation - unit for sparse files. The underlying infra-structure for - sparse files is based on NTFS compression. The punch hole - is done on a "compression unit". This compression unit - is based on the cluster size. You cannot punch a hole if - the cluster size >= 8K. For smaller sizes the table is - as follows: - - Cluster Size Compression Unit - 512 Bytes 8 KB - 1 KB 16 KB - 2 KB 32 KB - 4 KB 64 KB - - Default NTFS cluster size is 4K, compression unit size of 64K. - Therefore unless the user has created the file system with - a smaller cluster size and used larger page sizes there is - little benefit from compression out of the box. */ - - stat_info->block_size = (stat_info->block_size <= 4096) - ? stat_info->block_size * 16 : ULINT_UNDEFINED; } else { stat_info->type = OS_FILE_TYPE_UNKNOWN; } @@ -4615,7 +4820,18 @@ os_file_io( } else if ((ulint) n_bytes + bytes_returned == n) { bytes_returned += n_bytes; - *err = DB_SUCCESS; + + if (offset > 0 + && !type.is_log() + && type.is_write() + && type.punch_hole()) { + *err = type.punch_hole(file, + static_cast(offset), + n); + + } else { + *err = DB_SUCCESS; + } return(original_n); } @@ -4668,7 +4884,7 @@ ssize_t os_file_pwrite( IORequest& type, os_file_t file, - const void* buf, + const byte* buf, ulint n, os_offset_t offset, dberr_t* err) @@ -4680,7 +4896,7 @@ os_file_pwrite( (void) my_atomic_addlint(&os_n_pending_writes, 1); MONITOR_ATOMIC_INC(MONITOR_OS_PENDING_WRITES); - ssize_t n_bytes = os_file_io(type, file, const_cast(buf), + ssize_t n_bytes = os_file_io(type, file, const_cast(buf), n, offset, err); (void) my_atomic_addlint(&os_n_pending_writes, -1); @@ -4696,8 +4912,9 @@ os_file_pwrite( @param[in] offset file offset from the start where to read @param[in] n number of bytes to read, starting from offset @return DB_SUCCESS if request was successful, false if fail */ +static MY_ATTRIBUTE((warn_unused_result)) dberr_t -os_file_write_func( +os_file_write_page( IORequest& type, const char* name, os_file_t file, @@ -4711,7 +4928,7 @@ os_file_write_func( ut_ad(type.validate()); ut_ad(n > 0); - ssize_t n_bytes = os_file_pwrite(type, file, buf, n, offset, &err); + ssize_t n_bytes = os_file_pwrite(type, file, (byte*)buf, n, offset, &err); if ((ulint) n_bytes != n && !os_has_said_disk_full) { @@ -5195,6 +5412,31 @@ os_file_read_no_error_handling_func( return(os_file_read_page(type, file, buf, offset, n, o, false)); } +/** NOTE! Use the corresponding macro os_file_write(), not directly +Requests a synchronous write operation. +@param[in] type IO flags +@param[in] file handle to an open file +@param[out] buf buffer from which to write +@param[in] offset file offset from the start where to read +@param[in] n number of bytes to read, starting from offset +@return DB_SUCCESS if request was successful, false if fail */ +dberr_t +os_file_write_func( + IORequest& type, + const char* name, + os_file_t file, + const void* buf, + os_offset_t offset, + ulint n) +{ + ut_ad(type.validate()); + ut_ad(type.is_write()); + + const byte* ptr = reinterpret_cast(buf); + + return(os_file_write_page(type, name, file, ptr, offset, n)); +} + /** Check the existence and type of the given file. @param[in] path path name of file @param[out] exists true if the file exists @@ -5213,6 +5455,110 @@ os_file_status( #endif /* _WIN32 */ } +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return DB_SUCCESS or error code */ +dberr_t +os_file_punch_hole( + os_file_t fh, + os_offset_t off, + os_offset_t len) +{ + dberr_t err; + +#ifdef _WIN32 + err = os_file_punch_hole_win32(fh, off, len); +#else + err = os_file_punch_hole_posix(fh, off, len); +#endif /* _WIN32 */ + + return (err); +} + +/** Free storage space associated with a section of the file. +@param[in] fh Open file handle +@param[in] off Starting offset (SEEK_SET) +@param[in] len Size of the hole +@return DB_SUCCESS or error code */ +dberr_t +IORequest::punch_hole( + os_file_t fh, + os_offset_t off, + os_offset_t len) +{ + /* In this debugging mode, we act as if punch hole is supported, + and then skip any calls to actually punch a hole here. + In this way, Transparent Page Compression is still being tested. */ + DBUG_EXECUTE_IF("ignore_punch_hole", + return(DB_SUCCESS); + ); + + ulint trim_len = get_trim_length(len); + + if (trim_len == 0) { + return(DB_SUCCESS); + } + + off += len; + + /* Check does file system support punching holes for this + tablespace. */ + if (!should_punch_hole() || !srv_use_trim) { + return DB_IO_NO_PUNCH_HOLE; + } + + dberr_t err = os_file_punch_hole(fh, off, len); + + if (err == DB_SUCCESS) { + srv_stats.page_compressed_trim_op.inc(); + } else { + /* If punch hole is not supported, + set space so that it is not used. */ + if (err == DB_IO_NO_PUNCH_HOLE) { + space_no_punch_hole(); + err = DB_SUCCESS; + } + } + + return (err); +} + +/** Check if the file system supports sparse files. + +Warning: On POSIX systems we try and punch a hole from offset 0 to +the system configured page size. This should only be called on an empty +file. + +Note: On Windows we use the name and on Unices we use the file handle. + +@param[in] name File name +@param[in] fh File handle for the file - if opened +@return true if the file system supports sparse files */ +bool +os_is_sparse_file_supported(const char* path, os_file_t fh) +{ + /* In this debugging mode, we act as if punch hole is supported, + then we skip any calls to actually punch a hole. In this way, + Transparent Page Compression is still being tested. */ + DBUG_EXECUTE_IF("ignore_punch_hole", + return(true); + ); + +#ifdef _WIN32 + return(os_is_sparse_file_supported_win32(path)); +#else + dberr_t err; + + /* We don't know the FS block size, use the sector size. The FS + will do the magic. */ + err = os_file_punch_hole_posix(fh, 0, UNIV_PAGE_SIZE); + + return(err == DB_SUCCESS); +#endif /* _WIN32 */ +} + /** This function returns information about the specified file @param[in] path pathname of the file @param[out] stat_info information of a file in a directory @@ -5776,12 +6122,7 @@ AIO::reserve_slot( const char* name, void* buf, os_offset_t offset, - ulint len, - ulint* write_size)/*!< in/out: Actual write size initialized - after fist successfull trim - operation for this page and if - initialized we do not trim again if - actual page size does not decrease. */ + ulint len) { #ifdef WIN_ASYNC_IO ut_a((len & 0xFFFFFFFFUL) == len); @@ -5871,8 +6212,6 @@ AIO::reserve_slot( slot->ptr = slot->buf; slot->offset = offset; slot->err = DB_SUCCESS; - slot->write_size = write_size; - slot->is_log = type.is_log(); slot->original_len = static_cast(len); slot->io_already_done = false; slot->buf = static_cast(buf); @@ -6225,6 +6564,7 @@ Requests an asynchronous i/o operation. @param[in,out] m2 message for the AIO handler (can be used to identify a completed AIO operation); ignored if mode is OS_AIO_SYNC + @return DB_SUCCESS or error code */ dberr_t os_aio_func( @@ -6237,12 +6577,7 @@ os_aio_func( ulint n, bool read_only, fil_node_t* m1, - void* m2, - ulint* write_size)/*!< in/out: Actual write size initialized - after fist successfull trim - operation for this page and if - initialized we do not trim again if - actual page size does not decrease. */ + void* m2) { #ifdef WIN_ASYNC_IO BOOL ret = TRUE; @@ -6278,7 +6613,7 @@ try_again: Slot* slot; - slot = array->reserve_slot(type, m1, m2, file, name, buf, offset, n, write_size); + slot = array->reserve_slot(type, m1, m2, file, name, buf, offset, n); if (type.is_read()) { diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index 00b7bd14c98..b2722c2a9bf 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -989,41 +989,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_SAVED}, - {"compress_trim_sect512", "compression", - "Number of sect-512 TRIMed by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT512}, - - {"compress_trim_sect1024", "compression", - "Number of sect-1024 TRIMed by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT1024}, - - {"compress_trim_sect2048", "compression", - "Number of sect-2048 TRIMed by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT2048}, - - {"compress_trim_sect4096", "compression", - "Number of sect-4K TRIMed by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT4096}, - - {"compress_trim_sect8192", "compression", - "Number of sect-8K TRIMed by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT8192}, - - {"compress_trim_sect16384", "compression", - "Number of sect-16K TRIMed by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT16384}, - - {"compress_trim_sect32768", "compression", - "Number of sect-32K TRIMed by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT32768}, - {"compress_pages_page_compressed", "compression", "Number of pages compressed by page compression", MONITOR_NONE, @@ -1034,11 +999,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESSED_TRIM_OP}, - {"compress_page_compressed_trim_op_saved", "compression", - "Number of TRIM operation saved by page compression", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_OVLD_PAGE_COMPRESSED_TRIM_OP_SAVED}, - {"compress_pages_page_decompressed", "compression", "Number of pages decompressed by page compression", MONITOR_NONE, @@ -2073,36 +2033,12 @@ srv_mon_process_existing_counter( case MONITOR_OVLD_PAGE_COMPRESS_SAVED: value = srv_stats.page_compression_saved; break; - case MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT512: - value = srv_stats.page_compression_trim_sect512; - break; - case MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT1024: - value = srv_stats.page_compression_trim_sect1024; - break; - case MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT2048: - value = srv_stats.page_compression_trim_sect2048; - break; - case MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT4096: - value = srv_stats.page_compression_trim_sect4096; - break; - case MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT8192: - value = srv_stats.page_compression_trim_sect8192; - break; - case MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT16384: - value = srv_stats.page_compression_trim_sect16384; - break; - case MONITOR_OVLD_PAGE_COMPRESS_TRIM_SECT32768: - value = srv_stats.page_compression_trim_sect32768; - break; case MONITOR_OVLD_PAGES_PAGE_COMPRESSED: value = srv_stats.pages_page_compressed; break; case MONITOR_OVLD_PAGE_COMPRESSED_TRIM_OP: value = srv_stats.page_compressed_trim_op; break; - case MONITOR_OVLD_PAGE_COMPRESSED_TRIM_OP_SAVED: - value = srv_stats.page_compressed_trim_op_saved; - break; case MONITOR_OVLD_PAGES_PAGE_DECOMPRESSED: value = srv_stats.pages_page_decompressed; break; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 5d478e4529f..bd4dd1c80af 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -184,7 +184,7 @@ my_bool srv_use_native_aio = TRUE; my_bool srv_numa_interleave = FALSE; /* If this flag is TRUE, then we will use fallocate(PUCH_HOLE) to the pages */ -UNIV_INTERN my_bool srv_use_trim = FALSE; +UNIV_INTERN my_bool srv_use_trim; /* If this flag is TRUE, then we disable doublewrite buffer */ UNIV_INTERN my_bool srv_use_atomic_writes = FALSE; /* If this flag IS TRUE, then we use this algorithm for page compressing the pages */ @@ -1617,13 +1617,10 @@ srv_export_innodb_status(void) export_vars.innodb_available_undo_logs = srv_available_undo_logs; export_vars.innodb_page_compression_saved = srv_stats.page_compression_saved; - export_vars.innodb_page_compression_trim_sect512 = srv_stats.page_compression_trim_sect512; - export_vars.innodb_page_compression_trim_sect4096 = srv_stats.page_compression_trim_sect4096; export_vars.innodb_index_pages_written = srv_stats.index_pages_written; export_vars.innodb_non_index_pages_written = srv_stats.non_index_pages_written; export_vars.innodb_pages_page_compressed = srv_stats.pages_page_compressed; export_vars.innodb_page_compressed_trim_op = srv_stats.page_compressed_trim_op; - export_vars.innodb_page_compressed_trim_op_saved = srv_stats.page_compressed_trim_op_saved; export_vars.innodb_pages_page_decompressed = srv_stats.pages_page_decompressed; export_vars.innodb_pages_page_compression_error = srv_stats.pages_page_compression_error; export_vars.innodb_pages_decrypted = srv_stats.pages_decrypted; diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index d43735bba2e..f597147d50f 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -761,6 +761,8 @@ ut_strerr( case DB_NO_FK_ON_S_BASE_COL: return("Cannot add foreign key on the base column " "of stored column"); + case DB_IO_NO_PUNCH_HOLE: + return ("File system does not support punch hole (trim) operation."); /* do not add default: in order to produce a warning if new code is added to the enum but not added here */ From 51b248cfdd7b0c6c6477be8eda7a0cdd335f11bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 24 Jan 2017 15:04:50 +0200 Subject: [PATCH 106/167] MDEV-11879: Duplicate option innochecksum -l (--log, --leaf) Move --leaf under -e to avoid duplicate option and retain -l for --log (to maintain compatibility with MySQL 5.7). --- extra/innochecksum.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index 9d02a545cc5..707451da7fa 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -1381,7 +1381,7 @@ static struct my_option innochecksum_options[] = { {"log", 'l', "log output.", &log_filename, &log_filename, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"leaf", 'l', "Examine leaf index pages", + {"leaf", 'e', "Examine leaf index pages", &do_leaf, &do_leaf, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"merge", 'm', "leaf page count if merge given number of consecutive pages", &n_merge, &n_merge, 0, GET_ULONG, REQUIRED_ARG, 0, 0, (longlong)10L, 0, 1, 0}, @@ -1411,7 +1411,7 @@ static void usage(void) printf("Usage: %s [-c] [-s ] [-e ] " "[-p ] [-v] [-a ] [-n] " "[-C ] [-w ] [-S] [-D ] " - "[-l ] \n", my_progname); + "[-l ] [-e] \n", my_progname); printf("See " REFMAN "innochecksum.html for usage hints.\n"); my_print_help(innochecksum_options); my_print_variables(innochecksum_options); From 836804499704396aacff58d415b63741b22ff2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 24 Jan 2017 15:10:45 +0200 Subject: [PATCH 107/167] Fix compiler error on native AIO. --- storage/innobase/os/os0file.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index f305de38e01..846e5567e73 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -1883,7 +1883,6 @@ LinuxAIOHandler::collect() /* Deallocate unused blocks from file system. This is newer done to page 0 or to log files.*/ if (slot->offset > 0 - && !slot->skip_punch_hole && !slot->type.is_log() && slot->type.is_write() && slot->type.punch_hole()) { From ae91690d893c13e86fd9f84e0c37fd9640bca257 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 24 Jan 2017 17:22:06 +0400 Subject: [PATCH 108/167] MDEV-11780 Crash with PREPARE + SP out parameter + literal Before "MDEV-10709 Expressions as parameters to Dynamic SQL" only user variables were syntactically allowed as EXECUTE parameters. User variables were OK as both IN and OUT parameters. When Item_param was bound to an actual parameter (a user variable), it automatically meant that the bound Item was settable. The DBUG_ASSERT() in Protocol_text::send_out_parameters() guarded that the actual parameter is really settable. After MDEV-10709, any kind of expressions are allowed as EXECUTE IN parameters. But the patch for MDEV-10709 forgot to check that only descendants of Settable_routine_parameter should be allowed as OUT parameters. So an attempt to pass a non-settable parameter as an OUT parameter made server crash on the above mentioned DBUG_ASSERT. This patch changes Item_param::get_settable_routine_parameter(), which previously always returned "this". Now, when Item_param is bound to some Item, it caches if the bound Item is settable. Item_param::get_settable_routine_parameter() now returns "this" only if the bound actual parameter is settable, and returns NULL otherwise. --- mysql-test/r/ps.result | 23 +++++++++++++++++++++++ mysql-test/t/ps.test | 29 +++++++++++++++++++++++++++++ sql/item.cc | 13 ++++++++++++- sql/item.h | 3 ++- 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 5b7d4b6fa7f..6c0750e513a 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -4747,3 +4747,26 @@ INSERT INTO t1 VALUES (1),(2),(3); EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING DEFAULT,DEFAULT; ERROR HY000: Default/ignore value is not supported for such parameter usage DROP TABLE t1; +# +# MDEV-11780 Crash with PREPARE + SP out parameter + literal +# +CREATE OR REPLACE PROCEDURE p1(OUT a INT) +BEGIN +SET a=10; +END; +$$ +PREPARE stmt FROM 'CALL p1(?)'; +EXECUTE stmt USING 10; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +EXECUTE stmt USING DEFAULT; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +EXECUTE stmt USING IGNORE; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +DEALLOCATE PREPARE stmt; +EXECUTE IMMEDIATE 'CALL p1(?)' USING 10; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE; +ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger +DROP PROCEDURE p1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 00e0c4086bb..74ab7659ac6 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -4287,3 +4287,32 @@ INSERT INTO t1 VALUES (1),(2),(3); --error ER_INVALID_DEFAULT_PARAM EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING DEFAULT,DEFAULT; DROP TABLE t1; + +--echo # +--echo # MDEV-11780 Crash with PREPARE + SP out parameter + literal +--echo # + +DELIMITER $$; +CREATE OR REPLACE PROCEDURE p1(OUT a INT) +BEGIN + SET a=10; +END; +$$ +DELIMITER ;$$ + +PREPARE stmt FROM 'CALL p1(?)'; +--error ER_SP_NOT_VAR_ARG +EXECUTE stmt USING 10; +--error ER_SP_NOT_VAR_ARG +EXECUTE stmt USING DEFAULT; +--error ER_SP_NOT_VAR_ARG +EXECUTE stmt USING IGNORE; +DEALLOCATE PREPARE stmt; + +--error ER_SP_NOT_VAR_ARG +EXECUTE IMMEDIATE 'CALL p1(?)' USING 10; +--error ER_SP_NOT_VAR_ARG +EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT; +--error ER_SP_NOT_VAR_ARG +EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE; +DROP PROCEDURE p1; diff --git a/sql/item.cc b/sql/item.cc index bab49115482..369b2df2675 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3313,7 +3313,15 @@ Item_param::Item_param(THD *thd, uint pos_in_query_arg): item_type(PARAM_ITEM), indicators(0), indicator(STMT_INDICATOR_NONE), set_param_func(default_set_param_func), - m_out_param_info(NULL) + m_out_param_info(NULL), + /* + Set m_is_settable_routine_parameter to "true" by default. + This is needed for client-server protocol, + whose parameters are always settable. + For dynamic SQL, settability depends on the type of Item passed + as an actual parameter. See Item_param::set_from_item(). + */ + m_is_settable_routine_parameter(true) { name= (char*) "?"; /* @@ -3557,6 +3565,7 @@ bool Item_param::CONVERSION_INFO::convert(THD *thd, String *str) bool Item_param::set_from_item(THD *thd, Item *item) { DBUG_ENTER("Item_param::set_from_item"); + m_is_settable_routine_parameter= item->get_settable_routine_parameter(); if (limit_clause_param) { longlong val= item->val_int(); @@ -4132,6 +4141,7 @@ Item_param::set_param_type_and_swap_value(Item_param *src) void Item_param::set_default() { + m_is_settable_routine_parameter= false; state= DEFAULT_VALUE; fixed= true; /* @@ -4147,6 +4157,7 @@ void Item_param::set_default() void Item_param::set_ignore() { + m_is_settable_routine_parameter= false; state= IGNORE_VALUE; fixed= true; null_value= true; diff --git a/sql/item.h b/sql/item.h index f9efd104b04..bb2f05b4c6d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2982,7 +2982,7 @@ public: Rewritable_query_parameter *get_rewritable_query_parameter() { return this; } Settable_routine_parameter *get_settable_routine_parameter() - { return this; } + { return m_is_settable_routine_parameter ? this : NULL; } bool append_for_log(THD *thd, String *str); bool check_vcol_func_processor(void *int_arg) {return FALSE;} @@ -3002,6 +3002,7 @@ public: private: Send_field *m_out_param_info; + bool m_is_settable_routine_parameter; }; From 106fbadaba03daf51a62c40c1edbe9afb386d149 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 24 Jan 2017 17:29:51 +0400 Subject: [PATCH 109/167] MDEV-11848 Automatic statement repreparation changes query semantics --- mysql-test/r/set_statement.result | 8 ++++++-- mysql-test/r/sql_mode.result | 17 +++++++++++++++++ mysql-test/t/set_statement.test | 6 ++---- mysql-test/t/sql_mode.test | 14 ++++++++++++++ sql/sql_prepare.cc | 9 ++++++++- 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/set_statement.result b/mysql-test/r/set_statement.result index 4cb143f6ba5..91b8aa6fe59 100644 --- a/mysql-test/r/set_statement.result +++ b/mysql-test/r/set_statement.result @@ -652,7 +652,9 @@ v1 v2 3 4 ALTER TABLE t1 ADD COLUMN v3 int; execute stmt; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.* FROM t1' at line 1 +v1 v2 v3 +1 2 NULL +3 4 NULL ALTER TABLE t1 drop COLUMN v3; deallocate prepare stmt; '' @@ -670,7 +672,9 @@ v1 v2 3 4 ALTER TABLE t1 ADD COLUMN v3 int; execute stmt; -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '.* FROM t1' at line 1 +v1 v2 v3 +1 2 NULL +3 4 NULL ALTER TABLE t1 drop COLUMN v3; deallocate prepare stmt; SELECT @@sql_mode; diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index 782ae00bb33..04935a4a268 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -742,3 +742,20 @@ DROP FUNCTION test_function; SET @@sql_mode= @org_mode; #End of Test for Bug#12601974 +# +# MDEV-11848 Automatic statement repreparation changes query semantics +# +SET sql_mode=DEFAULT; +CREATE OR REPLACE TABLE t1 (a TEXT); +PREPARE stmt FROM 'INSERT INTO t1 (a) VALUES (2||3)'; +EXECUTE stmt; +SET sql_mode=ORACLE; +EXECUTE stmt; +ALTER TABLE t1 ADD b INT; +EXECUTE stmt; +SELECT * FROM t1; +a b +1 NULL +1 NULL +1 NULL +DROP TABLE t1; diff --git a/mysql-test/t/set_statement.test b/mysql-test/t/set_statement.test index a91c53c8dee..32f56e498df 100644 --- a/mysql-test/t/set_statement.test +++ b/mysql-test/t/set_statement.test @@ -618,8 +618,7 @@ SELECT @@sql_mode; SET STATEMENT sql_mode='ansi' FOR PREPARE stmt FROM 'SELECT "t1".* FROM t1'; execute stmt; ALTER TABLE t1 ADD COLUMN v3 int; -# repreparation with other mode cause an error ---error ER_PARSE_ERROR +# repreparation with other mode does not cause an error execute stmt; ALTER TABLE t1 drop COLUMN v3; deallocate prepare stmt; @@ -632,8 +631,7 @@ PREPARE stmt FROM 'SELECT "t1".* FROM t1'; SET sql_mode=default; execute stmt; ALTER TABLE t1 ADD COLUMN v3 int; -# repreparation with other mode cause an error ---error ER_PARSE_ERROR +# repreparation with other mode does not cause an error execute stmt; ALTER TABLE t1 drop COLUMN v3; deallocate prepare stmt; diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test index 869bf45dbf3..263437a0bf1 100644 --- a/mysql-test/t/sql_mode.test +++ b/mysql-test/t/sql_mode.test @@ -513,3 +513,17 @@ SET @@sql_mode= @org_mode; --echo --echo #End of Test for Bug#12601974 + +--echo # +--echo # MDEV-11848 Automatic statement repreparation changes query semantics +--echo # +SET sql_mode=DEFAULT; +CREATE OR REPLACE TABLE t1 (a TEXT); +PREPARE stmt FROM 'INSERT INTO t1 (a) VALUES (2||3)'; +EXECUTE stmt; +SET sql_mode=ORACLE; +EXECUTE stmt; +ALTER TABLE t1 ADD b INT; +EXECUTE stmt; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 735bdb73d58..f5e0244f75a 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -227,6 +227,7 @@ private: SELECT_LEX and other classes). */ MEM_ROOT main_mem_root; + sql_mode_t m_sql_mode; private: bool set_db(const char *db, uint db_length); bool set_parameters(String *expanded_query, @@ -3603,7 +3604,8 @@ Prepared_statement::Prepared_statement(THD *thd_arg) param_count(0), last_errno(0), flags((uint) IS_IN_USE), - start_param(0) + start_param(0), + m_sql_mode(thd->variables.sql_mode) { init_sql_alloc(&main_mem_root, thd_arg->variables.query_alloc_block_size, thd_arg->variables.query_prealloc_size, MYF(MY_THREAD_SPECIFIC)); @@ -3777,6 +3779,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) Statement stmt_backup; Query_arena *old_stmt_arena; DBUG_ENTER("Prepared_statement::prepare"); + DBUG_ASSERT(m_sql_mode == thd->variables.sql_mode); /* If this is an SQLCOM_PREPARE, we also increase Com_prepare_sql. However, it seems handy if com_stmt_prepare is increased always, @@ -4365,6 +4368,7 @@ Prepared_statement::reprepare() bool error; Prepared_statement copy(thd); + copy.m_sql_mode= m_sql_mode; copy.set_sql_prepare(); /* To suppress sending metadata to the client. */ @@ -4374,9 +4378,12 @@ Prepared_statement::reprepare() &cur_db_changed)) return TRUE; + sql_mode_t save_sql_mode= thd->variables.sql_mode; + thd->variables.sql_mode= m_sql_mode; error= ((name.str && copy.set_name(&name)) || copy.prepare(query(), query_length()) || validate_metadata(©)); + thd->variables.sql_mode= save_sql_mode; if (cur_db_changed) mysql_change_db(thd, &saved_cur_db_name, TRUE); From e5398aca766536bc6151270a6dcd57260dada713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 24 Jan 2017 15:21:02 +0200 Subject: [PATCH 110/167] Native AIO should also punch_hole if available. --- storage/innobase/os/os0file.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 846e5567e73..9e41e698cb4 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -1887,7 +1887,7 @@ LinuxAIOHandler::collect() && slot->type.is_write() && slot->type.punch_hole()) { - slot->err = AIOHandler::io_complete(slot); + slot->err = slot->type.punch_hole(slot->file, slot->offset, slot->len); } else { slot->err = DB_SUCCESS; } From 50831b0f197fd1edb98aa56085e391e5033e2a54 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 24 Jan 2017 17:34:44 +0400 Subject: [PATCH 111/167] MDEV-11557 port MySQL-5.7 JSON tests to MariaDB. json_no_table.test ported. --- include/json_lib.h | 25 +- mysql-test/mysql-test-run.pl | 1 + mysql-test/r/func_json.result | 6 + mysql-test/suite/json/r/json_no_table.result | 3634 ++++++++++++++++++ mysql-test/suite/json/t/json_no_table.test | 2288 +++++++++++ mysql-test/t/func_json.test | 2 + sql/item_jsonfunc.cc | 376 +- sql/item_jsonfunc.h | 1 + sql/share/errmsg-utf8.txt | 2 + strings/json_lib.c | 166 +- 10 files changed, 6293 insertions(+), 208 deletions(-) create mode 100644 mysql-test/suite/json/r/json_no_table.result create mode 100644 mysql-test/suite/json/t/json_no_table.test diff --git a/include/json_lib.h b/include/json_lib.h index ce7f27317bc..ddba571ac59 100644 --- a/include/json_lib.h +++ b/include/json_lib.h @@ -219,7 +219,7 @@ typedef struct st_json_engine_t /* string constants. */ int stack[JSON_DEPTH_LIMIT]; /* Keeps the stack of nested JSON structures. */ - int *stack_p; /* The 'stack' pointer. */ + int stack_p; /* The 'stack' pointer. */ } json_engine_t; @@ -308,7 +308,7 @@ typedef const int *json_level_t; */ #define json_get_level(j) (j->stack_p) -int json_skip_to_level(json_engine_t *j, json_level_t level); +int json_skip_to_level(json_engine_t *j, int level); /* json_skip_level() works as above with just current structre. @@ -391,6 +391,27 @@ int json_append_ascii(CHARSET_INFO *json_cs, uchar *json, uchar *json_end, const uchar *ascii, const uchar *ascii_end); + +/* + Scan the JSON and return paths met one-by-one. + json_get_path_start(&p) + while (json_get_path_next(&p)) + { + handle_the_next_path(); + } +*/ + +int json_get_path_start(json_engine_t *je, CHARSET_INFO *i_cs, + const uchar *str, const uchar *end, + json_path_t *p); + + +int json_get_path_next(json_engine_t *je, json_path_t *p); + + +int json_path_compare(const json_path_t *a, const json_path_t *b); + + #ifdef __cplusplus } #endif diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index b3fe2d2f20a..1b6802e6b49 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -182,6 +182,7 @@ my @DEFAULT_SUITES= qw( innodb_fts- innodb_gis- innodb_zip- + json- maria- multi_source- optimizer_unfixed_bugs- diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 6c1987cc3e7..47993ae9a32 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -212,6 +212,12 @@ json_extract('1', '$') select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]'); json_extract('[10, 20, [30, 40], 1, 10]', '$[1]') 20 +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]'); +json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]') +[20] +select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a'); +json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a') +[[3, 4]] select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word'); json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word') {"a":1, "b":{"c":1, "k1":"word"}, "d":[1, 2]} diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result new file mode 100644 index 00000000000..514b6a775d4 --- /dev/null +++ b/mysql-test/suite/json/r/json_no_table.result @@ -0,0 +1,3634 @@ +SELECT CAST(0.0e0 AS JSON) = -0.0e0; +CAST(0.0e0 AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(CAST(0 AS DECIMAL) AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +SELECT CAST(0.0e0 AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(0.0e0 AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = -0.0e0; +CAST(CAST(0 AS DECIMAL) AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = -0.0e0; +CAST(CAST(0 AS SIGNED) AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(CAST(0 AS SIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = -0.0e0; +CAST(CAST(0 AS UNSIGNED) AS JSON) = -0.0e0 +1 +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); +CAST(CAST(0 AS UNSIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL) +1 +select cast('"abc"' as json); +cast('"abc"' as json) +"abc" +error ER_INVALID_JSON_TEXT_IN_PARAM +select cast('abc' as json); +cast('abc' as json) +abc + +# String literal - valid JSON +select JSON_VALID('123'); +JSON_VALID('123') +1 +select JSON_VALID('-123'); +JSON_VALID('-123') +1 +select JSON_VALID('5000000000'); +JSON_VALID('5000000000') +1 +select JSON_VALID('-5000000000'); +JSON_VALID('-5000000000') +1 +select JSON_VALID('1.23'); +JSON_VALID('1.23') +1 +select JSON_VALID('"123"'); +JSON_VALID('"123"') +1 +select JSON_VALID('true'); +JSON_VALID('true') +1 +select JSON_VALID('false'); +JSON_VALID('false') +1 +select JSON_VALID('null'); +JSON_VALID('null') +1 +select JSON_VALID('{"address": "Trondheim"}'); +JSON_VALID('{"address": "Trondheim"}') +1 + +# String literal - not valid JSON +select JSON_VALID('12 3'); +JSON_VALID('12 3') +0 + +# String literal not in UTF-8 +set names 'ascii'; +select JSON_VALID('123'); +JSON_VALID('123') +1 +set names 'utf8'; + +# Json expression +select JSON_VALID(cast('[123]' as JSON )); +JSON_VALID(cast('[123]' as JSON )) +1 + +# Json expression NULL +select JSON_VALID(cast(NULL as JSON )); +JSON_VALID(cast(NULL as JSON )) +NULL + +# Bare NULL +select JSON_VALID( NULL ); +JSON_VALID( NULL ) +NULL + +# Function result - string +select JSON_VALID( UPPER('"abc"') ); +JSON_VALID( UPPER('"abc"') ) +1 +set names 'latin1'; + +# Function result - string +select JSON_VALID( UPPER('"abc"') ); +JSON_VALID( UPPER('"abc"') ) +1 +set names 'utf8'; + +# Function result - date, not valid as JSON without CAST +select JSON_VALID( CAST('2015-01-15' AS DATE) ); +JSON_VALID( CAST('2015-01-15' AS DATE) ) +0 + +# The date string doesn't parse as JSON text, so wrong: +select JSON_VALID( CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8') ); +JSON_VALID( CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8') ) +0 +# OK, though: +select JSON_VALID( CAST(CURDATE() as JSON) ); +JSON_VALID( CAST(CURDATE() as JSON) ) +0 + +# Function result - NULL +select JSON_VALID( UPPER(NULL) ); +JSON_VALID( UPPER(NULL) ) +NULL +select JSON_VALID( UPPER(CAST(NULL as CHAR)) ); +JSON_VALID( UPPER(CAST(NULL as CHAR)) ) +NULL +SELECT JSON_VALID( '{ "firstName" : "Fred", "lastName" : "Flintstone" }' ); +JSON_VALID( '{ "firstName" : "Fred", "lastName" : "Flintstone" }' ) +1 +SELECT JSON_VALID( '3' ); +JSON_VALID( '3' ) +1 +SELECT JSON_VALID( null ); +JSON_VALID( null ) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_CONTAINS_PATH function. +# ---------------------------------------------------------------------- +select json_contains_path(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_contains_path' +select json_contains_path('{ "a": true }' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_contains_path' +select json_contains_path('{ "a": true }', 'all' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_contains_path' +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_contains_path('{ "a": tru }', 'all', '$' ); +json_contains_path('{ "a": tru }', 'all', '$' ) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_contains_path' at position 10 +error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$[' ); +json_contains_path('{ "a": true }', 'all', '$[' ) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 3 to function 'json_contains_path' +error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$a.***[3]' ); +json_contains_path('{ "a": true }', 'all', '$a.***[3]' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 3 to function 'json_contains_path' at position 2 +error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_contains_path('{ "a": true }', 'foo', '$.a' ); +json_contains_path('{ "a": true }', 'foo', '$.a' ) +NULL +Warnings: +Warning 4046 Argument 2 to function 'json_contains_path' must be "one" or "all". +error ER_INVALID_JSON_CHARSET +select json_contains_path('{}', 'all', cast('$' as binary)); +json_contains_path('{}', 'all', cast('$' as binary)) +1 +select json_contains_path(null, 'all', '$.a' ); +json_contains_path(null, 'all', '$.a' ) +NULL +select json_contains_path('{ "a": true }', null, '$.a' ); +json_contains_path('{ "a": true }', null, '$.a' ) +NULL +select json_contains_path('{ "a": true }', 'all', null ); +json_contains_path('{ "a": true }', 'all', null ) +NULL +select json_contains_path('{ "a": true }', 'all', '$' ); +json_contains_path('{ "a": true }', 'all', '$' ) +1 +select json_contains_path('{ "a": true }', 'all', '$.a' ); +json_contains_path('{ "a": true }', 'all', '$.a' ) +1 +select json_contains_path('{ "a": true }', 'one', '$.a' ); +json_contains_path('{ "a": true }', 'one', '$.a' ) +1 +select json_contains_path('{ "a": true }', 'all', '$.b' ); +json_contains_path('{ "a": true }', 'all', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'one', '$.b' ); +json_contains_path('{ "a": true }', 'one', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'all', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'all', '$.a', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'all', '$.b', '$.a' ); +json_contains_path('{ "a": true }', 'all', '$.b', '$.a' ) +0 +select json_contains_path('{ "a": true }', 'ALL', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'ALL', '$.a', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'aLl', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'aLl', '$.a', '$.b' ) +0 +select json_contains_path('{ "a": true }', 'one', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'one', '$.a', '$.b' ) +1 +select json_contains_path('{ "a": true }', 'one', '$.b', '$.a' ); +json_contains_path('{ "a": true }', 'one', '$.b', '$.a' ) +1 +select json_contains_path('{ "a": true }', 'ONE', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'ONE', '$.a', '$.b' ) +1 +select json_contains_path('{ "a": true }', 'oNe', '$.a', '$.b' ); +json_contains_path('{ "a": true }', 'oNe', '$.a', '$.b' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]', '$**[5]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]', '$**[5]' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[2]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[2]' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[3]' ); +json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[3]' ) +0 +select json_contains_path('{"a":1, "b":2}', 'one', '$.*'); +json_contains_path('{"a":1, "b":2}', 'one', '$.*') +1 +select json_contains_path('[1,2,3]', 'one', '$.*'); +json_contains_path('[1,2,3]', 'one', '$.*') +0 +select json_contains_path('{}', 'one', '$[*]'); +json_contains_path('{}', 'one', '$[*]') +0 +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'one', '$**.a.*'); +JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'one', '$**.a.*') +1 +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'all', '$**.a.*'); +JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'all', '$**.a.*') +1 +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'one', '$**[*]'); +JSON_CONTAINS_PATH('[1,2,3]', 'one', '$**[*]') +1 +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'all', '$**[*]'); +JSON_CONTAINS_PATH('[1,2,3]', 'all', '$**[*]') +1 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$**[1]', '$.b[0]', '$.c' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$**[1]', '$.b[0]', '$.c' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.c', '$**[1]', '$.b[0]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.c', '$**[1]', '$.b[0]' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.b[0]', '$.c', '$**[1]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.b[0]', '$.c', '$**[1]' ) +0 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$**[1]', '$.b[0]', '$.c' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$**[1]', '$.b[0]', '$.c' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.c', '$**[1]', '$.b[0]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.c', '$**[1]', '$.b[0]' ) +1 +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.b[0]', '$.c', '$**[1]' ); +json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.b[0]', '$.c', '$**[1]' ) +1 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.a.c', +'$.b[1]' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.a.c', +'$.b[1]' +) +0 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'$.a.c', +'$.b[1]' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'$.a.c', +'$.b[1]' +) +1 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.c' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'all', +'$.c' +) +0 +SELECT JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, { "c" : { "d" : true } } ] }', +'all', +'$.b[1].c.d' +); +JSON_CONTAINS_PATH +( +'{ "a" : 123, "b" : [ 123, { "c" : { "d" : true } } ] }', +'all', +'$.b[1].c.d' +) +1 +select json_length( null ); +json_length( null ) +NULL +select json_length( '1' ); +json_length( '1' ) +1 + +# invalid json text +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_length( 'abc' ); +json_length( 'abc' ) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_length' at position 1 +select json_length( '"abc"' ); +json_length( '"abc"' ) +1 +select json_length( 'true' ); +json_length( 'true' ) +1 +select json_length( 'false' ); +json_length( 'false' ) +1 +select json_length( 'null' ); +json_length( 'null' ) +1 +select json_length( '{}' ); +json_length( '{}' ) +0 +select json_length( '{ "a" : 100, "b" : 200 }' ); +json_length( '{ "a" : 100, "b" : 200 }' ) +2 +select json_length( '{ "a" : 100, "b" : [ 300, 400, 500 ] }' ); +json_length( '{ "a" : 100, "b" : [ 300, 400, 500 ] }' ) +2 +select json_length( '[]' ); +json_length( '[]' ) +0 +select json_length( '[ null, "foo", true, 1.1 ]' ); +json_length( '[ null, "foo", true, 1.1 ]' ) +4 +select json_length( '[ null, "foo", true, { "a" : "b", "c" : "d" } ]' ); +json_length( '[ null, "foo", true, { "a" : "b", "c" : "d" } ]' ) +4 +select json_length( '"foo"' ); +json_length( '"foo"' ) +1 +select json_length( '1.2' ); +json_length( '1.2' ) +1 + +# invalid json path +error ER_INVALID_JSON_PATH +select json_length( 'true', 'c$' ); +json_length( 'true', 'c$' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_length' at position 1 + +# invalid json path +error ER_INVALID_JSON_PATH +select json_length( '{ "foo" : [ true, false ] }', '$.foo[bar]' ); +json_length( '{ "foo" : [ true, false ] }', '$.foo[bar]' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_length' at position 7 + +# wildcards not allowed in path expressions for this function +error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.*' ); +json_length( 'true', '$.*' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_length' + +# wildcards not allowed in path expressions for this function +error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.foo**.bar' ); +json_length( 'true', '$.foo**.bar' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_length' +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[1]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[1]' ) +3 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) +NULL +select json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ) +NULL +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ) +NULL +select json_length( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); +json_length( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ) +3 +SELECT JSON_LENGTH +( +'{}' +); +JSON_LENGTH +( +'{}' +) +0 +SELECT JSON_LENGTH +( +'3' +); +JSON_LENGTH +( +'3' +) +1 +SELECT JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }' +); +JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }' +) +2 +SELECT JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.b' +); +JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.b' +) +3 +SELECT JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.c' +); +JSON_LENGTH +( +'{ "a" : 123, "b" : [ 123, 456, 789 ] }', +'$.c' +) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_DEPTH function. +# ---------------------------------------------------------------------- +select json_depth(null); +json_depth(null) +NULL +select json_depth(cast(null as json)); +json_depth(cast(null as json)) +NULL +select json_depth(cast('[]' as json)), +json_depth(cast('{}' as json)), +json_depth(cast('null' as json)), +json_depth(json_quote('foo')); +json_depth(cast('[]' as json)) json_depth(cast('{}' as json)) json_depth(cast('null' as json)) json_depth(json_quote('foo')) +1 1 1 1 +select json_depth(cast('[[2], 3, [[[4]]]]' as json)); +json_depth(cast('[[2], 3, [[[4]]]]' as json)) +5 +select json_depth(cast('{"a": {"a1": [3]}, "b": {"b1": {"c": {"d": [5]}}}}' as json)); +json_depth(cast('{"a": {"a1": [3]}, "b": {"b1": {"c": {"d": [5]}}}}' as json)) +6 +SELECT JSON_DEPTH +( +'{}' +); +JSON_DEPTH +( +'{}' +) +1 +SELECT JSON_DEPTH +( +'[]' +); +JSON_DEPTH +( +'[]' +) +1 +SELECT JSON_DEPTH( '"abc"' ); +JSON_DEPTH( '"abc"' ) +1 +SELECT JSON_DEPTH( CAST( '"abc"' AS JSON ) ); +JSON_DEPTH( CAST( '"abc"' AS JSON ) ) +1 +error ER_INVALID_TYPE_FOR_JSON +SELECT JSON_DEPTH( 1 ); +JSON_DEPTH( 1 ) +1 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH( 'abc' ); +JSON_DEPTH( 'abc' ) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_depth' at position 1 +SELECT JSON_DEPTH( CAST( 1 AS JSON ) ); +JSON_DEPTH( CAST( 1 AS JSON ) ) +1 +SELECT JSON_DEPTH +( +'{ "a" : true, "b" : false, "c" : null }' +); +JSON_DEPTH +( +'{ "a" : true, "b" : false, "c" : null }' +) +2 +SELECT JSON_DEPTH +( +'[ "a", true, "b" , false, "c" , null ]' +); +JSON_DEPTH +( +'[ "a", true, "b" , false, "c" , null ]' +) +2 +SELECT JSON_DEPTH +( +'{ "a" : true, "b" : {}, "c" : null }' +); +JSON_DEPTH +( +'{ "a" : true, "b" : {}, "c" : null }' +) +2 +SELECT JSON_DEPTH +( +'[ "a", true, "b" , {}, "c" , null ]' +); +JSON_DEPTH +( +'[ "a", true, "b" , {}, "c" , null ]' +) +2 +SELECT JSON_DEPTH +( +'{ "a" : true, "b" : { "e" : false }, "c" : null }' +); +JSON_DEPTH +( +'{ "a" : true, "b" : { "e" : false }, "c" : null }' +) +3 +SELECT JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null ]' +); +JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null ]' +) +3 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null' +); +JSON_DEPTH +( +'[ "a", true, "b" , { "e" : false }, "c" , null' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_depth' +# ---------------------------------------------------------------------- +# Test of JSON_REMOVE function. +# ---------------------------------------------------------------------- +select json_remove( null, '$[1]' ); +json_remove( null, '$[1]' ) +NULL +select json_remove( null, '$[1]' ) is null; +json_remove( null, '$[1]' ) is null +1 +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) +NULL +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null +1 +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) +NULL +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) is null +1 + +# not enough args +select json_remove(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_remove' + +# not enough args +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_remove' + +# not enough args +select json_remove( '$[1]' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_remove' + +# invalid json text +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ', '$[1]', '$[2]' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ', '$[1]', '$[2]' ) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' + +# invalid json path +error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1', '$[2]' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1', '$[2]' ) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 2 to function 'json_remove' + +# invalid json path +error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', '$[2' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', '$[2' ) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 3 to function 'json_remove' + +# Vacuous path expression +error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$' ); +json_remove( '[ 1, 2, 3 ]', '$' ) +NULL +Warnings: +Warning 4051 Path expression '$' is not allowed in argument 2 to function 'json_remove'. + +# Vacuous path expression +error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$', '$[2]' ); +json_remove( '[ 1, 2, 3 ]', '$', '$[2]' ) +NULL +Warnings: +Warning 4051 Path expression '$' is not allowed in argument 2 to function 'json_remove'. + +# Vacuous path expression +error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$[1]', '$' ); +json_remove( '[ 1, 2, 3 ]', '$[1]', '$' ) +NULL +Warnings: +Warning 4051 Path expression '$' is not allowed in argument 3 to function 'json_remove'. +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[*]' ); +json_remove( '[ 1, 2, 3 ]', '$[*]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$**[2]' ); +json_remove( '[ 1, 2, 3 ]', '$**[2]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ); +json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 3 to function 'json_remove' +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ); +json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 3 to function 'json_remove' +select json_remove( '[ 1, 2, 3 ]', '$[0]' ); +json_remove( '[ 1, 2, 3 ]', '$[0]' ) +[ 2, 3 ] +select json_remove( '[ 1, 2, 3 ]', '$[1]' ); +json_remove( '[ 1, 2, 3 ]', '$[1]' ) +[ 1, 3 ] +select json_remove( '[ 1, 2, 3 ]', '$[2]' ); +json_remove( '[ 1, 2, 3 ]', '$[2]' ) +[ 1, 2] +select json_remove( '[ 1, 2, 3 ]', '$[3]' ); +json_remove( '[ 1, 2, 3 ]', '$[3]' ) +[ 1, 2, 3 ] +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ) +[ 1, 5 ] +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": { "a": true } } ]', '$**.a' ); +json_remove( '[ { "a": { "a": true } } ]', '$**.a' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +select json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ); +json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ) +[ { }, { "b": false }, { }, { "a": null } ] +error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c": null }, { "a": null } ]', '$**.a' ); +json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c": null }, { "a": null } ]', '$**.a' ) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_remove' +select json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ); +json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ) +{"id": 123, "name": "systemQA", "array": [1, 2, 3]} +SELECT JSON_REMOVE +( +'{"a" : "foo", "b" : [true, {"c" : 123}]}', +'$.b[ 1 ]' +); +JSON_REMOVE +( +'{"a" : "foo", "b" : [true, {"c" : 123}]}', +'$.b[ 1 ]' +) +{"a" : "foo", "b" : [true, {"c" : 123}]} +SELECT JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +); +JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' +SELECT JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +); +JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' +SELECT JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "d" : 456 } ] }', +'$.b[ 1 ].e' +); +JSON_REMOVE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "d" : 456 } ] }', +'$.b[ 1 ].e' +) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_remove' +# ---------------------------------------------------------------------- +# Test of JSON_MERGE function. +# ---------------------------------------------------------------------- + +# not enough args +select json_merge(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_merge' + +# not enough args +select json_merge( '[ 1, 2, 3 ]' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_merge' +select json_merge( null, null ); +json_merge( null, null ) +NULL +select json_merge( null, '[ 1, 2, 3 ]' ); +json_merge( null, '[ 1, 2, 3 ]' ) +NULL +select json_merge( '[ 1, 2, 3 ]', null ); +json_merge( '[ 1, 2, 3 ]', null ) +NULL +select json_merge( null, '[ 1, 2, 3 ]', '[ 4, 5, 6 ]' ); +json_merge( null, '[ 1, 2, 3 ]', '[ 4, 5, 6 ]' ) +NULL +select json_merge( '[ 1, 2, 3 ]', null, '[ 4, 5, 6 ]' ); +json_merge( '[ 1, 2, 3 ]', null, '[ 4, 5, 6 ]' ) +NULL +select json_merge( '[ 1, 2, 3 ]', '[ 4, 5, 6 ]', null ); +json_merge( '[ 1, 2, 3 ]', '[ 4, 5, 6 ]', null ) +NULL +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2]', '[3, 4' ); +json_merge( '[1, 2]', '[3, 4' ) +[1, 2, 3, 4 +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2', '[3, 4]' ); +json_merge( '[1, 2', '[3, 4]' ) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_merge' +select json_merge( '1', '2' ); +json_merge( '1', '2' ) +[1, 2] +select json_merge( '1', '[2, 3]' ); +json_merge( '1', '[2, 3]' ) +[1, 2, 3] +select json_merge( '[1, 2]', '3' ); +json_merge( '[1, 2]', '3' ) +[1, 2, 3] +select json_merge( '1', '{ "a": 2 }' ); +json_merge( '1', '{ "a": 2 }' ) +[1, { "a": 2 }] +select json_merge( '{ "a": 2 }', '1' ); +json_merge( '{ "a": 2 }', '1' ) +[{ "a": 2 }, 1] +select json_merge( '[1, 2]', '[3, 4]' ); +json_merge( '[1, 2]', '[3, 4]' ) +[1, 2, 3, 4] +select json_merge( '{ "a": 2 }', '{ "b": 3}' ); +json_merge( '{ "a": 2 }', '{ "b": 3}' ) +{ "a": 2 , "b": 3} +select json_merge( '[1, 2]', '{ "a": 2 }' ); +json_merge( '[1, 2]', '{ "a": 2 }' ) +[1, 2, { "a": 2 }] +select json_merge( '{ "a": 2 }', '[1, 2]' ); +json_merge( '{ "a": 2 }', '[1, 2]' ) +[{ "a": 2 }, 1, 2] +select json_merge( '{"a": 1, "b": 2 }', '{"b": 3, "d": 4 }' ); +json_merge( '{"a": 1, "b": 2 }', '{"b": 3, "d": 4 }' ) +{"a": 1, "b": 2 , "b": 3, "d": 4 } +select json_merge( '{"a": 1, "b": 2 }', '{"b": [3, 4], "d": 4 }' ); +json_merge( '{"a": 1, "b": 2 }', '{"b": [3, 4], "d": 4 }' ) +{"a": 1, "b": 2 , "b": [3, 4], "d": 4 } +select json_merge( '{"a": 1, "b": [2, 3] }', '{"b": 4, "d": 4 }' ); +json_merge( '{"a": 1, "b": [2, 3] }', '{"b": 4, "d": 4 }' ) +{"a": 1, "b": [2, 3] , "b": 4, "d": 4 } +select json_merge( '{"a": 1, "b": 2 }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +json_merge( '{"a": 1, "b": 2 }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ) +{"a": 1, "b": 2 , "b": {"e": 7, "f": 8}, "d": 4 } +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": 2 }' ); +json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": 2 }' ) +{"b": {"e": 7, "f": 8}, "d": 4 , "a": 1, "b": 2 } +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": [10, 11], "d": 4 }' ); +json_merge( '{"a": 1, "b": [2, 9] }', '{"b": [10, 11], "d": 4 }' ) +{"a": 1, "b": [2, 9] , "b": [10, 11], "d": 4 } +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +json_merge( '{"a": 1, "b": [2, 9] }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ) +{"a": 1, "b": [2, 9] , "b": {"e": 7, "f": 8}, "d": 4 } +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": [2, 9] }' ); +json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": [2, 9] }' ) +{"b": {"e": 7, "f": 8}, "d": 4 , "a": 1, "b": [2, 9] } +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{ "a": 1, "b": {"e": 20, "g": 21 } }' ); +json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{ "a": 1, "b": {"e": 20, "g": 21 } }' ) +{"b": {"e": 7, "f": 8}, "d": 4 , "a": 1, "b": {"e": 20, "g": 21 } } +select json_merge( '1', '2', '3' ); +json_merge( '1', '2', '3' ) +[1, 2, 3] +select json_merge( '[1, 2 ]', '3', '[4, 5]' ); +json_merge( '[1, 2 ]', '3', '[4, 5]' ) +[1, 2 , 3, 4, 5] +select json_merge +( +'{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] }', +'{ "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] }', +'{ "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] }' +); +json_merge +( +'{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] }', +'{ "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] }', +'{ "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] }' +) +{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] , "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] , "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] } +SELECT JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'[ 5, 6]' +); +JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'[ 5, 6]' +) +[{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }, 5, 6] +SELECT JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": [ false, 34 ] }' +); +JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": [ false, 34 ] }' +) +{ "a" : "foo", "b" : [ true, { "c" : 123 } ] , "b": [ false, 34 ] } +SELECT JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": "bar" }' +); +JSON_MERGE +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'{ "b": "bar" }' +) +{ "a" : "foo", "b" : [ true, { "c" : 123 } ] , "b": "bar" } +SELECT JSON_MERGE +( +'{ "a" : { "b" : 1 } }', +'{ "a" : { "c" : 1 } }' +); +JSON_MERGE +( +'{ "a" : { "b" : 1 } }', +'{ "a" : { "c" : 1 } }' +) +{ "a" : { "b" : 1 } , "a" : { "c" : 1 } } +# ---------------------------------------------------------------------- +# Test of JSON_TYPE function. +# ---------------------------------------------------------------------- +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type('abc'); +json_type('abc') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_type' at position 1 +select json_type('{"a": 2}'); +json_type('{"a": 2}') +OBJECT +select json_type('[1,2]'); +json_type('[1,2]') +ARRAY +select json_type('"scalar string"'); +json_type('"scalar string"') +STRING +select json_type('true'); +json_type('true') +BOOLEAN +select json_type('false'); +json_type('false') +BOOLEAN +select json_type('null'); +json_type('null') +NULL +select json_type('1'); +json_type('1') +INTEGER +select json_type('-0'); +json_type('-0') +INTEGER +select json_type('-0.0'); +json_type('-0.0') +DOUBLE +error ER_INVALID_TYPE_FOR_JSON +select json_type(-1); +json_type(-1) +INTEGER +error ER_INVALID_TYPE_FOR_JSON +select json_type(CAST(1 AS UNSIGNED)); +json_type(CAST(1 AS UNSIGNED)) +INTEGER +select json_type('32767'); +json_type('32767') +INTEGER +error ER_INVALID_TYPE_FOR_JSON +select json_type(PI()); +json_type(PI()) +DOUBLE +select json_type('3.14'); +json_type('3.14') +DOUBLE +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type(CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8')); +json_type(CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8')) +INTEGER +# ---------------------------------------------------------------------- +# Test of CAST(literal AS JSON) +# ---------------------------------------------------------------------- +select json_type(cast(cast('2014-11-25 18:00' as datetime) as json)); +json_type(cast(cast('2014-11-25 18:00' as datetime) as json)) +INTEGER +select json_type(cast(cast('2014-11-25' as date) as json)); +json_type(cast(cast('2014-11-25' as date) as json)) +INTEGER +select json_type(cast(cast('18:00:59' as time) as json)); +json_type(cast(cast('18:00:59' as time) as json)) +INTEGER +select json_type(cast(127 as json)); +json_type(cast(127 as json)) +INTEGER +select json_type(cast(255 as json)); +json_type(cast(255 as json)) +INTEGER +select json_type(cast(32767 as json)); +json_type(cast(32767 as json)) +INTEGER +select json_type(cast(65535 as json)); +json_type(cast(65535 as json)) +INTEGER +select json_type(cast(8388607 as json)); +json_type(cast(8388607 as json)) +INTEGER +select json_type(cast(16777215 as json)); +json_type(cast(16777215 as json)) +INTEGER +select json_type(cast(2147483647 as json)); +json_type(cast(2147483647 as json)) +INTEGER +select json_type(cast(4294967295 as json)); +json_type(cast(4294967295 as json)) +INTEGER +select json_type(cast(9223372036854775807 as json)); +json_type(cast(9223372036854775807 as json)) +INTEGER +select json_type(cast(18446744073709551615 as json)); +json_type(cast(18446744073709551615 as json)) +INTEGER +select json_type(cast(true as json)); +json_type(cast(true as json)) +INTEGER +select json_type(cast(b'10101' as json)); +json_type(cast(b'10101' as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(cast(3.14 as decimal(5,2)) as json)); +json_type(cast(cast(3.14 as decimal(5,2)) as json)) +DOUBLE +select json_type(cast(3.14 as json)); +json_type(cast(3.14 as json)) +DOUBLE +select json_type(cast(3.14E30 as json)); +json_type(cast(3.14E30 as json)) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_type' at position 7 +select json_type(cast(cast('10101abcde' as binary) as json)); +json_type(cast(cast('10101abcde' as binary) as json)) +INTEGER +select json_type(cast(ST_GeomFromText('POINT(1 1)') as json)); +json_type(cast(ST_GeomFromText('POINT(1 1)') as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json)); +json_type(cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json)); +json_type(cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json)) +NULL +Warnings: +Warning 4036 Character disallowd in JSON in argument 1 to function 'json_type' at position 1 +select json_type(cast(null as json)); +json_type(cast(null as json)) +NULL +select json_type(cast(null as json)) is null; +json_type(cast(null as json)) is null +1 +select json_type(null) is null; +json_type(null) is null +1 +select cast(cast('2014-11-25 18:00' as datetime) as json); +cast(cast('2014-11-25 18:00' as datetime) as json) +2014-11-25 18:00:00 +select cast(cast('2014-11-25' as date) as json); +cast(cast('2014-11-25' as date) as json) +2014-11-25 +select cast(cast('18:00:59' as time) as json); +cast(cast('18:00:59' as time) as json) +18:00:59 +select cast(127 as json); +cast(127 as json) +127 +select cast(255 as json); +cast(255 as json) +255 +select cast(32767 as json); +cast(32767 as json) +32767 +select cast(65535 as json); +cast(65535 as json) +65535 +select cast(8388607 as json); +cast(8388607 as json) +8388607 +select cast(16777215 as json); +cast(16777215 as json) +16777215 +select cast(2147483647 as json); +cast(2147483647 as json) +2147483647 +select cast(4294967295 as json); +cast(4294967295 as json) +4294967295 +select cast(9223372036854775807 as json); +cast(9223372036854775807 as json) +9223372036854775807 +select cast(18446744073709551615 as json); +cast(18446744073709551615 as json) +18446744073709551615 +select cast(true as json); +cast(true as json) +1 +select cast(b'10101' as json); +cast(b'10101' as json) + +select cast(cast(3.14 as decimal(5,2)) as json); +cast(cast(3.14 as decimal(5,2)) as json) +3.14 +select cast(3.14 as json); +cast(3.14 as json) +3.14 +select cast(3.14e0 as json); +cast(3.14e0 as json) +3.14 +select cast(cast('10101abcde' as binary) as json); +cast(cast('10101abcde' as binary) as json) +10101abcde +select cast(ST_GeomFromText('POINT(1 1)') as json); +cast(ST_GeomFromText('POINT(1 1)') as json) +ð?ð? +select cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json); +cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json) +ð?ð?@@ +select cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json); +cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json) +$@$@$@$@@@@@@@@@@@ +select cast(null as json); +cast(null as json) +NULL +select cast(null as json) is null; +cast(null as json) is null +1 +# ---------------------------------------------------------------------- +# Test of JSON_KEYS function. +# ---------------------------------------------------------------------- +select json_keys(NULL); +json_keys(NULL) +NULL +select json_keys(NULL, '$.b'); +json_keys(NULL, '$.b') +NULL +select json_keys(NULL, NULL); +json_keys(NULL, NULL) +NULL +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a') +NULL +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', NULL); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', NULL) +NULL +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}') +["a", "b"] +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.b'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.b') +["e", "b"] +error ER_INVALID_JSON_PATH_WILDCARD +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b'); +json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b') +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_keys' +# returns [ "a", "b" ] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }'); +JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }') +["a", "b"] +# returns [] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c'); +JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c') +[] +# returns NULL +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]'); +JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]') +NULL +error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010'); +JSON_KEYS('{"a":1}', '1010') +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_keys' at position 1 +error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010') IS NULL; +JSON_KEYS('{"a":1}', '1010') IS NULL +0 +SELECT JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }' +); +JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }' +) +["a", "b"] +SELECT JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c' +); +JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.b[1].c' +) +[] +SELECT JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]' +); +JSON_KEYS +( +'{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', +'$.a.b[2]' +) +NULL +SELECT JSON_KEYS(); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_KEYS' +SELECT JSON_KEYS('{}', '$', '$'); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_KEYS' +# ---------------------------------------------------------------------- +# CAST( AS CHAR). See also 'json_conversions.test' for other +# conversion tests. +# ---------------------------------------------------------------------- +select cast(json_keys('{"a": 1}') as char); +cast(json_keys('{"a": 1}') as char) +["a"] +select cast(cast(1 as json) as char); +cast(cast(1 as json) as char) +1 +select cast(json_keys(NULL) as char); +cast(json_keys(NULL) as char) +NULL +# ---------------------------------------------------------------------- +# Path matching with double-quotes +# ---------------------------------------------------------------------- +select json_extract( '{ "one potato" : 1 }', '$."one potato"' ); +json_extract( '{ "one potato" : 1 }', '$."one potato"' ) +NULL +select json_extract( '{ "a.b" : 1 }', '$."a.b"' ); +json_extract( '{ "a.b" : 1 }', '$."a.b"' ) +NULL +select json_extract( '{ "\\"a\\"": 1}', '$."a"' ); +json_extract( '{ "\\"a\\"": 1}', '$."a"' ) +NULL +select json_extract( '{ "\\"a\\"": 1}', '$."\\"a\\""' ); +json_extract( '{ "\\"a\\"": 1}', '$."\\"a\\""' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 7 +select json_extract( '{ "a": 1}', '$."a"' ); +json_extract( '{ "a": 1}', '$."a"' ) +NULL +select json_extract( '{ "a": 1}', '$.a' ); +json_extract( '{ "a": 1}', '$.a' ) +1 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0]' ) +[ 3, 2 ] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0][1]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0][1]' ) +2 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1]' ) +[ { "c" : "d" }, 1 ] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0]' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0]' ) +{ "c" : "d" } +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0].c' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0].c' ) +"d" +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."one potato"' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."one potato"' ) +NULL +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.b.c' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.b.c' ) +6 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."b.c"' ); +json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."b.c"' ) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_EXTRACT function. +# ---------------------------------------------------------------------- +select json_extract(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_extract' +select json_extract('$.b'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_extract' +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_extract' +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_extract('$.a', '{"a": 1, "b": {"e": "foo", "b": 3}}'); +json_extract('$.a', '{"a": 1, "b": {"e": "foo", "b": 3}}') +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 2 to function 'json_extract' at position 1 +select json_extract(NULL, '$.b'); +json_extract(NULL, '$.b') +NULL +select json_extract(NULL, NULL); +json_extract(NULL, NULL) +NULL +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a') +1 +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*'); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*') +[1, {"e": "foo", "b": 3}] +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', '$.b.e'); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', '$.b.e') +[1, "foo"] +select json_extract('{"a": 1, "b": [1,2,3]}', '$.b[2]'); +json_extract('{"a": 1, "b": [1,2,3]}', '$.b[2]') +3 +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL); +json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL) +[1] +# returns a JSON value containing just the string "123" +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c') +NULL +# returns a JSON value containing just the number 123 +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c') +NULL +# raises an error because the document is not valid +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('{ "a" : [ }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : [ }', +'$.b[ 1 ].c') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 11 +# raises an error because the path is invalid +error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].') +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 2 to function 'json_extract' +# returns a JSON value containing the number 123 (because of +# auto-wrapping the scalar) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]') +NULL +# returns a JSON value containing the object because of auto-wrapping +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : {"not array": 4} } ] }', +'$.b[ 1 ].c[ 0 ]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : {"not array": 4} } ] }', +'$.b[ 1 ].c[ 0 ]') +NULL +# returns null because the path, although valid, does not identify a value +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]') +NULL +# returns a JSON value containing the number 123 (due to normalization) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c') +NULL +# returns a JSON array [ "foo", true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]') +["foo", true] +# returns a JSON array [ true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]'); +JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]') +[true] +select json_extract( '[1]', '$[0][0]' ); +json_extract( '[1]', '$[0][0]' ) +NULL +select json_extract( '[1]', '$**[0]' ); +json_extract( '[1]', '$**[0]' ) +[1] +select json_extract( '{ "a": 1 }', '$.a[0]' ); +json_extract( '{ "a": 1 }', '$.a[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$**[0]' ); +json_extract( '{ "a": 1 }', '$**[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$[0].a' ); +json_extract( '{ "a": 1 }', '$[0].a' ) +NULL +select json_extract( '{ "a": 1 }', '$**.a' ); +json_extract( '{ "a": 1 }', '$**.a' ) +[1] +select json_extract( '{ "a": 1 }', '$[0].a[0]' ); +json_extract( '{ "a": 1 }', '$[0].a[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$**[0]' ); +json_extract( '{ "a": 1 }', '$**[0]' ) +NULL +select json_extract( '{ "a": 1 }', '$[0].a' ); +json_extract( '{ "a": 1 }', '$[0].a' ) +NULL +select json_extract( '{ "a": 1 }', '$**.a' ); +json_extract( '{ "a": 1 }', '$**.a' ) +[1] +select json_extract( '{ "a": 1 }', '$[0][0].a' ); +json_extract( '{ "a": 1 }', '$[0][0].a' ) +NULL +select json_extract( '{ "a": 1 }', '$[0][0][0].a' ); +json_extract( '{ "a": 1 }', '$[0][0][0].a' ) +NULL +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', '$**.a.*'); +JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', '$**.a.*') +[{"c":42}] +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'$[1][0][0].x[0].a.*'); +JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', +'$[1][0][0].x[0].a.*') +[{"c":42}] +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', +'$.b[ 1 ].c' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c' +) +NULL +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT +( +'{ "a" : [ }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : [ }', +'$.b[ 1 ].c' +) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 11 +error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].' +) +NULL +Warnings: +Warning 4041 Unexpected end of JSON path in argument 2 to function 'json_extract' +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 0 ]' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', +'$.b[ 1 ].c[ 1 ]' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.b[ 1 ].c' +) +NULL +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.a', '$.b[0]' +) +["foo", true] +SELECT JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]' +); +JSON_EXTRACT +( +'{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', +'$.d', '$.b[0]' +) +[true] +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].b' ) jdoc; +jdoc +NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].b' ) jdoc; +jdoc +NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].a' ) jdoc; +jdoc +1 +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].a' ) jdoc; +jdoc +[1, 2] +select json_extract( '[ { "a": 1 }, { "b": 2 } ]', '$[*].a' ) jdoc; +jdoc +[1] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a' ) jdoc; +jdoc +[3,4] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[*].a' ) jdoc; +jdoc +[[3,4]] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a', '$[1].a' ) jdoc; +jdoc +[[3,4]] +# ---------------------------------------------------------------------- +# Test of JSON_ARRAY_APPEND function. +# ---------------------------------------------------------------------- +select json_array_append(NULL, '$.b', cast(1 as json)); +json_array_append(NULL, '$.b', cast(1 as json)) +NULL +select json_array_append('[1,2,3]', NULL, cast(1 as json)); +json_array_append('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_array_append('[1,2,3]', '$', NULL); +json_array_append('[1,2,3]', '$', NULL) +[1,2,3, null] +select json_array_append(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_append' +select json_array_append(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_append' +select json_array_append(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_append' +SELECT JSON_ARRAY_APPEND(cast('1' as json), '$', 3); +JSON_ARRAY_APPEND(cast('1' as json), '$', 3) +[1, 3] +SELECT JSON_ARRAY_APPEND(cast('{"a": 3}' as json), '$', 3); +JSON_ARRAY_APPEND(cast('{"a": 3}' as json), '$', 3) +[{"a": 3}, 3] +error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append(cast('{"a": {"b": [3]}}' as json), '$**[0]', 6); +json_array_append(cast('{"a": {"b": [3]}}' as json), '$**[0]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +# Auto-wrapping, since because the paths identify scalars. +# should return {"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a": "foo", "b": "bar", "c": "wibble"}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)); +JSON_ARRAY_APPEND('{"a": "foo", "b": "bar", "c": "wibble"}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)) +{"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} +# should return {"a": "foo", "b": [1, 2, 3, 4], +# "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)); +JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', cast(4 as json), +'$.c', cast('"grape"' as json)) +{"a" : "foo","b": [1, 2, 3, 4], "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', 4, +'$.c', 'grape'); +JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', +'$.b', 4, +'$.c', 'grape') +{"a" : "foo","b": [1, 2, 3, 4], "c": ["apple", "pear", "grape"]} +error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4); +json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4); +json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_array_append' +SELECT JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : "bar", "c" : "wibble" }', +'$.b', 4, +'$.c', "grape" +); +JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : "bar", "c" : "wibble" }', +'$.b', 4, +'$.c', "grape" +) +{ "a" : "foo", "b" : ["bar", 4], "c" : ["wibble", "grape"] } +SELECT JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ "apple", "pear" ] }', +'$.b', 4, +'$.c', "grape" +); +JSON_ARRAY_APPEND +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ "apple", "pear" ] }', +'$.b', 4, +'$.c', "grape" +) +{ "a" : "foo", "b" : [ 1, 2, 3 , 4], "c" : [ "apple", "pear" , "grape"] } +# ---------------------------------------------------------------------- +# Bug#21373874 ASSERTION `PARENT' FAILED +# ---------------------------------------------------------------------- +select json_array_append('{"a":1}', '$[0]', 100); +json_array_append('{"a":1}', '$[0]', 100) +NULL +select json_array_append('3', '$[0]', 100); +json_array_append('3', '$[0]', 100) +NULL +select json_array_append('3', '$[0][0][0][0]', 100); +json_array_append('3', '$[0][0][0][0]', 100) +NULL +# ---------------------------------------------------------------------- +# Test of JSON_INSERT function. +# ---------------------------------------------------------------------- +select json_insert(NULL, '$.b', cast(1 as json)); +json_insert(NULL, '$.b', cast(1 as json)) +NULL +select json_insert('[1,2,3]', NULL, cast(1 as json)); +json_insert('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_insert('[1,2,3]', '$[3]', NULL); +json_insert('[1,2,3]', '$[3]', NULL) +[1,2,3, null] +select json_insert(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_insert' +select json_insert(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_insert' +select json_insert(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_insert' +select json_insert('[1,2,3]', '$[2]', 4); +json_insert('[1,2,3]', '$[2]', 4) +[1,2,3] +select json_insert('[1,2,3]', '$[3]', 4); +json_insert('[1,2,3]', '$[3]', 4) +[1,2,3, 4] +select json_insert('[1,2,3]', '$[10]', 4); +json_insert('[1,2,3]', '$[10]', 4) +[1,2,3, 4] +select json_insert('{"c":4}', '$.c', 4); +json_insert('{"c":4}', '$.c', 4) +{"c":4} +select json_insert('{"c":4}', '$.a', 4); +json_insert('{"c":4}', '$.a', 4) +{"c":4, "a":4} +select json_insert('1', '$', 4); +json_insert('1', '$', 4) +[1, 4] +select json_insert('1', '$[0]', 4); +json_insert('1', '$[0]', 4) +[1, 4] +select json_insert('1', '$[1]', 4); +json_insert('1', '$[1]', 4) +[1, 4] +select json_insert('1', '$[10]', '4', '$[11]', 5); +json_insert('1', '$[10]', '4', '$[11]', 5) +[1, "4", 5] +select json_insert('[1,2,3]', '$[2][0]', 4); +json_insert('[1,2,3]', '$[2][0]', 4) +[1,2,[3, 4]] +select json_insert('[1,2,3]', '$[2][2]', 4); +json_insert('[1,2,3]', '$[2][2]', 4) +[1,2,[3, 4]] +select json_insert('{"a": 3}', '$.a[0]', 4); +json_insert('{"a": 3}', '$.a[0]', 4) +{"a": [3, 4]} +select json_insert('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); +json_insert('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') +{"a": [3, 4, "5"]} +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": [1], "b": 2}' as json), '$.*[1]', 6); +json_insert(cast('{"a": [1], "b": 2}' as json), '$.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": 1, "b": 2}' as json), '$.*[1]', 6); +json_insert(cast('{"a": 1, "b": 2}' as json), '$.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$.a.*[1]', 6); +json_insert(cast('{"a": {"b": 3}}' as json), '$.a.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$.a.*[1]', 6); +json_insert(cast('{"a": {"b": [3]}}' as json), '$.a.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$**[1]', 6); +json_insert(cast('{"a": {"b": 3}}' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); +json_insert(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$[*][1]', 6); +json_insert(cast('[1]' as json), '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$**[1]', 6); +json_insert(cast('[1]' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$[*][1]', 6); +json_insert(cast('[1, [2], 3]' as json), '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$**[1]', 6); +json_insert(cast('[1, [2], 3]' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$[*][1]', 6); +json_insert(cast('[[1]]' as json), '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$**[1]', 6); +json_insert(cast('[[1]]' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +select json_insert(cast('{"a": 3}' as json), '$[1]', 6); +json_insert(cast('{"a": 3}' as json), '$[1]', 6) +[{"a": 3}, 6] +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a', true); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a', true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', 123); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', 123) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":123} +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', '123'); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', '123') +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":"123"} +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[1]', true); +JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[1]', true) +{ "a" : ["foo", true], "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT('{ "a" : "foo"}', '$.b', true, '$.b', false); +JSON_INSERT('{ "a" : "foo"}', '$.b', true, '$.b', false) +{ "a" : "foo", "b":true} +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +true +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +true +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +123 +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +123 +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":123} +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +'123' +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +'123' +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":"123"} +SELECT JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[1]', +true +); +JSON_INSERT +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[1]', +true +) +{ "a" : ["foo", true], "b" : [ 1, 2, 3 ] } +SELECT JSON_INSERT +( +'{ "a" : "foo"}', +'$.b', true, +'$.b', false +); +JSON_INSERT +( +'{ "a" : "foo"}', +'$.b', true, +'$.b', false +) +{ "a" : "foo", "b":true} +# ---------------------------------------------------------------------- +# Test of JSON_ARRAY_INSERT function. +# ---------------------------------------------------------------------- +select json_array_insert(NULL, '$.b[1]', 1); +json_array_insert(NULL, '$.b[1]', 1) +NULL +select json_array_insert('[1,2,3]', NULL, 1); +json_array_insert('[1,2,3]', NULL, 1) +NULL +select json_array_insert('[1,2,3]', '$[3]', NULL); +json_array_insert('[1,2,3]', '$[3]', NULL) +[1,2,3, null] +select json_array_insert(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert' +select json_array_insert(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert' +select json_array_insert(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_array_insert' +error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$', 1); +json_array_insert('true', '$', 1) +NULL +error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a', 1); +json_array_insert('true', '$.a', 1) +NULL +error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a[1].b', 1); +json_array_insert('true', '$.a[1].b', 1) +NULL +select json_array_insert( 'true', '$[0]', false ); +json_array_insert( 'true', '$[0]', false ) +true +select json_array_insert( 'true', '$[1]', false ); +json_array_insert( 'true', '$[1]', false ) +true +select json_array_insert( '{ "a": true }', '$.a[0]', false ); +json_array_insert( '{ "a": true }', '$.a[0]', false ) +{ "a": true } +select json_array_insert( '{ "a": true }', '$.a[1]', false ); +json_array_insert( '{ "a": true }', '$.a[1]', false ) +{ "a": true } +select json_array_insert( '[]', '$[0]', false ); +json_array_insert( '[]', '$[0]', false ) +[false] +select json_array_insert( '[]', '$[1]', false ); +json_array_insert( '[]', '$[1]', false ) +[false] +select json_array_insert( '[true]', '$[0]', false ); +json_array_insert( '[true]', '$[0]', false ) +[false, true] +select json_array_insert( '[true]', '$[1]', false ); +json_array_insert( '[true]', '$[1]', false ) +[true, false] +select json_array_insert( '[true]', '$[2]', false ); +json_array_insert( '[true]', '$[2]', false ) +[true, false] +select json_array_insert( '{ "a": [] }', '$.a[0]', false ); +json_array_insert( '{ "a": [] }', '$.a[0]', false ) +{ "a": [false] } +select json_array_insert( '{ "a": [] }', '$.a[1]', false ); +json_array_insert( '{ "a": [] }', '$.a[1]', false ) +{ "a": [false] } +select json_array_insert( '{ "a": [true] }', '$.a[0]', false ); +json_array_insert( '{ "a": [true] }', '$.a[0]', false ) +{ "a": [false, true] } +select json_array_insert( '{ "a": [true] }', '$.a[1]', false ); +json_array_insert( '{ "a": [true] }', '$.a[1]', false ) +{ "a": [true, false] } +select json_array_insert( '{ "a": [true] }', '$.a[2]', false ); +json_array_insert( '{ "a": [true] }', '$.a[2]', false ) +{ "a": [true, false] } +select json_array_insert( '[1, 2, 3, 4]', '$[0]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[0]', false ) +[false, 1, 2, 3, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[1]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[1]', false ) +[1, false, 2, 3, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[2]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[2]', false ) +[1, 2, false, 3, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[3]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[3]', false ) +[1, 2, 3, false, 4] +select json_array_insert( '[1, 2, 3, 4]', '$[4]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[4]', false ) +[1, 2, 3, 4, false] +select json_array_insert( '[1, 2, 3, 4]', '$[5]', false ); +json_array_insert( '[1, 2, 3, 4]', '$[5]', false ) +[1, 2, 3, 4, false] +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false ) +{ "a": [false, 1, 2, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false ) +{ "a": [1, false, 2, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false ) +{ "a": [1, 2, false, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false ) +{ "a": [1, 2, 3, false, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false ) +{ "a": [1, 2, 3, 4, false] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false ) +{ "a": [1, 2, 3, 4, false] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false ) +{ "a": [1, 2, 3, 4] } +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false ); +json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false ) +{ "a": [1, 2, 3, 4] } +select json_array_insert( '"a"', '$[0]', true ); +json_array_insert( '"a"', '$[0]', true ) +"a" +select json_array_insert( '[ "a" ]', '$[0][0]', true ); +json_array_insert( '[ "a" ]', '$[0][0]', true ) +[ "a" ] +select json_array_insert( '"a"', '$[1]', true ); +json_array_insert( '"a"', '$[1]', true ) +"a" +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$.a.*[1]', 6); +json_insert('[]', '$.a.*[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$**[1]', 6); +json_insert('[]', '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$[*][1]', 6); +json_insert('[]', '$[*][1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_insert' +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ); +json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ) +[ 1, false, true, 2, 3 ] +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', +cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false ); +json_array_insert( '[ 1, 2, 3 ]', '$[1]', +cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false ) +[ 1, [ "a", "b", false, "c", "d" ], 2, 3 ] +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1); +JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +error ER_INVALID_JSON_TEXT_IN_PARAM +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) ); +json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) ) +[ 1, null, 2, 3 ] +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +# ---------------------------------------------------------------------- +# Test of JSON_SET function. +# ---------------------------------------------------------------------- +select json_set(NULL, '$.b', cast(1 as json)); +json_set(NULL, '$.b', cast(1 as json)) +NULL +select json_set('[1,2,3]', NULL, cast(1 as json)); +json_set('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_set('[1,2,3]', '$[3]', NULL); +json_set('[1,2,3]', '$[3]', NULL) +[1,2,3, null] +select json_set(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_set' +select json_set(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_set' +select json_set(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_set' +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_SET('{}', '$.name', JSON_EXTRACT('', '$')); +JSON_SET('{}', '$.name', JSON_EXTRACT('', '$')) +{, "name":null} +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +select json_set('[1,2,3]', '$[2]', 4); +json_set('[1,2,3]', '$[2]', 4) +[1,2,4] +select json_set('[1,2,3]', '$[3]', 4); +json_set('[1,2,3]', '$[3]', 4) +[1,2,3, 4] +select json_set('[1,2,3]', '$[10]', 4); +json_set('[1,2,3]', '$[10]', 4) +[1,2,3, 4] +select json_set('{"c":4}', '$.c', 5); +json_set('{"c":4}', '$.c', 5) +{"c":5} +select json_set('{"c":4}', '$.a', 5); +json_set('{"c":4}', '$.a', 5) +{"c":4, "a":5} +select json_set('1', '$', 4); +json_set('1', '$', 4) +[1, 4] +select json_set('1', '$[0]', 4); +json_set('1', '$[0]', 4) +[1, 4] +select json_set('1', '$[1]', 4); +json_set('1', '$[1]', 4) +[1, 4] +select json_set('1', '$[10]', '4', '$[11]', 5); +json_set('1', '$[10]', '4', '$[11]', 5) +[1, "4", 5] +select json_set('[1,2,3]', '$[2][0]', 4); +json_set('[1,2,3]', '$[2][0]', 4) +[1,2,[3, 4]] +select json_set('[1,2,3]', '$[2][2]', 4); +json_set('[1,2,3]', '$[2][2]', 4) +[1,2,[3, 4]] +select json_set('{"a": 3}', '$.a[0]', 4); +json_set('{"a": 3}', '$.a[0]', 4) +{"a": [3, 4]} +select json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); +json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') +{"a": [3, 4, "5"]} +error ER_INVALID_JSON_PATH_WILDCARD +select json_set(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); +json_set(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6) +NULL +Warnings: +Warning 4044 Wildcards in JSON path not allowed in argument 2 to function 'json_set' +SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT()); +JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT()) +{ "a" : {}, "b" : [ 1, 2, 3 ] } +SELECT JSON_SET('{ "a" : "foo"}', '$.a', +JSON_OBJECT( 'b', false ), '$.a.c', true); +JSON_SET('{ "a" : "foo"}', '$.a', +JSON_OBJECT( 'b', false ), '$.a.c', true) +{ "a" : {"b": false, "c":true}} +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +cast('{}' as json)); +json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +cast('{}' as json)) +{ "a" : {}, "b" : [ 1, 2, 3 ] } +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +cast('[true, false]' as json)); +json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +cast('[true, false]' as json)) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":[true, false]} +select json_set('1', '$[3]', 2); +json_set('1', '$[3]', 2) +[1, 2] +select json_set('{ "a" : "foo"}', '$.a', +cast('{"b": false}' as json), '$.a.c', true); +json_set('{ "a" : "foo"}', '$.a', +cast('{"b": false}' as json), '$.a.c', true) +{ "a" : {"b": false, "c":true}} +SELECT JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT() +); +JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a', +JSON_OBJECT() +) +{ "a" : {}, "b" : [ 1, 2, 3 ] } +SELECT JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( true, false ) +); +JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( true, false ) +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":[true, false]} +SELECT JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) ) +); +JSON_SET +( +'{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) ) +) +{ "a" : "foo", "b" : [ 1, 2, 3 ] , "c":[true, false]} +SELECT JSON_SET +( +'1', +'$[3]', +2 +); +JSON_SET +( +'1', +'$[3]', +2 +) +[1, 2] +SELECT JSON_SET +( +'{ "a" : "foo"}', +'$.a', JSON_OBJECT( 'b', false ), +'$.a.c', true +); +JSON_SET +( +'{ "a" : "foo"}', +'$.a', JSON_OBJECT( 'b', false ), +'$.a.c', true +) +{ "a" : {"b": false, "c":true}} +# ---------------------------------------------------------------------- +# Test of JSON_REPLACE function. +# ---------------------------------------------------------------------- +select json_replace(NULL, '$.b', cast(1 as json)); +json_replace(NULL, '$.b', cast(1 as json)) +NULL +select json_replace('[1,2,3]', NULL, cast(1 as json)); +json_replace('[1,2,3]', NULL, cast(1 as json)) +NULL +select json_replace('[1,2,3]', '$[2]', NULL); +json_replace('[1,2,3]', '$[2]', NULL) +[1,2,null] +select json_replace(NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_replace' +select json_replace(NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_replace' +select json_replace(NULL, NULL, NULL, NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_replace' +select json_replace('[1,2,3]', '$[2]', 4); +json_replace('[1,2,3]', '$[2]', 4) +[1,2,4] +select json_replace('[1,2,3]', '$[3]', 4); +json_replace('[1,2,3]', '$[3]', 4) +[1,2,3] +select json_replace('[1,2,3]', '$[10]', 4); +json_replace('[1,2,3]', '$[10]', 4) +[1,2,3] +select json_replace('{"c":4}', '$.c', 5); +json_replace('{"c":4}', '$.c', 5) +{"c":5} +select json_replace('{"c":4}', '$.a', 5); +json_replace('{"c":4}', '$.a', 5) +{"c":4} +select json_replace('1', '$', 4); +json_replace('1', '$', 4) +1 +select json_replace('1', '$[0]', 4); +json_replace('1', '$[0]', 4) +1 +select json_replace('1', '$[1]', 4); +json_replace('1', '$[1]', 4) +1 +select json_replace('1', '$[10]', '4', '$[11]', 5); +json_replace('1', '$[10]', '4', '$[11]', 5) +1 +select json_replace('[1,2,3]', '$[2][0]', 4); +json_replace('[1,2,3]', '$[2][0]', 4) +[1,2,3] +select json_replace('[1,2,3]', '$[2][2]', 4); +json_replace('[1,2,3]', '$[2][2]', 4) +[1,2,3] +select json_replace('{"a": 3}', '$.a[0]', 4); +json_replace('{"a": 3}', '$.a[0]', 4) +{"a": 3} +select json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); +json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') +{"a": 3} +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +true); +JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.c', +true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[0]', +true); +JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.a[0]', +true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.b[5]', +true); +JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +'$.b[5]', +true) +{ "a" : "foo", "b" : [ 1, 2, 3 ] } +# ---------------------------------------------------------------------- +# Test of JSON_ARRAY function. +# ---------------------------------------------------------------------- +select json_array(NULL, '$.b', cast(1 as json)); +json_array(NULL, '$.b', cast(1 as json)) +[null, "$.b", 1] +select json_array('[1,2,3]', NULL, cast(1 as json)); +json_array('[1,2,3]', NULL, cast(1 as json)) +["[1,2,3]", null, 1] +select json_array('[1,2,3]', '$[3]', NULL); +json_array('[1,2,3]', '$[3]', NULL) +["[1,2,3]", "$[3]", null] +select json_array(); +json_array() +[] +select json_array(3.14); +json_array(3.14) +[3.14] +select json_array('[1,2,3]'); +json_array('[1,2,3]') +["[1,2,3]"] +select json_array(cast('[1,2,3]' as json)); +json_array(cast('[1,2,3]' as json)) +[[1,2,3]] +select json_array(1,2,3); +json_array(1,2,3) +[1, 2, 3] +select json_array(b'0', b'1', b'10'); +json_array(b'0', b'1', b'10') +["\u0000", "\u0001", "\u0002"] +SELECT JSON_ARRAY(); +JSON_ARRAY() +[] +# ---------------------------------------------------------------------- +# Test of JSON_OBJECT function. +# ---------------------------------------------------------------------- +select json_object( 'a' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_object' +select json_object( 'a', 1, 'b' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_object' +error ER_JSON_DOCUMENT_NULL_KEY +select json_object( null, 1 ); +json_object( null, 1 ) +{"": 1} +select json_object(); +json_object() +{} +select json_object( 'a', null ); +json_object( 'a', null ) +{"a": null} +select json_object( 'a', 1 ); +json_object( 'a', 1 ) +{"a": 1} +select json_object( 'a', 1, 'b', 'foo' ); +json_object( 'a', 1, 'b', 'foo' ) +{"a": 1, "b": "foo"} +select json_object( 'a', 1, 'b', 'foo', 'c', cast( '{ "d": "wibble" }' as json ) ); +json_object( 'a', 1, 'b', 'foo', 'c', cast( '{ "d": "wibble" }' as json ) ) +{"a": 1, "b": "foo", "c": { "d": "wibble" }} +select json_object( 'a', true, 'b', false, 'c', cast( 'null' as json) ); +json_object( 'a', true, 'b', false, 'c', cast( 'null' as json) ) +{"a": true, "b": false, "c": null} +select json_valid( json_object( '"a"', 1 ) ); +json_valid( json_object( '"a"', 1 ) ) +0 +select json_object( REPEAT('a', 64 * 1024), 1 ); +json_object( REPEAT('a', 64 * 1024), 1 ) +{"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": 1} +select json_object(json_array(), json_array()); +json_object(json_array(), json_array()) +{"[]": []} +select json_object( cast(json_array() as char), json_array()); +json_object( cast(json_array() as char), json_array()) +{"[]": []} +select json_object( 1, json_array()); +json_object( 1, json_array()) +{"1": []} +select json_object( cast(1 as char), json_array()); +json_object( cast(1 as char), json_array()) +{"1": []} +SELECT JSON_OBJECT(); +JSON_OBJECT() +{} +# ---------------------------------------------------------------------- +# Test of JSON_SEARCH function. +# ---------------------------------------------------------------------- +select json_search(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_search' +select json_search( '{ "a": true }' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_search' +select json_search( '{ "a": true }', 'one' ); +ERROR 42000: Incorrect parameter count in the call to native function 'json_search' +select json_search( null, 'one', 'foo' ); +json_search( null, 'one', 'foo' ) +NULL +select json_search( '{ "a": "foo" }', null, 'foo' ); +json_search( '{ "a": "foo" }', null, 'foo' ) +NULL +select json_search( '{ "a": "foo" }', 'one', 'foo', null, null ); +json_search( '{ "a": "foo" }', 'one', 'foo', null, null ) +NULL +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$.a', null ); +json_search( '{ "a": "foo" }', 'one', 'foo', null, '$.a', null ) +NULL +error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'twof', 'foo' ); +json_search( '{ "a": "foo" }', 'twof', 'foo' ) +NULL +Warnings: +Warning 4046 Argument 2 to function 'json_search' must be "one" or "all". +error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'two', 'foo' ); +json_search( '{ "a": "foo" }', 'two', 'foo' ) +NULL +Warnings: +Warning 4046 Argument 2 to function 'json_search' must be "one" or "all". +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); +ERROR HY000: Incorrect arguments to ESCAPE +error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$a' ); +json_search( '{ "a": "foo" }', 'one', 'foo', null, '$a' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 5 to function 'json_search' at position 2 +error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'all', 'foo', null, '$.a', '$b' ); +json_search( '{ "a": "foo" }', 'all', 'foo', null, '$.a', '$b' ) +NULL +Warnings: +Warning 4042 Syntax error in JSON path in argument 6 to function 'json_search' at position 2 +select json_search(a, b, c); +ERROR 42S22: Unknown column 'a' in 'field list' +select json_search( '{ "a": "foobar" }', 'one', 'foo%' ); +json_search( '{ "a": "foobar" }', 'one', 'foo%' ) +"$.a" +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'one', 'foo%' ); +json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'one', 'foo%' ) +"$.a" +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'foo%' ); +json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'foo%' ) +["$.a", "$.c[1]"] +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'f__us' ); +json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'f__us' ) +"$.b" +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a' ) +["$.a[0]", "$.a[2]"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a', '$.b' ) +["$.a[0]", "$.a[2]", "$.b"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'one', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'one', 'foo%', null, '$.a', '$.b' ) +"$.a[0]" +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ALL', 'foo%', null, '$.a' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ALL', 'foo%', null, '$.a' ) +["$.a[0]", "$.a[2]"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'aLl', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'aLl', 'foo%', null, '$.a', '$.b' ) +["$.a[0]", "$.a[2]", "$.b"] +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ONE', 'foo%', null, '$.a', '$.b' ); +json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ONE', 'foo%', null, '$.a', '$.b' ) +"$.a[0]" +select json_search +( +'[ { "a": { "b": { "c": "fool" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "food"} } ]', +'all', +'foo%', +null, +'$**.c' +); +json_search +( +'[ { "a": { "b": { "c": "fool" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "food"} } ]', +'all', +'foo%', +null, +'$**.c' +) +["$[0].a.b.c", "$[2].c.c"] +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$**.c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$**.c' +) +["$[0].a.b.c", "$[1].b.c", "$[2].c.c"] +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%e', +null, +'$**.c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%e', +null, +'$**.c' +) +["$[0].a.b.c", "$[2].c.c"] +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$[*].c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', +'all', +'sho%', +null, +'$[*].c' +) +"$[2].c.c" +select json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, [ { "b": { "c": "shout" } }, { "c": { "c": "shoe"} } ] ]', +'all', +'sho%', +null, +'$[1]**.c' +); +json_search +( +'[ { "a": { "b": { "c": "showtime" } } }, [ { "b": { "c": "shout" } }, { "c": { "c": "shoe"} } ] ]', +'all', +'sho%', +null, +'$[1]**.c' +) +["$[1][0].b.c", "$[1][1].c.c"] +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo%bar' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo%bar' ) +["$[0]", "$[1]"] +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]', '$[2]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]', '$[2]' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[0]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[0]' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[1]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[1]' ) +"$[1]" +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ) +NULL +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[1]' ); +json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[1]' ) +"$[1]" +select json_search( '[ "abc", "ABC" ]', 'all', 'aBc' ); +json_search( '[ "abc", "ABC" ]', 'all', 'aBc' ) +["$[0]", "$[1]"] +select json_search( '[ "abc", "ABC" ]', 'all', 'abc' ); +json_search( '[ "abc", "ABC" ]', 'all', 'abc' ) +["$[0]", "$[1]"] +select json_search( '[ "abc", "ABC" ]', 'all', 'ABC' ); +json_search( '[ "abc", "ABC" ]', 'all', 'ABC' ) +["$[0]", "$[1]"] +select json_search( '[ 10, "10", 1.0, "1.0" ]', 'all', '1%' ); +json_search( '[ 10, "10", 1.0, "1.0" ]', 'all', '1%' ) +["$[0]", "$[1]", "$[2]", "$[3]"] +SELECT JSON_SEARCH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'123' +); +JSON_SEARCH +( +'{ "a" : 123, "b" : [ 123, 456 ] }', +'one', +'123' +) +"$.a" +SELECT JSON_SEARCH +( +'{ "a" : "123", "b" : [ 123, "789", "123", "456", "123" ] }', +'one', +'123', +null, +'$.b' +); +JSON_SEARCH +( +'{ "a" : "123", "b" : [ 123, "789", "123", "456", "123" ] }', +'one', +'123', +null, +'$.b' +) +"$.b[0]" +SELECT JSON_SEARCH +( +'{ "a" : "123", "b" : { "key" : "123" } }', +'one', +'123' +); +JSON_SEARCH +( +'{ "a" : "123", "b" : { "key" : "123" } }', +'one', +'123' +) +"$.a" +SELECT JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%' +); +JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%' +) +"$.b.key" +SELECT JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234", "c": "directorysub%directoryabc" } }', +'one', +'dir%torysub@%dir%', +'@' +); +JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234", "c": "directorysub%directoryabc" } }', +'one', +'dir%torysub@%dir%', +'@' +) +"$.b.c" +SELECT JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%', +null, +'$.c' +); +JSON_SEARCH +( +'{ "a" : "1243", "b" : { "key" : "1234" } }', +'one', +'123%', +null, +'$.c' +) +NULL +SELECT JSON_UNQUOTE +( +JSON_SEARCH +( +'{ "onepotato": "foot", "one potato": "food" , "one \\"potato": "fool" }', +'all', +'food' + ) +); +JSON_UNQUOTE +( +JSON_SEARCH +( +'{ "onepotato": "foot", "one potato": "food" , "one \\"potato": "fool" }', +'all', +'food' + ) +) +$.one potato +select json_type(case (null is null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end); +json_type(case (null is null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end) +NULL +select json_type(case (null is not null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end); +json_type(case (null is not null) when 1 then +cast('null' as json) else +cast('[1,2,3]' as json) end) +ARRAY +select json_type( if(null is null, +cast('null' as json), +cast('[1,2,3]' as json)) ); +json_type( if(null is null, +cast('null' as json), +cast('[1,2,3]' as json)) ) +NULL +select json_type( if(null is not null, +cast('null' as json), +cast('[1,2,3]' as json))); +json_type( if(null is not null, +cast('null' as json), +cast('[1,2,3]' as json))) +ARRAY +select cast(json_extract(cast(concat('[', cast('["A",2]' as json), ']') as json), +'$[0][1]') as char) = 2; +cast(json_extract(cast(concat('[', cast('["A",2]' as json), ']') as json), +'$[0][1]') as char) = 2 +1 +# ---------------------------------------------------------------------- +# Test of aggregate function MAX, MIN. +# ---------------------------------------------------------------------- +select max(cast('[1,2,3]' as json)); +max(cast('[1,2,3]' as json)) +[1,2,3] +# ---------------------------------------------------------------------- +# Test of JSON_QUOTE, JSON_UNQUOTE +# ---------------------------------------------------------------------- +select json_quote(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_quote('abc', 'def'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_quote(NULL, 'def'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_quote('abc', NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_quote' +select json_unquote(); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_unquote('"abc"', '"def"'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_unquote(NULL, 'def'); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_unquote('"abc"', NULL); +ERROR 42000: Incorrect parameter count in the call to native function 'json_unquote' +select json_quote(NULL); +json_quote(NULL) +NULL +select json_unquote(NULL); +json_unquote(NULL) +NULL +select json_quote('abc'); +json_quote('abc') +"abc" +select json_quote(convert('abc' using ascii)); +json_quote(convert('abc' using ascii)) +"abc" +select json_quote(convert('abc' using latin1)); +json_quote(convert('abc' using latin1)) +"abc" +select json_quote(convert('abc' using utf8)); +json_quote(convert('abc' using utf8)) +"abc" +select json_quote(convert('abc' using utf8mb4)); +json_quote(convert('abc' using utf8mb4)) +"abc" +select json_unquote('abc'); +json_unquote('abc') +abc +select json_unquote('"abc"'); +json_unquote('"abc"') +abc +select json_unquote(convert('"abc"' using ascii)); +json_unquote(convert('"abc"' using ascii)) +abc +select json_unquote(convert('"abc"' using latin1)); +json_unquote(convert('"abc"' using latin1)) +abc +select json_unquote(convert('"abc"' using utf8)); +json_unquote(convert('"abc"' using utf8)) +abc +select json_unquote(convert('"abc"' using utf8mb4)); +json_unquote(convert('"abc"' using utf8mb4)) +abc +select json_quote('"'); +json_quote('"') +"\"" +select json_unquote('"'); +json_unquote('"') +" +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_unquote' +error ER_INCORRECT_TYPE +select json_quote(123); +json_quote(123) +NULL +error ER_INCORRECT_TYPE +select json_unquote(123); +json_unquote(123) +123 +select json_unquote('""'); +json_unquote('""') + +select char_length(json_unquote('""')); +char_length(json_unquote('""')) +0 +select json_unquote('"" '); +json_unquote('"" ') + +select json_unquote(cast(json_quote('abc') as json)); +json_unquote(cast(json_quote('abc') as json)) +abc +select cast('{"abc": "foo"}' as json); +cast('{"abc": "foo"}' as json) +{"abc": "foo"} +select json_unquote(cast('{"abc": "foo"}' as json)); +json_unquote(cast('{"abc": "foo"}' as json)) +{"abc": "foo"} +select json_extract(cast('{"abc": "foo"}' as json), '$.abc'); +json_extract(cast('{"abc": "foo"}' as json), '$.abc') +"foo" +select json_unquote(json_extract(cast('{"abc": "foo"}' as json), '$.abc')); +json_unquote(json_extract(cast('{"abc": "foo"}' as json), '$.abc')) +foo +select json_unquote('["a", "b", "c"]'); +json_unquote('["a", "b", "c"]') +["a", "b", "c"] +select json_unquote(cast('["a", "b", "c"]' as json)); +json_unquote(cast('["a", "b", "c"]' as json)) +["a", "b", "c"] +select charset(json_unquote('"abc"')); +charset(json_unquote('"abc"')) +utf8 +select json_quote(convert(X'e68891' using utf8)); +json_quote(convert(X'e68891' using utf8)) +"我" +select json_quote(convert(X'e68891' using utf8mb4)); +json_quote(convert(X'e68891' using utf8mb4)) +"我" +select cast(json_quote(convert(X'e68891' using utf8)) as json); +cast(json_quote(convert(X'e68891' using utf8)) as json) +"我" +select json_unquote(convert(X'e68891' using utf8)); +json_unquote(convert(X'e68891' using utf8)) +我 +select json_quote(json_quote(json_quote('abc'))); +json_quote(json_quote(json_quote('abc'))) +"\"\\\"abc\\\"\"" +select json_unquote(json_unquote(json_unquote( # long round trip of it +json_quote(json_quote(json_quote('abc')))))); +json_unquote(json_unquote(json_unquote( # long round trip of it +json_quote(json_quote(json_quote('abc')))))) +abc +select cast(cast('2015-01-15 23:24:25' as datetime) as json); +cast(cast('2015-01-15 23:24:25' as datetime) as json) +2015-01-15 23:24:25 +select json_unquote(cast(cast('2015-01-15 23:24:25' as datetime) as json)); +json_unquote(cast(cast('2015-01-15 23:24:25' as datetime) as json)) +2015-01-15 23:24:25 +select cast(st_geomfromtext('point(1 1)') as json); +cast(st_geomfromtext('point(1 1)') as json) +ð?ð? +select json_unquote(cast(st_geomfromtext('point(1 1)') as json)); +json_unquote(cast(st_geomfromtext('point(1 1)') as json)) +ð?ð? +SELECT JSON_UNQUOTE( '"abc"' ); +JSON_UNQUOTE( '"abc"' ) +abc +SELECT JSON_UNQUOTE( '"abc' ); +JSON_UNQUOTE( '"abc' ) +"abc +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_unquote' +error ER_INCORRECT_TYPE +SELECT JSON_UNQUOTE( 123 ); +JSON_UNQUOTE( 123 ) +123 +SELECT JSON_UNQUOTE +( CAST( CAST( '"abc"' AS JSON ) AS CHAR ) ); +JSON_UNQUOTE +( CAST( CAST( '"abc"' AS JSON ) AS CHAR ) ) +abc +SELECT JSON_UNQUOTE +( +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) +) = 'fred'; +JSON_UNQUOTE +( +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) +) = 'fred' +1 +SELECT +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) = 'fred'; +CAST( +JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) +AS CHAR +) = 'fred' +0 +SELECT JSON_QUOTE( 'abc' ); +JSON_QUOTE( 'abc' ) +"abc" +error ER_INCORRECT_TYPE +SELECT JSON_QUOTE( 123 ); +JSON_QUOTE( 123 ) +NULL +SELECT CAST( JSON_QUOTE( '123' ) AS JSON ); +CAST( JSON_QUOTE( '123' ) AS JSON ) +"123" +# ---------------------------------------------------------------------- +# Test of JSON_CONTAINS +# ---------------------------------------------------------------------- +# should give NULL +select json_contains(NULL, NULL); +json_contains(NULL, NULL) +NULL +select json_contains(cast('{"a": 1, "b": 2}' as json), NULL); +json_contains(cast('{"a": 1, "b": 2}' as json), NULL) +NULL +select json_contains(NULL, cast('null' as json)); +json_contains(NULL, cast('null' as json)) +NULL +select json_contains(cast('[1]' as json), cast('[1]' as json), NULL); +json_contains(cast('[1]' as json), cast('[1]' as json), NULL) +NULL +# should give 0: +select json_contains(cast(3.14 as json), cast(3 as json)); +json_contains(cast(3.14 as json), cast(3 as json)) +0 +# should give 0: not at top level +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json)); +json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json)) +0 +# but path argument will fix it: +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json), '$.a'); +json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json), '$.a') +1 +# but arrays "introspect" +select json_contains(cast('[1,[2.0, 3.0]]' as json), cast('[2.0]' as json)); +json_contains(cast('[1,[2.0, 3.0]]' as json), cast('[2.0]' as json)) +1 +select json_contains(cast('[1, 2, [3, [4, 5]], 6, 7]' as json), cast('5' as json)); +json_contains(cast('[1, 2, [3, [4, 5]], 6, 7]' as json), cast('5' as json)) +1 +# should give 0: just a key +select json_contains(cast('{"a": 1, "b": 2}' as json), cast('"a"' as json)); +json_contains(cast('{"a": 1, "b": 2}' as json), cast('"a"' as json)) +0 +# should give 0: one candidate element doesn't match +select json_contains(cast('[1]' as json), cast('[1,2]' as json)); +json_contains(cast('[1]' as json), cast('[1,2]' as json)) +0 +# should all give 1 +select json_contains(cast('null' as json), cast('null' as json)); +json_contains(cast('null' as json), cast('null' as json)) +1 +# simple object subset +select json_contains(cast('{"a": 1, "b": 2}' as json), cast( '{"a": 1}' as json)); +json_contains(cast('{"a": 1, "b": 2}' as json), cast( '{"a": 1}' as json)) +1 +# simple vector subset +select json_contains(cast('[1, 2, 3]' as json), cast('[1, 3]' as json)); +json_contains(cast('[1, 2, 3]' as json), cast('[1, 3]' as json)) +1 +# auto-wrap, should give 1 +select json_contains(cast('[1, 2, 3]' as json), cast(3 as json)); +json_contains(cast('[1, 2, 3]' as json), cast(3 as json)) +1 +# ok even with nested cast off elements +select json_contains(cast('{"person": {"id": 1, "country": "norway"}}' as json), +cast('{"person": {"country": "norway"}}' as json)); +json_contains(cast('{"person": {"id": 1, "country": "norway"}}' as json), +cast('{"person": {"country": "norway"}}' as json)) +1 +# vector reordering and duplicates is ok +select json_contains(cast('[1,3,5]' as json), cast('[5,3,1,5]' as json)); +json_contains(cast('[1,3,5]' as json), cast('[5,3,1,5]' as json)) +1 +# ok even with more elts in candidate than in doc +select json_contains(cast('[{"b": 4, "a":7}]' as json), cast('[{"a":7},{"b":4}]' as json)); +json_contains(cast('[{"b": 4, "a":7}]' as json), cast('[{"a":7},{"b":4}]' as json)) +1 +select json_contains(cast('[{"b": 4, "a":7}, 5]' as json), cast('[5, {"a":7, "b":4}]' as json)); +json_contains(cast('[{"b": 4, "a":7}, 5]' as json), cast('[5, {"a":7, "b":4}]' as json)) +1 +# ok even with mixed number types that compare equal +select json_contains(cast('[{"b": 4, "a":7}, 5.0]' as json), cast('[5, {"a":7.0E0, "b":4}]' as json)); +json_contains(cast('[{"b": 4, "a":7}, 5.0]' as json), cast('[5, {"a":7.0E0, "b":4}]' as json)) +1 +select json_contains( '{"customer": "cust3"}', '{"customer": "cust1"}' ); +json_contains( '{"customer": "cust3"}', '{"customer": "cust1"}' ) +0 +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[3],false]'); +JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[3],false]') +1 +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[4],false]'); +JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[4],false]') +0 +SELECT JSON_CONTAINS('[true,false]', '[[true]]'); +JSON_CONTAINS('[true,false]', '[[true]]') +1 +SELECT JSON_CONTAINS('[1,2]', '[[1]]'); +JSON_CONTAINS('[1,2]', '[[1]]') +1 +SELECT JSON_CONTAINS('[1,2]', '1', '$.abc'); +JSON_CONTAINS('[1,2]', '1', '$.abc') +0 +SELECT JSON_CONTAINS('{}', '{}'); +JSON_CONTAINS('{}', '{}') +1 +SELECT JSON_CONTAINS('{}', '{"a":1}'); +JSON_CONTAINS('{}', '{"a":1}') +0 +SELECT JSON_CONTAINS('{"a":1}', '{"a":1,"b":2}'); +JSON_CONTAINS('{"a":1}', '{"a":1,"b":2}') +0 +SELECT JSON_CONTAINS +( +CAST('[1, 4, 6]' AS JSON), +CAST('[1, 6]' AS JSON) +); +JSON_CONTAINS +( +CAST('[1, 4, 6]' AS JSON), +CAST('[1, 6]' AS JSON) +) +1 +SELECT JSON_CONTAINS +( +CAST('{"person": {"id": 1, "country": "norway"}}' AS JSON), +CAST('{"person": {"country": "norway"}}' AS JSON) +); +JSON_CONTAINS +( +CAST('{"person": {"id": 1, "country": "norway"}}' AS JSON), +CAST('{"person": {"country": "norway"}}' AS JSON) +) +1 +SELECT JSON_CONTAINS +( +CAST('[1,3,5]' AS JSON), +CAST('[5,3,1,5]' AS JSON) +); +JSON_CONTAINS +( +CAST('[1,3,5]' AS JSON), +CAST('[5,3,1,5]' AS JSON) +) +1 +SELECT JSON_CONTAINS +( +CAST('[3.14]' AS JSON), +CAST('[3]' AS JSON) +); +JSON_CONTAINS +( +CAST('[3.14]' AS JSON), +CAST('[3]' AS JSON) +) +0 +SELECT JSON_CONTAINS +( +CAST('[1, 2, 3]' AS JSON), +CAST(3 AS JSON) +); +JSON_CONTAINS +( +CAST('[1, 2, 3]' AS JSON), +CAST(3 AS JSON) +) +1 +SELECT JSON_CONTAINS(); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_CONTAINS' +SELECT JSON_CONTAINS('[1]'); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_CONTAINS' +SELECT JSON_CONTAINS('[1]', '[1]', '$', '$[0]'); +ERROR 42000: Incorrect parameter count in the call to native function 'JSON_CONTAINS' +# ---------------------------------------------------------------------- +# Wrong collation from JSON_QUOTE caused problems: Set it in +# Item_func_json_quote::fix_length_and_dec. Bug found by Knut. +# Similar issue for JSON_UNQUOTE and JSON_TYPE. +# ---------------------------------------------------------------------- +select json_object("a", ifnull(json_quote('test'), cast('null' as json))); +json_object("a", ifnull(json_quote('test'), cast('null' as json))) +{"a": "\"test\""} +select cast(concat('[', json_quote('ab'), ']') as json); +cast(concat('[', json_quote('ab'), ']') as json) +["ab"] +select cast(concat('[', json_unquote('"12"'), ']') as json); +cast(concat('[', json_unquote('"12"'), ']') as json) +[12] +select cast(concat('["', json_type(cast(1 as json)), '"]') as json); +cast(concat('["', json_type(cast(1 as json)), '"]') as json) +["INTEGER"] +# +# Bug#20912438: ITEM_TYPE_HOLDER::DISPLAY_LENGTH(ITEM*): ASSERTION `0' FAILED +# +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55"}')) UNION ALL +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55" }') LIMIT 0); +JSON_KEYS('{ "key80": "2015-04-20 11:53:55"}') +["key80"] +SELECT CAST(1 AS JSON) UNION ALL SELECT CAST(1 AS JSON); +CAST(1 AS JSON) +1 +1 +SELECT COUNT(*), CAST(NULL AS JSON); +COUNT(*) CAST(NULL AS JSON) +1 NULL +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT COUNT(*), JSON_EXTRACT('not valid json!', '$'); +COUNT(*) JSON_EXTRACT('not valid json!', '$') +1 NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 1 +# ---------------------------------------------------------------------- +# Bug report from John E. +# Crash in Item_copy_json::~Item_copy_json +# ---------------------------------------------------------------------- +EXPLAIN SELECT COUNT(*), JSON_KEYS('{}'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used +select json_search( '{ "a": "foo" }', 'one', 'foo', 'a' ); +json_search( '{ "a": "foo" }', 'one', 'foo', 'a' ) +"$.a" +select json_search( '{ "a": "foo" }', 'one', 'foo', null ); +json_search( '{ "a": "foo" }', 'one', 'foo', null ) +"$.a" +select json_search( '{ "a": "foo" }', 'one', 'foo', convert(x'f8' using latin1) ); +json_search( '{ "a": "foo" }', 'one', 'foo', convert(x'f8' using latin1) ) +"$.a" +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); +ERROR HY000: Incorrect arguments to ESCAPE +# ---------------------------------------------------------------------- +# Wrong results when Json_path_cache primed is accessed +# during the prepare-phase. +#---------------------------------------------------------------------- +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null +1 +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', null ) is null'; +execute stmt1; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null +1 +error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$.' ) is null; +json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$.' ) is null +0 +error ER_INVALID_JSON_PATH +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', ''$.'' ) is null'; +# ---------------------------------------------------------------------- +# Bug#20987329 VALUE OF PREPARED STATEMENT PLACEHOLDER FOR PARAMETER +# IN JSON_EXTRACT IS STICKY +#---------------------------------------------------------------------- +prepare json_stmt1 FROM 'select json_contains( ''{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }'', ''[2]'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt1 USING @mypath; +json_contains( '{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }', '[2]', ? ) +1 +set @mypath = '$.keyB'; +execute json_stmt1 USING @mypath; +json_contains( '{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }', '[2]', ? ) +0 +prepare json_stmt2 FROM 'select json_contains_path( ''{ "keyA": [1, 2, 3] }'', ''all'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt2 USING @mypath; +json_contains_path( '{ "keyA": [1, 2, 3] }', 'all', ? ) +1 +set @mypath = '$.keyB'; +execute json_stmt2 USING @mypath; +json_contains_path( '{ "keyA": [1, 2, 3] }', 'all', ? ) +0 +prepare json_stmt3 FROM 'select json_length( ''{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt3 USING @mypath; +json_length( '{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }', ? ) +3 +set @mypath = '$.keyB'; +execute json_stmt3 USING @mypath; +json_length( '{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }', ? ) +4 +prepare json_stmt4 FROM 'select json_keys( ''[ { "keyA": true }, { "keyB": false } ]'', ? )'; +set @mypath = '$[0]'; +execute json_stmt4 USING @mypath; +json_keys( '[ { "keyA": true }, { "keyB": false } ]', ? ) +["keyA"] +set @mypath = '$[1]'; +execute json_stmt4 USING @mypath; +json_keys( '[ { "keyA": true }, { "keyB": false } ]', ? ) +["keyB"] +prepare json_stmt5 FROM 'select json_array_append( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA'; +execute json_stmt5 USING @mypath; +json_array_append( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2, 5], "keyB": [3, 4] } +set @mypath = '$.keyB'; +execute json_stmt5 USING @mypath; +json_array_append( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 4, 5] } +prepare json_stmt6 FROM 'select json_insert( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt6 USING @mypath; +json_insert( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2, 5], "keyB": [3, 4] } +set @mypath = '$.keyB[2]'; +execute json_stmt6 USING @mypath; +json_insert( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 4, 5] } +prepare json_stmt7 FROM 'select json_set( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt7 USING @mypath; +json_set( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2, 5], "keyB": [3, 4] } +set @mypath = '$.keyB[2]'; +execute json_stmt7 USING @mypath; +json_set( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 4, 5] } +prepare json_stmt8 FROM 'select json_replace( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[1]'; +execute json_stmt8 USING @mypath; +json_replace( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 5], "keyB": [3, 4] } +set @mypath = '$.keyB[1]'; +execute json_stmt8 USING @mypath; +json_replace( '{ "keyA": [1, 2], "keyB": [3, 4] }', ?, 5 ) +{ "keyA": [1, 2], "keyB": [3, 5] } +prepare json_stmt9 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ''all'', ''foo%'', null, ? )'; +set @mypath = '$.keyA'; +execute json_stmt9 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', 'all', 'foo%', null, ? ) +"$.keyA[0]" +set @mypath = '$.keyB'; +execute json_stmt9 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', 'all', 'foo%', null, ? ) +"$.keyB[0]" +prepare json_stmt10 FROM 'select json_remove( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt10 USING @mypath; +json_remove( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ? ) +{ "keyB": [ "food" ] } +set @mypath = '$.keyB'; +execute json_stmt10 USING @mypath; +json_remove( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ? ) +{ "keyA": [ "foot" ]} +prepare json_stmt11 FROM 'select json_contains_path( ''{ "keyA": true }'', ?, ''$.keyA'', ''$.keyB'' )'; +set @mypath = 'one'; +execute json_stmt11 USING @mypath; +json_contains_path( '{ "keyA": true }', ?, '$.keyA', '$.keyB' ) +1 +set @mypath = 'all'; +execute json_stmt11 USING @mypath; +json_contains_path( '{ "keyA": true }', ?, '$.keyA', '$.keyB' ) +0 +prepare json_stmt12 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ?, ''foo%'' )'; +set @mypath = 'one'; +execute json_stmt12 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ?, 'foo%' ) +"$.keyA[0]" +set @mypath = 'all'; +execute json_stmt12 USING @mypath; +json_search( '{ "keyA": [ "foot" ], "keyB": [ "food" ] }', ?, 'foo%' ) +["$.keyA[0]", "$.keyB[0]"] +# +# Bug#21128632 JSON_QUOTE(JSON_TYPE(...)) GIVES ERROR 3139 ER_INVALID_JSON_CHARSET +# +select json_quote( json_type( json_object() ) ); +json_quote( json_type( json_object() ) ) +"OBJECT" +select json_quote( json_type( cast('{}' as json) ) ); +json_quote( json_type( cast('{}' as json) ) ) +"OBJECT" +# +# Bug#21148020 OUTPUT FROM JSON_TYPE() IS TRUNCATED +# WHEN EXECUTED IN A VIEW OR JOIN +# +SELECT JSON_TYPE(JSON_OBJECT()); +JSON_TYPE(JSON_OBJECT()) +OBJECT +CREATE VIEW v1 AS SELECT JSON_TYPE(JSON_OBJECT()); +SELECT * FROM v1; +JSON_TYPE(JSON_OBJECT()) +OBJE +drop view v1; +# +# Bug#21198333 SIG 6 IN ITEM_CACHE_JSON::CACHE_VALUE AT SQL/ITEM.CC:9470 +# +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT MIN(JSON_EXTRACT('not json', '$')); +MIN(JSON_EXTRACT('not json', '$')) +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 1 +# +# Bug#21200657 DATA FROM DERIVED TABLE BASED +# ON JSN_QUOTE()/JSN_UNQUOTE() CALL IS TRUNCATED +# +SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1; +field1 +"This is a string that should not be truncated" +SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1; +field1 +This is a string that should not be truncated +SELECT * FROM (SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1) AS DERIVED_TABLE; +field1 +"This is a string that should not be truncated" +SELECT * FROM (SELECT JSON_UNQUOTE("This is a string that should not be truncated") AS field1) AS DERIVED_TABLE; +field1 +This is a string that should not be truncated +SELECT * FROM (SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1) AS DERIVED_TABLE; +field1 +This is a string that should not be truncated +# +# Bug#21296173 JSON_OBJECT('KEY', BOOLEAN_LITERAL) USES VALUES 0, 1 +# FOR BOOL WHEN USED VIA VIEW +# +SELECT JSON_OBJECT('key1', false, 'key2', true); +JSON_OBJECT('key1', false, 'key2', true) +{"key1": false, "key2": true} +SELECT JSON_ARRAY('key1', false, 'key2', true); +JSON_ARRAY('key1', false, 'key2', true) +["key1", false, "key2", true] +CREATE VIEW v1 AS SELECT JSON_OBJECT('key1', false, 'key2', true); +SELECT * FROM v1; +JSON_OBJECT('key1', false, 'key2', true) +{"key1": 0, "key2": 1} +CREATE VIEW v2 AS SELECT JSON_ARRAY('key1', false, 'key2', true); +SELECT * FROM v2; +JSON_ARRAY('key1', false, 'key2', true) +["key1", 0, "key2", 1] +drop view v1; +drop view v2; +# +# Bug#21293089 JSON_CONTAINS() RETURNS WRONG RESULT WITH EMPTY JSON ARRAY +# +SELECT JSON_CONTAINS('[]', '{"a" : 1}'); +JSON_CONTAINS('[]', '{"a" : 1}') +0 +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, 5]'); +JSON_CONTAINS('[]', '[1, 2, 3, 4, 5]') +0 +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, {"a" : 1}]'); +JSON_CONTAINS('[]', '[1, 2, 3, 4, {"a" : 1}]') +0 +SELECT JSON_CONTAINS('[]', '{"a" : [1, 2, 3, 4, 5]}'); +JSON_CONTAINS('[]', '{"a" : [1, 2, 3, 4, 5]}') +0 +SELECT JSON_CONTAINS('[]', '[]'); +JSON_CONTAINS('[]', '[]') +1 +# +# Bug#21377136 STACK OVERFLOW IN RAPIDJSON::GENERICREADER +# +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[', 100000)); +JSON_VALID(REPEAT('[', 100000)) +0 +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":', 100000)); +JSON_VALID(REPEAT('{"a":', 100000)) +0 +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":[', 100000)); +JSON_VALID(REPEAT('{"a":[', 100000)) +0 +error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[{"a":', 100000)); +JSON_VALID(REPEAT('[{"a":', 100000)) +0 +# +# Bug#21381806 JSON: ASSERTION FAILED: ARG->NULL_VALUE +# +SELECT JSON_SET(CASE WHEN 1 THEN NULL ELSE NULL END, '{}', '{}'); +JSON_SET(CASE WHEN 1 THEN NULL ELSE NULL END, '{}', '{}') +NULL +SELECT JSON_VALID(CASE WHEN 1 THEN NULL ELSE NULL END); +JSON_VALID(CASE WHEN 1 THEN NULL ELSE NULL END) +NULL +SELECT JSON_ARRAY(CASE WHEN 1 THEN NULL ELSE NULL END); +JSON_ARRAY(CASE WHEN 1 THEN NULL ELSE NULL END) +[null] +# +# Bug#21384048 ASSERTION FAILED: N >= 0 && N <= 308 +# IN RAPIDJSON::INTERNAL::FASTPATH +# +SELECT JSON_EXTRACT('-1E-36181012216111515851075235238', '$'); +JSON_EXTRACT('-1E-36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 33 +SELECT JSON_EXTRACT('1E-36181012216111515851075235238', '$'); +JSON_EXTRACT('1E-36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 32 +SELECT JSON_EXTRACT('1E-325', '$'); +JSON_EXTRACT('1E-325', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +SELECT JSON_EXTRACT('1E-324', '$'); +JSON_EXTRACT('1E-324', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +SELECT JSON_EXTRACT('1E-323', '$'); +JSON_EXTRACT('1E-323', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +SELECT JSON_EXTRACT('1E+308', '$'); +JSON_EXTRACT('1E+308', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+309', '$'); +JSON_EXTRACT('1E+309', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 6 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+36181012216111515851075235238', '$'); +JSON_EXTRACT('1E+36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 32 +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('-1E+36181012216111515851075235238', '$'); +JSON_EXTRACT('-1E+36181012216111515851075235238', '$') +NULL +Warnings: +Warning 4038 Syntax error in JSON text in argument 1 to function 'json_extract' at position 33 +# +# Bug#21383284: ASSERTION IN SELECT_LEX::SETUP_CONDS +# +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', 'too-long-escape'); +ERROR HY000: Incorrect arguments to ESCAPE +error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', JSON_EXTRACT('', '$')); +1 +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract' +# +# Bug#21442624 INCORRECT RESULT FROM JSON_SET WITH AUTO-WRAPPING +# +SELECT JSON_SET('1', '$', 100); +JSON_SET('1', '$', 100) +[1, 100] +SELECT JSON_SET('1', '$[0]', 100); +JSON_SET('1', '$[0]', 100) +[1, 100] +SELECT JSON_SET('1', '$[0][0]', 100); +JSON_SET('1', '$[0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +SELECT JSON_SET('1', '$[0][0][0]', 100); +JSON_SET('1', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +SELECT JSON_SET('[]', '$', 100); +JSON_SET('[]', '$', 100) +[, 100] +SELECT JSON_SET('[]', '$[0]', 100); +JSON_SET('[]', '$[0]', 100) +[, 100] +SELECT JSON_SET('[]', '$[0][0]', 100); +JSON_SET('[]', '$[0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +SELECT JSON_SET('[]', '$[0][0][0]', 100); +JSON_SET('[]', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +SELECT JSON_SET('[1]', '$', 100); +JSON_SET('[1]', '$', 100) +[1, 100] +SELECT JSON_SET('[1]', '$[0]', 100); +JSON_SET('[1]', '$[0]', 100) +[100] +SELECT JSON_SET('[1]', '$[0][0]', 100); +JSON_SET('[1]', '$[0][0]', 100) +[[1, 100]] +SELECT JSON_SET('[1]', '$[0][0][0]', 100); +JSON_SET('[1]', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +SELECT JSON_SET('[[1]]', '$', 100); +JSON_SET('[[1]]', '$', 100) +[[1], 100] +SELECT JSON_SET('[[1]]', '$[0]', 100); +JSON_SET('[[1]]', '$[0]', 100) +[100] +SELECT JSON_SET('[[1]]', '$[0][0]', 100); +JSON_SET('[[1]]', '$[0][0]', 100) +[[100]] +SELECT JSON_SET('[[1]]', '$[0][0][0]', 100); +JSON_SET('[[1]]', '$[0][0][0]', 100) +[[[1, 100]]] +SELECT JSON_SET('[[[1]]]', '$', 100); +JSON_SET('[[[1]]]', '$', 100) +[[[1]], 100] +SELECT JSON_SET('[[[1]]]', '$[0]', 100); +JSON_SET('[[[1]]]', '$[0]', 100) +[100] +SELECT JSON_SET('[[[1]]]', '$[0][0]', 100); +JSON_SET('[[[1]]]', '$[0][0]', 100) +[[100]] +SELECT JSON_SET('[[[1]]]', '$[0][0][0]', 100); +JSON_SET('[[[1]]]', '$[0][0][0]', 100) +[[[100]]] +SELECT JSON_REPLACE('1', '$', 100); +JSON_REPLACE('1', '$', 100) +1 +SELECT JSON_REPLACE('1', '$[0]', 100); +JSON_REPLACE('1', '$[0]', 100) +1 +SELECT JSON_REPLACE('1', '$[0][0]', 100); +JSON_REPLACE('1', '$[0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +SELECT JSON_REPLACE('1', '$[0][0][0]', 100); +JSON_REPLACE('1', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +SELECT JSON_REPLACE('[]', '$', 100); +JSON_REPLACE('[]', '$', 100) +[] +SELECT JSON_REPLACE('[]', '$[0]', 100); +JSON_REPLACE('[]', '$[0]', 100) +[] +SELECT JSON_REPLACE('[]', '$[0][0]', 100); +JSON_REPLACE('[]', '$[0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +SELECT JSON_REPLACE('[]', '$[0][0][0]', 100); +JSON_REPLACE('[]', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +SELECT JSON_REPLACE('[1]', '$', 100); +JSON_REPLACE('[1]', '$', 100) +[1] +SELECT JSON_REPLACE('[1]', '$[0]', 100); +JSON_REPLACE('[1]', '$[0]', 100) +[100] +SELECT JSON_REPLACE('[1]', '$[0][0]', 100); +JSON_REPLACE('[1]', '$[0][0]', 100) +[1] +SELECT JSON_REPLACE('[1]', '$[0][0][0]', 100); +JSON_REPLACE('[1]', '$[0][0][0]', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +SELECT JSON_REPLACE('[[1]]', '$', 100); +JSON_REPLACE('[[1]]', '$', 100) +[[1]] +SELECT JSON_REPLACE('[[1]]', '$[0]', 100); +JSON_REPLACE('[[1]]', '$[0]', 100) +[100] +SELECT JSON_REPLACE('[[1]]', '$[0][0]', 100); +JSON_REPLACE('[[1]]', '$[0][0]', 100) +[[100]] +SELECT JSON_REPLACE('[[1]]', '$[0][0][0]', 100); +JSON_REPLACE('[[1]]', '$[0][0][0]', 100) +[[1]] +SELECT JSON_REPLACE('[[[1]]]', '$', 100); +JSON_REPLACE('[[[1]]]', '$', 100) +[[[1]]] +SELECT JSON_REPLACE('[[[1]]]', '$[0]', 100); +JSON_REPLACE('[[[1]]]', '$[0]', 100) +[100] +SELECT JSON_REPLACE('[[[1]]]', '$[0][0]', 100); +JSON_REPLACE('[[[1]]]', '$[0][0]', 100) +[[100]] +SELECT JSON_REPLACE('[[[1]]]', '$[0][0][0]', 100); +JSON_REPLACE('[[[1]]]', '$[0][0][0]', 100) +[[[100]]] +# +# Bug#21828321: JSON FUNCS CALL DBUG_ABORT OR EXIT() ON WINDOWS! +# +SELECT JSON_ARRAY(LEAST(NULL, NULL), GREATEST(NULL, NULL), LEAST(j1, NULL), +GREATEST(NULL, j2), LEAST(j1, j2), GREATEST(j1, j2)) AS j +FROM (SELECT CAST('1' AS JSON) AS j1, CAST('2' AS JSON) AS j2) t; +j +[null, null, null, null, "1", "2"] diff --git a/mysql-test/suite/json/t/json_no_table.test b/mysql-test/suite/json/t/json_no_table.test new file mode 100644 index 00000000000..584af56a3a9 --- /dev/null +++ b/mysql-test/suite/json/t/json_no_table.test @@ -0,0 +1,2288 @@ +########### suite/json/t/json_notable.test # +# Tests json columns functionality that does not need any tables # +# to be defined (no storage engine functionality) # +# # +# This test copies some tests originally in json.test # +###################################################################### + +# Some extra checks for comparisons between positive and negative zero. +# All should be equal. +SELECT CAST(0.0e0 AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = CAST(-0.0e0 AS DECIMAL); +SELECT CAST(0.0e0 AS JSON) = CAST(-0.0e0 AS DECIMAL); +SELECT CAST(CAST(0 AS DECIMAL) AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS SIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = -0.0e0; +SELECT CAST(CAST(0 AS UNSIGNED) AS JSON) = CAST(-0.0e0 AS DECIMAL); + +# Test that CAST string argument isn't treated as ANY_JSON_ATOM +# in that a MySQL string needs to be parsed to JSON here; it is not +# auto-converted to a JSON string as in ANY_JSON_ATOM contexts. +select cast('"abc"' as json); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select cast('abc' as json); + +--echo +--echo # String literal - valid JSON +select JSON_VALID('123'); # uint +select JSON_VALID('-123'); # int +select JSON_VALID('5000000000'); # uint64 +select JSON_VALID('-5000000000'); # int64 +select JSON_VALID('1.23'); # double +select JSON_VALID('"123"'); +select JSON_VALID('true'); +select JSON_VALID('false'); +select JSON_VALID('null'); +select JSON_VALID('{"address": "Trondheim"}'); + +--echo +--echo # String literal - not valid JSON +select JSON_VALID('12 3'); + +--echo +--echo # String literal not in UTF-8 +set names 'ascii'; +# auto-convert to utf-8 +select JSON_VALID('123'); + +set names 'utf8'; + +--echo +--echo # Json expression +select JSON_VALID(cast('[123]' as JSON )); + +--echo +--echo # Json expression NULL +select JSON_VALID(cast(NULL as JSON )); + +--echo +--echo # Bare NULL +select JSON_VALID( NULL ); + +--echo +--echo # Function result - string +select JSON_VALID( UPPER('"abc"') ); + +set names 'latin1'; +--echo +--echo # Function result - string +# auto-convert to utf-8 +select JSON_VALID( UPPER('"abc"') ); + +set names 'utf8'; + +--echo +--echo # Function result - date, not valid as JSON without CAST +select JSON_VALID( CAST('2015-01-15' AS DATE) ); + +--echo +--echo # The date string doesn't parse as JSON text, so wrong: +select JSON_VALID( CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8') ); +--echo # OK, though: +select JSON_VALID( CAST(CURDATE() as JSON) ); + +--echo +--echo # Function result - NULL +select JSON_VALID( UPPER(NULL) ); +select JSON_VALID( UPPER(CAST(NULL as CHAR)) ); + +# examples from wl7909 spec +# returns 1 +SELECT JSON_VALID( '{ "firstName" : "Fred", "lastName" : "Flintstone" }' ); + +# returns 1 +SELECT JSON_VALID( '3' ); + +# returns NULL as IS JSON would +SELECT JSON_VALID( null ); + + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_CONTAINS_PATH function. +--echo # ---------------------------------------------------------------------- + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_contains_path(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_contains_path('{ "a": true }' ); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_contains_path('{ "a": true }', 'all' ); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_contains_path('{ "a": tru }', 'all', '$' ); +--echo error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$[' ); +--echo error ER_INVALID_JSON_PATH +select json_contains_path('{ "a": true }', 'all', '$a.***[3]' ); +--echo error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_contains_path('{ "a": true }', 'foo', '$.a' ); +--echo error ER_INVALID_JSON_CHARSET +select json_contains_path('{}', 'all', cast('$' as binary)); + +select json_contains_path(null, 'all', '$.a' ); +select json_contains_path('{ "a": true }', null, '$.a' ); +select json_contains_path('{ "a": true }', 'all', null ); + +# degenerate path +select json_contains_path('{ "a": true }', 'all', '$' ); + +# positive, one path +select json_contains_path('{ "a": true }', 'all', '$.a' ); +select json_contains_path('{ "a": true }', 'one', '$.a' ); + +# negative, one path +select json_contains_path('{ "a": true }', 'all', '$.b' ); +select json_contains_path('{ "a": true }', 'one', '$.b' ); + +# all +select json_contains_path('{ "a": true }', 'all', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'all', '$.b', '$.a' ); +select json_contains_path('{ "a": true }', 'ALL', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'aLl', '$.a', '$.b' ); + +# some +select json_contains_path('{ "a": true }', 'one', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'one', '$.b', '$.a' ); +select json_contains_path('{ "a": true }', 'ONE', '$.a', '$.b' ); +select json_contains_path('{ "a": true }', 'oNe', '$.a', '$.b' ); + +# some wildcards +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**[4]', '$**[5]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[2]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2, { "c": [ 4, 5, { "d": [ 6, 7, 8, 9, 10 ]} ] } ] }', 'all', '$**.c[3]' ); +select json_contains_path('{"a":1, "b":2}', 'one', '$.*'); +select json_contains_path('[1,2,3]', 'one', '$.*'); +select json_contains_path('{}', 'one', '$[*]'); + +# combine ellipsis and wildcard +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', + 'one', '$**.a.*'); +SELECT JSON_CONTAINS_PATH('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', + 'all', '$**.a.*'); +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'one', '$**[*]'); +SELECT JSON_CONTAINS_PATH('[1,2,3]', 'all', '$**[*]'); + +# 3 paths +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$**[1]', '$.b[0]', '$.c' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.c', '$**[1]', '$.b[0]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'all', '$.b[0]', '$.c', '$**[1]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$**[1]', '$.b[0]', '$.c' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.c', '$**[1]', '$.b[0]' ); +select json_contains_path('{ "a": true, "b": [ 1, 2 ] }', 'one', '$.b[0]', '$.c', '$**[1]' ); + +# examples from the wl7909 spec +# returns 0 because there is no element at $.a.c +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'all', + '$.a.c', + '$.b[1]' +); + +# returns 1 because there is an element at $.b[1] +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'one', + '$.a.c', + '$.b[1]' +); + +# returns 0 because there is no element at the given path +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'all', + '$.c' +); + +# returns 1 because there is an element at $.b[1].c.d +SELECT JSON_CONTAINS_PATH +( + '{ "a" : 123, "b" : [ 123, { "c" : { "d" : true } } ] }', + 'all', + '$.b[1].c.d' +); + +select json_length( null ); +select json_length( '1' ); +--echo +--echo # invalid json text +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_length( 'abc' ); +select json_length( '"abc"' ); +select json_length( 'true' ); +select json_length( 'false' ); +select json_length( 'null' ); + +select json_length( '{}' ); +select json_length( '{ "a" : 100, "b" : 200 }' ); +select json_length( '{ "a" : 100, "b" : [ 300, 400, 500 ] }' ); +select json_length( '[]' ); +select json_length( '[ null, "foo", true, 1.1 ]' ); +select json_length( '[ null, "foo", true, { "a" : "b", "c" : "d" } ]' ); +select json_length( '"foo"' ); +select json_length( '1.2' ); + + +# bad path expressions +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_length( 'true', 'c$' ); +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_length( '{ "foo" : [ true, false ] }', '$.foo[bar]' ); +--echo +--echo # wildcards not allowed in path expressions for this function +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.*' ); +--echo +--echo # wildcards not allowed in path expressions for this function +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_length( 'true', '$.foo**.bar' ); + +# json_length() with non-vacuous path expressions + +# 1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[0]' ); +# 3 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[1]' ); +# 1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); +# auto-wrapping: 1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); # auto-wrap scalar +select json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ); # ditto object + +# non-existent path: null +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ); +# 3 +select json_length( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); + +# examples from the wl7909 spec +# returns 0 +SELECT JSON_LENGTH +( + '{}' +); + +# returns 1 +SELECT JSON_LENGTH +( + '3' +); + +# returns 2 +SELECT JSON_LENGTH +( + '{ "a" : 123, "b" : [ 123, 456, 789 ] }' +); + +# returns 3 +SELECT JSON_LENGTH +( + '{ "a" : 123, "b" : [ 123, 456, 789 ] }', + '$.b' +); + +# returns null because the path does not exist +SELECT JSON_LENGTH +( + '{ "a" : 123, "b" : [ 123, 456, 789 ] }', + '$.c' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_DEPTH function. +--echo # ---------------------------------------------------------------------- +select json_depth(null); +select json_depth(cast(null as json)); +#select i, json_depth(j) from t1; +select json_depth(cast('[]' as json)), + json_depth(cast('{}' as json)), + json_depth(cast('null' as json)), + json_depth(json_quote('foo')); +select json_depth(cast('[[2], 3, [[[4]]]]' as json)); +select json_depth(cast('{"a": {"a1": [3]}, "b": {"b1": {"c": {"d": [5]}}}}' as json)); + +# examples from the wl7909 spec +# returns 1 +SELECT JSON_DEPTH +( + '{}' +); + +# returns 1 +SELECT JSON_DEPTH +( + '[]' +); + +# returns 1 +SELECT JSON_DEPTH( '"abc"' ); + +# returns 1 +SELECT JSON_DEPTH( CAST( '"abc"' AS JSON ) ); + +--echo error ER_INVALID_TYPE_FOR_JSON +SELECT JSON_DEPTH( 1 ); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH( 'abc' ); + +# returns 1 +SELECT JSON_DEPTH( CAST( 1 AS JSON ) ); + +# returns 2 +SELECT JSON_DEPTH +( + '{ "a" : true, "b" : false, "c" : null }' +); + +# returns 2 +SELECT JSON_DEPTH +( + '[ "a", true, "b" , false, "c" , null ]' +); + +# returns 2 +SELECT JSON_DEPTH +( + '{ "a" : true, "b" : {}, "c" : null }' +); + +# returns 2 +SELECT JSON_DEPTH +( + '[ "a", true, "b" , {}, "c" , null ]' +); + +# returns 3 +SELECT JSON_DEPTH +( + '{ "a" : true, "b" : { "e" : false }, "c" : null }' +); + +# returns 3 +SELECT JSON_DEPTH +( + '[ "a", true, "b" , { "e" : false }, "c" , null ]' +); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_DEPTH +( + '[ "a", true, "b" , { "e" : false }, "c" , null' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_REMOVE function. +--echo # ---------------------------------------------------------------------- + +# null args +select json_remove( null, '$[1]' ); +select json_remove( null, '$[1]' ) is null; +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ); +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ); +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', null ) is null; + +# too few args + +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_remove(); +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]' ); +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_remove( '$[1]' ); + +# malformed args +--echo +--echo # invalid json text +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ', '$[1]', '$[2]' ); +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1', '$[2]' ); +--echo +--echo # invalid json path +--echo error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]', '$[2' ); +--echo +--echo # Vacuous path expression +--echo error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$' ); +--echo +--echo # Vacuous path expression +--echo error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$', '$[2]' ); +--echo +--echo # Vacuous path expression +--echo error ER_JSON_VACUOUS_PATH +select json_remove( '[ 1, 2, 3 ]', '$[1]', '$' ); + +# wildcard/ellipsis not allowed in paths +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[*]' ); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$**[2]' ); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$[*]' ); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ 1, 2, 3 ]', '$[2]', '$**[2]' ); + +# simple matches + +select json_remove( '[ 1, 2, 3 ]', '$[0]' ); +select json_remove( '[ 1, 2, 3 ]', '$[1]' ); +select json_remove( '[ 1, 2, 3 ]', '$[2]' ); +select json_remove( '[ 1, 2, 3 ]', '$[3]' ); +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$[1]' ); + +# one match nested inside another +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": { "a": true } } ]', '$**.a' ); + +# multiple paths +select json_remove( '[ { "a": true }, { "b": false }, { "c": null }, { "a": null } ]', '$[0].a', '$[2].c' ); + +# ellipsis with matches at different levels +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_remove( '[ { "a": true }, { "b": [ { "c": { "a": true } } ] }, { "c": null }, { "a": null } ]', '$**.a' ); + +# nonsense path +select json_remove( '{"id": 123, "name": "systemQA", "array": [1, 2, 3]}', '$[0]' ); + +# examples from wl7909 spec +# returns the document {"a": "foo", "b": [true]} +SELECT JSON_REMOVE +( + '{"a" : "foo", "b" : [true, {"c" : 123}]}', + '$.b[ 1 ]' +); + +# returns {"a": "foo", "b": [true, {}]} due to normalization +SELECT JSON_REMOVE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.b[ 1 ].c' +); + +# returns {"a": "foo", "b": [true, {}]} +SELECT JSON_REMOVE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c' +); + +# returns the original document because the path doesn't identify an element +SELECT JSON_REMOVE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "d" : 456 } ] }', + '$.b[ 1 ].e' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_MERGE function. +--echo # ---------------------------------------------------------------------- + +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_merge(); +--echo +--echo # not enough args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_merge( '[ 1, 2, 3 ]' ); + +# null args result in NULL value +select json_merge( null, null ); +select json_merge( null, '[ 1, 2, 3 ]' ); +select json_merge( '[ 1, 2, 3 ]', null ); +select json_merge( null, '[ 1, 2, 3 ]', '[ 4, 5, 6 ]' ); +select json_merge( '[ 1, 2, 3 ]', null, '[ 4, 5, 6 ]' ); +select json_merge( '[ 1, 2, 3 ]', '[ 4, 5, 6 ]', null ); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2]', '[3, 4' ); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_merge( '[1, 2', '[3, 4]' ); + +# good json_merge() expressions +select json_merge( '1', '2' ); +select json_merge( '1', '[2, 3]' ); +select json_merge( '[1, 2]', '3' ); +select json_merge( '1', '{ "a": 2 }' ); +select json_merge( '{ "a": 2 }', '1' ); +select json_merge( '[1, 2]', '[3, 4]' ); +select json_merge( '{ "a": 2 }', '{ "b": 3}' ); +select json_merge( '[1, 2]', '{ "a": 2 }' ); +select json_merge( '{ "a": 2 }', '[1, 2]' ); + +select json_merge( '{"a": 1, "b": 2 }', '{"b": 3, "d": 4 }' ); +select json_merge( '{"a": 1, "b": 2 }', '{"b": [3, 4], "d": 4 }' ); +select json_merge( '{"a": 1, "b": [2, 3] }', '{"b": 4, "d": 4 }' ); +select json_merge( '{"a": 1, "b": 2 }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": 2 }' ); +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": [10, 11], "d": 4 }' ); +select json_merge( '{"a": 1, "b": [2, 9] }', '{"b": {"e": 7, "f": 8}, "d": 4 }' ); +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{"a": 1, "b": [2, 9] }' ); +select json_merge( '{"b": {"e": 7, "f": 8}, "d": 4 }', '{ "a": 1, "b": {"e": 20, "g": 21 } }' ); + +select json_merge( '1', '2', '3' ); +select json_merge( '[1, 2 ]', '3', '[4, 5]' ); +select json_merge +( + '{ "a": true, "b": { "c": 3, "d": 4 }, "e": [ 1, 2 ] }', + '{ "d": false, "b": { "g": 3, "d": 5 }, "f": [ 1, 2 ] }', + '{ "m": true, "b": { "h": 8, "d": 4 }, "e": [ 3, 4 ] }' +); + +# examples from the wl7909 spec +# returns [{"a": "foo", "b": [true, {"c": 123}]}, 5, 6] +SELECT JSON_MERGE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '[ 5, 6]' +); + +# returns {"a": "foo", "b": [true, {"c": 123}, false, 34]} +SELECT JSON_MERGE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '{ "b": [ false, 34 ] }' +); + +# returns {"a": "foo", "b": [true, {"c": 123}, "bar"]} +SELECT JSON_MERGE +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '{ "b": "bar" }' +); + +# returns {"a": {"b": 1, "c": 1}} +SELECT JSON_MERGE +( + '{ "a" : { "b" : 1 } }', + '{ "a" : { "c" : 1 } }' +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_TYPE function. +--echo # ---------------------------------------------------------------------- + +# negative test +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type('abc'); + +#select i, json_type(j) from t1; +select json_type('{"a": 2}'); +select json_type('[1,2]'); +select json_type('"scalar string"'); +select json_type('true'); +select json_type('false'); +select json_type('null'); +select json_type('1'); +select json_type('-0'); +select json_type('-0.0'); +--echo error ER_INVALID_TYPE_FOR_JSON +select json_type(-1); +--echo error ER_INVALID_TYPE_FOR_JSON +select json_type(CAST(1 AS UNSIGNED)); +select json_type('32767'); +--echo error ER_INVALID_TYPE_FOR_JSON +select json_type(PI()); +select json_type('3.14'); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_type(CAST(CAST('2015-01-15' AS DATE) as CHAR CHARACTER SET 'utf8')); + +--echo # ---------------------------------------------------------------------- +--echo # Test of CAST(literal AS JSON) +--echo # ---------------------------------------------------------------------- +select json_type(cast(cast('2014-11-25 18:00' as datetime) as json)); +select json_type(cast(cast('2014-11-25' as date) as json)); +select json_type(cast(cast('18:00:59' as time) as json)); +# select json_type(cast(cast('2014-11-25 18:00' as timestamp) as json)); -- cast target type not supported + +# select json_type(cast(cast('1999' as year) as json)); -- cast target type not supported +select json_type(cast(127 as json)); +select json_type(cast(255 as json)); +select json_type(cast(32767 as json)); +select json_type(cast(65535 as json)); +select json_type(cast(8388607 as json)); +select json_type(cast(16777215 as json)); +select json_type(cast(2147483647 as json)); +select json_type(cast(4294967295 as json)); +select json_type(cast(9223372036854775807 as json)); +select json_type(cast(18446744073709551615 as json)); +select json_type(cast(true as json)); +select json_type(cast(b'10101' as json)); + +select json_type(cast(cast(3.14 as decimal(5,2)) as json)); +select json_type(cast(3.14 as json)); +select json_type(cast(3.14E30 as json)); +# select json_type(cast(cast(3.14 as numeral(5,2)) as json)); -- cast target type not supported + +# select json_type(cast(cast(3.14 as double) as json)); -- cast target type not supported +# select json_type(cast(cast(3.14 as float) as json)); -- cast target type not supported + +# select json_type(cast(cast(b'10101' as bit(10)) as json)); -- cast target type not supported +# select json_type(cast(cast('10101abcde' as blob) as json)); -- cast target type not supported +select json_type(cast(cast('10101abcde' as binary) as json)); + +# select json_type(cast(cast('a' as enum('a','b','c')) as json)); -- cast target type not supported +# select json_type(cast(cast('a,c' as set('a','b','c')) as json)); -- cast target type not supported + +select json_type(cast(ST_GeomFromText('POINT(1 1)') as json)); +select json_type(cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json)); +select json_type(cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json)); +select json_type(cast(null as json)); +select json_type(cast(null as json)) is null; # check that it is an SQL NULL +select json_type(null) is null; # is an SQL NULL + +# +# same, but now show the printable value: +# +select cast(cast('2014-11-25 18:00' as datetime) as json); +select cast(cast('2014-11-25' as date) as json); +select cast(cast('18:00:59' as time) as json); +# select cast(cast('2014-11-25 18:00' as timestamp) as json); -- cast target type not supported + +# select cast(cast('1999' as year) as json); -- cast target type not supported +select cast(127 as json); +select cast(255 as json); +select cast(32767 as json); +select cast(65535 as json); +select cast(8388607 as json); +select cast(16777215 as json); +select cast(2147483647 as json); +select cast(4294967295 as json); +select cast(9223372036854775807 as json); +select cast(18446744073709551615 as json); +select cast(true as json); +select cast(b'10101' as json); + +select cast(cast(3.14 as decimal(5,2)) as json); +select cast(3.14 as json); +select cast(3.14e0 as json); +# select cast(cast(3.14 as numeral(5,2)) as json); -- cast target type not supported + +# select cast(cast(3.14 as double) as json); -- cast target type not supported +# select cast(cast(3.14 as float) as json); -- cast target type not supported + +# select cast(cast(b'10101' as bit(10) as json); -- cast target type not supported +# select cast(cast('10101abcde' as blob) as json); -- cast target type not supported +select cast(cast('10101abcde' as binary) as json); + +# select cast(cast('a' as enum('a','b','c') as json); -- cast target type not supported +# select cast(cast('a,c' as set('a','b','c') as json); -- cast target type not supported + +select cast(ST_GeomFromText('POINT(1 1)') as json); +select cast(ST_GeomFromText('LINESTRING(0 0,1 1,2 2)') as json); +select cast(ST_GeomFromText('POLYGON((0 0,10 0,10 10,0 10,0 0), + (5 5,7 5,7 7,5 7, 5 5))') as json); +select cast(null as json); +select cast(null as json) is null; # check that it is an SQL NULL + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_KEYS function. +--echo # ---------------------------------------------------------------------- +# should all give NULL: +select json_keys(NULL); +select json_keys(NULL, '$.b'); +select json_keys(NULL, NULL); +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', NULL); + +# non NULL results +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}'); +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.b'); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_keys('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*.b'); + +# Examples from the specification +--echo # returns [ "a", "b" ] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }'); + +--echo # returns [] +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.b[1].c'); + +--echo # returns NULL +SELECT JSON_KEYS('{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.a.b[2]'); + +--echo error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010'); +--echo error ER_INVALID_JSON_PATH +SELECT JSON_KEYS('{"a":1}', '1010') IS NULL; + +# examples from the wl7909 spec +# returns [ "a", "b" ] +SELECT JSON_KEYS +( + '{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }' +); + +# returns [] +SELECT JSON_KEYS +( + '{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.b[1].c' +); + +# returns NULL +SELECT JSON_KEYS +( + '{ "a" : "foo", "b" : [ true, { "c" : {} } ] }', + '$.a.b[2]' +); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_KEYS(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_KEYS('{}', '$', '$'); + +--echo # ---------------------------------------------------------------------- +--echo # CAST( AS CHAR). See also 'json_conversions.test' for other +--echo # conversion tests. +--echo # ---------------------------------------------------------------------- +select cast(json_keys('{"a": 1}') as char); +select cast(cast(1 as json) as char); +select cast(json_keys(NULL) as char); +#select cast(j as char) from keys1; + +--echo # ---------------------------------------------------------------------- +--echo # Path matching with double-quotes +--echo # ---------------------------------------------------------------------- + +# matches +select json_extract( '{ "one potato" : 1 }', '$."one potato"' ); +# matches +select json_extract( '{ "a.b" : 1 }', '$."a.b"' ); + +# doesn't match +select json_extract( '{ "\\"a\\"": 1}', '$."a"' ); +# matches +select json_extract( '{ "\\"a\\"": 1}', '$."\\"a\\""' ); +# matches +select json_extract( '{ "a": 1}', '$."a"' ); +# matches +select json_extract( '{ "a": 1}', '$.a' ); + +# examples from functional spec section on Path Syntax + +# [3, 2] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0]' ); +# 2 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[0][1]' ); +# [ { "c": "d" }, 1 ] +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1]' ); +# { "c": "d" } +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0]' ); +# "d" +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.a[1][0].c' ); +# 7 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."one potato"' ); +# 6 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$.b.c' ); +# 8 +select json_extract( '{ "a": [ [ 3, 2 ], [ { "c" : "d" }, 1 ] ], "b": { "c" : 6 }, "one potato": 7, "b.c" : 8 }', '$."b.c"' ); + + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_EXTRACT function. +--echo # ---------------------------------------------------------------------- + +# errors +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_extract(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_extract('$.b'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}'); + +# Confused argument order +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_extract('$.a', '{"a": 1, "b": {"e": "foo", "b": 3}}'); + +# NULLs +select json_extract(NULL, '$.b'); +select json_extract(NULL, NULL); + +# non-NULLs +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a'); +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.*'); +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', '$.b.e'); +select json_extract('{"a": 1, "b": [1,2,3]}', '$.b[2]'); +# one path is NULL +select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL); + +# Examples from the specification +--echo # returns a JSON value containing just the string "123" +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', + '$.b[ 1 ].c'); + +--echo # returns a JSON value containing just the number 123 +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c'); + +--echo # raises an error because the document is not valid +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('{ "a" : [ }', + '$.b[ 1 ].c'); + +--echo # raises an error because the path is invalid +--echo error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].'); + +--echo # returns a JSON value containing the number 123 (because of +--echo # auto-wrapping the scalar) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 0 ]'); +--echo # returns a JSON value containing the object because of auto-wrapping +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : {"not array": 4} } ] }', + '$.b[ 1 ].c[ 0 ]'); + +--echo # returns null because the path, although valid, does not identify a value +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 1 ]'); + +--echo # returns a JSON value containing the number 123 (due to normalization) +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.b[ 1 ].c'); + +--echo # returns a JSON array [ "foo", true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.a', '$.b[0]'); + +--echo # returns a JSON array [ true ] +SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.d', '$.b[0]'); + +# some examples verifying ellipsis behavior + +# should have same result +select json_extract( '[1]', '$[0][0]' ); +select json_extract( '[1]', '$**[0]' ); + +# should have same result +select json_extract( '{ "a": 1 }', '$.a[0]' ); +select json_extract( '{ "a": 1 }', '$**[0]' ); + +# should have same result +select json_extract( '{ "a": 1 }', '$[0].a' ); +select json_extract( '{ "a": 1 }', '$**.a' ); + +# should have same result +select json_extract( '{ "a": 1 }', '$[0].a[0]' ); +select json_extract( '{ "a": 1 }', '$**[0]' ); + +# should have the same result +select json_extract( '{ "a": 1 }', '$[0].a' ); +select json_extract( '{ "a": 1 }', '$**.a' ); +select json_extract( '{ "a": 1 }', '$[0][0].a' ); +select json_extract( '{ "a": 1 }', '$[0][0][0].a' ); + +# should have the same result +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', '$**.a.*'); +SELECT JSON_EXTRACT('[1, [[{"x": [{"a":{"b":{"c":42}}}]}]]]', + '$[1][0][0].x[0].a.*'); + +# examples from the wl7909 spec +# returns a JSON value containing just the string "123" +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', + '$.b[ 1 ].c' +); + +# returns a JSON value containing just the number 123 +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c' +); + +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT +( + '{ "a" : [ }', + '$.b[ 1 ].c' +); + +--echo error ER_INVALID_JSON_PATH +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].' +); + +# returns a JSON value containing the number 123 (because of auto-wrapping) +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 0 ]' +); + +# returns null because the path, although valid, does not identify a value +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123 } ] }', + '$.b[ 1 ].c[ 1 ]' +); + +# returns a JSON value containing the number 123 (due to normalization) +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.b[ 1 ].c' +); + +# returns a JSON array ["foo", true] +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.a', '$.b[0]' +); + +# returns a the 'true' literal +SELECT JSON_EXTRACT +( + '{ "a" : "foo", "b" : [ true, { "c" : 123, "c" : 456 } ] }', + '$.d', '$.b[0]' +); + +# should return NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].b' ) jdoc; + +# should return NULL +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].b' ) jdoc; + +# should return 1 +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[0].a' ) jdoc; + +# should return [1, 2] +select json_extract( '[ { "a": 1 }, { "a": 2 } ]', '$[*].a' ) jdoc; + +# should return [1] +select json_extract( '[ { "a": 1 }, { "b": 2 } ]', '$[*].a' ) jdoc; + +# should return [3, 4] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a' ) jdoc; + +# should return [[3, 4]] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[*].a' ) jdoc; + +# should return [[3, 4]] +select json_extract( '[ { "a": [3,4] }, { "b": 2 } ]', '$[0].a', '$[1].a' ) jdoc; + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_ARRAY_APPEND function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_array_append(NULL, '$.b', cast(1 as json)); +select json_array_append('[1,2,3]', NULL, cast(1 as json)); +select json_array_append('[1,2,3]', '$', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_append(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_append(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_append(NULL, NULL, NULL, NULL); + +# auto-wrap +SELECT JSON_ARRAY_APPEND(cast('1' as json), '$', 3); +SELECT JSON_ARRAY_APPEND(cast('{"a": 3}' as json), '$', 3); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append(cast('{"a": {"b": [3]}}' as json), '$**[0]', 6); + +# Examples from the specification + +--echo # Auto-wrapping, since because the paths identify scalars. +--echo # should return {"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a": "foo", "b": "bar", "c": "wibble"}', + '$.b', cast(4 as json), + '$.c', cast('"grape"' as json)); + +--echo # should return {"a": "foo", "b": [1, 2, 3, 4], +--echo # "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', + '$.b', cast(4 as json), + '$.c', cast('"grape"' as json)); + +# without CAST: cf. not required for ANY_JSON_ATOM arguments in specification +SELECT JSON_ARRAY_APPEND('{"a" : "foo","b": [1, 2, 3], "c": ["apple", "pear"]}', + '$.b', 4, + '$.c', 'grape'); + +# wild cards, multiple pairs +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], [], []]', '$[*]', 3, '$[*]', 4); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_array_append( '[[], "not array", []]', '$[*]', 3, '$[*]', 4); + +# examples from wl7909 spec +# should return {"a": "foo", "b": ["bar", 4], "c": ["wibble", "grape"]} due to autowrapping +SELECT JSON_ARRAY_APPEND +( + '{ "a" : "foo", "b" : "bar", "c" : "wibble" }', + '$.b', 4, + '$.c', "grape" +); + +# should return {"a": "foo", "b": [1, 2, 3, 4], "c": ["apple", "pear", "grape"]} +SELECT JSON_ARRAY_APPEND +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ "apple", "pear" ] }', + '$.b', 4, + '$.c', "grape" +); + +--echo # ---------------------------------------------------------------------- +--echo # Bug#21373874 ASSERTION `PARENT' FAILED +--echo # ---------------------------------------------------------------------- + +select json_array_append('{"a":1}', '$[0]', 100); +select json_array_append('3', '$[0]', 100); +select json_array_append('3', '$[0][0][0][0]', 100); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_INSERT function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_insert(NULL, '$.b', cast(1 as json)); +select json_insert('[1,2,3]', NULL, cast(1 as json)); +select json_insert('[1,2,3]', '$[3]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_insert(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_insert(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_insert(NULL, NULL, NULL, NULL); + +# positive test cases + +select json_insert('[1,2,3]', '$[2]', 4); +select json_insert('[1,2,3]', '$[3]', 4); +select json_insert('[1,2,3]', '$[10]', 4); + +select json_insert('{"c":4}', '$.c', 4); +select json_insert('{"c":4}', '$.a', 4); + +select json_insert('1', '$', 4); +select json_insert('1', '$[0]', 4); +select json_insert('1', '$[1]', 4); +select json_insert('1', '$[10]', '4', '$[11]', 5); + +select json_insert('[1,2,3]', '$[2][0]', 4); +select json_insert('[1,2,3]', '$[2][2]', 4); + +select json_insert('{"a": 3}', '$.a[0]', 4); +select json_insert('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); + +# wild card & auto-wrap (scalars) +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": [1], "b": 2}' as json), '$.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": 1, "b": 2}' as json), '$.*[1]', 6); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$.a.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$.a.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": 3}}' as json), '$**[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$[*][1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1]' as json), '$**[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$[*][1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[1, [2], 3]' as json), '$**[1]', 6); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$[*][1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert(cast('[[1]]' as json), '$**[1]', 6); + +# auto-wrap object +select json_insert(cast('{"a": 3}' as json), '$[1]', 6); + + +# Examples from the specification + +# returns the original document because the path does exist +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a', true); + +# inserts a number, returns '{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : 123 } +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', 123); + +# inserts a string, returns '{ "a" : "foo", "b" : [ 1, 2, 3 ], "c" : "123" } +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.c', '123'); + +# returns '{ "a" : [ "foo", true ], "b" : [ 1, 2, 3 ] }' +SELECT JSON_INSERT('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[1]', true); + +# should return { "a" : "foo", "b": true } +SELECT JSON_INSERT('{ "a" : "foo"}', '$.b', true, '$.b', false); + +# examples from the wl7909 spec +# returns the original document because the path does exist +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + true +); + +# inserts a number, returns '{"a": "foo", "b": [1, 2, 3], "c": 123} +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + 123 +); + +# inserts a string, returns '{"a": "foo", "b": [1, 2, 3], "c": "123"} +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + '123' +); + +# returns '{"a": ["foo", true], "b": [1, 2, 3]}' +SELECT JSON_INSERT +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a[1]', + true +); + +# returns {"a": "foo", "b": true} +SELECT JSON_INSERT +( + '{ "a" : "foo"}', + '$.b', true, + '$.b', false +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_ARRAY_INSERT function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_array_insert(NULL, '$.b[1]', 1); +select json_array_insert('[1,2,3]', NULL, 1); +select json_array_insert('[1,2,3]', '$[3]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_insert(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_insert(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_array_insert(NULL, NULL, NULL, NULL); + +# path does not indicate a cell position +--echo error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$', 1); +--echo error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a', 1); +--echo error ER_INVALID_JSON_PATH_ARRAY_CELL +select json_array_insert('true', '$.a[1].b', 1); + +# nop if there is no array at the path's parent +select json_array_insert( 'true', '$[0]', false ); +select json_array_insert( 'true', '$[1]', false ); +select json_array_insert( '{ "a": true }', '$.a[0]', false ); +select json_array_insert( '{ "a": true }', '$.a[1]', false ); + +# positive tests +select json_array_insert( '[]', '$[0]', false ); +select json_array_insert( '[]', '$[1]', false ); +select json_array_insert( '[true]', '$[0]', false ); +select json_array_insert( '[true]', '$[1]', false ); +select json_array_insert( '[true]', '$[2]', false ); +select json_array_insert( '{ "a": [] }', '$.a[0]', false ); +select json_array_insert( '{ "a": [] }', '$.a[1]', false ); +select json_array_insert( '{ "a": [true] }', '$.a[0]', false ); +select json_array_insert( '{ "a": [true] }', '$.a[1]', false ); +select json_array_insert( '{ "a": [true] }', '$.a[2]', false ); + +# insert into the middle of an array +select json_array_insert( '[1, 2, 3, 4]', '$[0]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[1]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[2]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[3]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[4]', false ); +select json_array_insert( '[1, 2, 3, 4]', '$[5]', false ); + +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[0]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[1]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[2]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[3]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[4]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.a[5]', false ); + +# nop +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[0]', false ); +select json_array_insert( '{ "a": [1, 2, 3, 4] }', '$.b[1]', false ); + +# no auto-wrapping +select json_array_insert( '"a"', '$[0]', true ); +select json_array_insert( '[ "a" ]', '$[0][0]', true ); +select json_array_insert( '"a"', '$[1]', true ); + +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$.a.*[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$**[1]', 6); +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_insert('[]', '$[*][1]', 6); + +# multiple paths, +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', true, '$[1]', false ); +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', + cast( '[ "a", "b", "c", "d" ]' as json ), '$[1][2]', false ); + +# test an error while evaluating the document expression +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_ARRAY_INSERT(JSON_EXTRACT('[1', '$'), '$[0]', 1); + +# error in reading new value +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +select json_array_insert( '[ 1, 2, 3 ]', '$[1]', json_extract( '[', '$' ) ); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_SET function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_set(NULL, '$.b', cast(1 as json)); +select json_set('[1,2,3]', NULL, cast(1 as json)); +select json_set('[1,2,3]', '$[3]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_set(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_set(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_set(NULL, NULL, NULL, NULL); + +# Detect errors in nested function calls. +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_SET('{}', '$.name', JSON_EXTRACT('', '$')); + +# positive test cases + +select json_set('[1,2,3]', '$[2]', 4); +select json_set('[1,2,3]', '$[3]', 4); +select json_set('[1,2,3]', '$[10]', 4); + +select json_set('{"c":4}', '$.c', 5); +select json_set('{"c":4}', '$.a', 5); + +select json_set('1', '$', 4); +select json_set('1', '$[0]', 4); +select json_set('1', '$[1]', 4); +select json_set('1', '$[10]', '4', '$[11]', 5); + +select json_set('[1,2,3]', '$[2][0]', 4); +select json_set('[1,2,3]', '$[2][2]', 4); + +select json_set('{"a": 3}', '$.a[0]', 4); +select json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); + +# auto-wrap plus ellipsis with nested hits should give: {"a": [{"b": [3, 6]}, 6]} +--echo error ER_INVALID_JSON_PATH_WILDCARD +select json_set(cast('{"a": {"b": [3]}}' as json), '$**[1]', 6); + +# Examples from the specification: Include when missing functions are +# available. + +# returns { "a" : {}, "b" : [ 1, 2, 3 ] } + SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + JSON_OBJECT()); + +# # returns { "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ true, false ] } +# SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +# '$.c', +# JSON_ARRAY( true, false )); + +# # returns { "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ true, false ] } +# SELECT JSON_SET('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', +# '$.c', +# JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) )); + +# # returns [ 1, null, null, 2 ] +# SELECT JSON_SET('1', '$[3]', 2); + +# should return { "a": { "b": false, "c": true } } +SELECT JSON_SET('{ "a" : "foo"}', '$.a', + JSON_OBJECT( 'b', false ), '$.a.c', true); + +# returns { "a" : {}, "b" : [ 1, 2, 3 ] } +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + cast('{}' as json)); + +# returns { "a" : "foo", "b" : [ 1, 2, 3 ], "c" : [ true, false ] } +select json_set('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + cast('[true, false]' as json)); + +# returns [ 1, null, null, 2 ] +select json_set('1', '$[3]', 2); + +# should return { "a": { "b": false, "c": true } } +select json_set('{ "a" : "foo"}', '$.a', + cast('{"b": false}' as json), '$.a.c', true); + +# examples from wl7909 spec +# returns {"a": {}, "b": [1, 2, 3]} +SELECT JSON_SET +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a', + JSON_OBJECT() +); + +# returns {"a": "foo", "b": [1, 2, 3], "c": [true, false]} +SELECT JSON_SET +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + JSON_ARRAY( true, false ) +); + +# returns {"a": "foo", "b": [1, 2, 3], "c": [true, false]} +SELECT JSON_SET +( + '{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + JSON_ARRAY( CAST( 'true' AS JSON ), CAST( 'false' AS JSON ) ) +); + +# returns [1, 2] +SELECT JSON_SET +( + '1', + '$[3]', + 2 +); + +# returns {"a": {"b": false, "c": true}} +SELECT JSON_SET +( + '{ "a" : "foo"}', + '$.a', JSON_OBJECT( 'b', false ), + '$.a.c', true +); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_REPLACE function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_replace(NULL, '$.b', cast(1 as json)); +select json_replace('[1,2,3]', NULL, cast(1 as json)); +select json_replace('[1,2,3]', '$[2]', NULL); + +# wrong # args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_replace(NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_replace(NULL, NULL); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_replace(NULL, NULL, NULL, NULL); + +# positive test cases + +select json_replace('[1,2,3]', '$[2]', 4); +select json_replace('[1,2,3]', '$[3]', 4); +select json_replace('[1,2,3]', '$[10]', 4); + +select json_replace('{"c":4}', '$.c', 5); +select json_replace('{"c":4}', '$.a', 5); + +select json_replace('1', '$', 4); +select json_replace('1', '$[0]', 4); +select json_replace('1', '$[1]', 4); +select json_replace('1', '$[10]', '4', '$[11]', 5); + +select json_replace('[1,2,3]', '$[2][0]', 4); +select json_replace('[1,2,3]', '$[2][2]', 4); + +select json_replace('{"a": 3}', '$.a[0]', 4); +select json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); + + +# Examples from the specification + +# returns the original document because the path doesn't exist +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.c', + true); + +# returns '{ "a" : true, "b" : [ 1, 2, 3 ] }' +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.a[0]', + true); + +# returns the original document because the path doesn't exist +SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', + '$.b[5]', + true); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_ARRAY function. +--echo # ---------------------------------------------------------------------- + +# NULLs +select json_array(NULL, '$.b', cast(1 as json)); +select json_array('[1,2,3]', NULL, cast(1 as json)); +select json_array('[1,2,3]', '$[3]', NULL); + + +# positive test cases +select json_array(); +select json_array(3.14); +select json_array('[1,2,3]'); +select json_array(cast('[1,2,3]' as json)); +select json_array(1,2,3); +select json_array(b'0', b'1', b'10'); + +# returns the empty array: [] +SELECT JSON_ARRAY(); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_OBJECT function. +--echo # ---------------------------------------------------------------------- + +# odd number of args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_object( 'a' ); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_object( 'a', 1, 'b' ); + +# null arg +--echo error ER_JSON_DOCUMENT_NULL_KEY +select json_object( null, 1 ); + +# positive tests +select json_object(); +select json_object( 'a', null ); +select json_object( 'a', 1 ); +select json_object( 'a', 1, 'b', 'foo' ); +select json_object( 'a', 1, 'b', 'foo', 'c', cast( '{ "d": "wibble" }' as json ) ); +select json_object( 'a', true, 'b', false, 'c', cast( 'null' as json) ); +select json_valid( json_object( '"a"', 1 ) ); + +# long key +select json_object( REPEAT('a', 64 * 1024), 1 ); + +# non-string keyNames are cast to CHAR +select json_object(json_array(), json_array()); +select json_object( cast(json_array() as char), json_array()); + +select json_object( 1, json_array()); +select json_object( cast(1 as char), json_array()); + +# returns the empty object: {} +SELECT JSON_OBJECT(); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_SEARCH function. +--echo # ---------------------------------------------------------------------- + +# wrong number of args +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_search(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_search( '{ "a": true }' ); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_search( '{ "a": true }', 'one' ); + +# null args +select json_search( null, 'one', 'foo' ); +select json_search( '{ "a": "foo" }', null, 'foo' ); +# FIXME. what should happen here? +#select json_search( '{ "a": "foo" }', 'one', null ); +select json_search( '{ "a": "foo" }', 'one', 'foo', null, null ); +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$.a', null ); + +# bad values for the oneOrAll arg +--echo error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'twof', 'foo' ); +--echo error ER_JSON_BAD_ONE_OR_ALL_ARG +select json_search( '{ "a": "foo" }', 'two', 'foo' ); + +# bad escape arg +--error ER_WRONG_ARGUMENTS +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); + +# bad path args +--echo error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'one', 'foo', null, '$a' ); +--echo error ER_INVALID_JSON_PATH +select json_search( '{ "a": "foo" }', 'all', 'foo', null, '$.a', '$b' ); + +--error ER_BAD_FIELD_ERROR +select json_search(a, b, c); + +# simple tests for search without path arguments +select json_search( '{ "a": "foobar" }', 'one', 'foo%' ); +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'one', 'foo%' ); +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'foo%' ); +select json_search( '{ "a": "foobar", "b": "focus", "c": [ "arm", "foot", "shoulder" ] }', 'all', 'f__us' ); + +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'all', 'foo%', null, '$.a', '$.b' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'one', 'foo%', null, '$.a', '$.b' ); + +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ALL', 'foo%', null, '$.a' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'aLl', 'foo%', null, '$.a', '$.b' ); +select json_search( '{ "a": [ "foolish", "folly", "foolhardy" ], "b" : "fool" }', 'ONE', 'foo%', null, '$.a', '$.b' ); + +# wildcards in the path expression +select json_search +( + '[ { "a": { "b": { "c": "fool" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "food"} } ]', + 'all', + 'foo%', + null, + '$**.c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', + 'all', + 'sho%', + null, + '$**.c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', + 'all', + 'sho%e', + null, + '$**.c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, { "b": { "c": "shoulder" } }, { "c": { "c": "shoe"} } ]', + 'all', + 'sho%', + null, + '$[*].c' +); + +select json_search +( + '[ { "a": { "b": { "c": "showtime" } } }, [ { "b": { "c": "shout" } }, { "c": { "c": "shoe"} } ] ]', + 'all', + 'sho%', + null, + '$[1]**.c' +); + +# escape character +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo%bar' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]', '$[1]', '$[2]' ); + +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[0]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo\%bar', null, '$[1]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[0]' ); +select json_search( '[ "footbar", "foo%bar" ]', 'all', 'foo|%bar', '|', '$[1]' ); + +# search is case-sensitive +select json_search( '[ "abc", "ABC" ]', 'all', 'aBc' ); +select json_search( '[ "abc", "ABC" ]', 'all', 'abc' ); +select json_search( '[ "abc", "ABC" ]', 'all', 'ABC' ); + +# only matches strings, not numerics +select json_search( '[ 10, "10", 1.0, "1.0" ]', 'all', '1%' ); + +# examples from the wl7909 spec +# returns null because numeric values don't match string values +SELECT JSON_SEARCH +( + '{ "a" : 123, "b" : [ 123, 456 ] }', + 'one', + '123' +); + +# returns "$.b[2]" +SELECT JSON_SEARCH +( + '{ "a" : "123", "b" : [ 123, "789", "123", "456", "123" ] }', + 'one', + '123', + null, + '$.b' +); + +# could return either "$.a" or "$.b.key" +SELECT JSON_SEARCH +( + '{ "a" : "123", "b" : { "key" : "123" } }', + 'one', + '123' +); + +# returns "$.b.key" +SELECT JSON_SEARCH +( + '{ "a" : "1243", "b" : { "key" : "1234" } }', + 'one', + '123%' +); + +# returns "$.b.c" +SELECT JSON_SEARCH +( + '{ "a" : "1243", "b" : { "key" : "1234", "c": "directorysub%directoryabc" } }', + 'one', + 'dir%torysub@%dir%', + '@' +); + +# returns null because the path doesn't exist +SELECT JSON_SEARCH +( + '{ "a" : "1243", "b" : { "key" : "1234" } }', + 'one', + '123%', + null, + '$.c' +); + +# returns $."one potato" +SELECT JSON_UNQUOTE +( + JSON_SEARCH + ( + '{ "onepotato": "foot", "one potato": "food" , "one \\"potato": "fool" }', + 'all', + 'food' + ) +); + +select json_type(case (null is null) when 1 then + cast('null' as json) else + cast('[1,2,3]' as json) end); + +select json_type(case (null is not null) when 1 then + cast('null' as json) else + cast('[1,2,3]' as json) end); + +select json_type( if(null is null, + cast('null' as json), + cast('[1,2,3]' as json)) ); + +select json_type( if(null is not null, + cast('null' as json), + cast('[1,2,3]' as json))); + +select cast(json_extract(cast(concat('[', cast('["A",2]' as json), ']') as json), + '$[0][1]') as char) = 2; + +--echo # ---------------------------------------------------------------------- +--echo # Test of aggregate function MAX, MIN. +--echo # ---------------------------------------------------------------------- + +select max(cast('[1,2,3]' as json)); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_QUOTE, JSON_UNQUOTE +--echo # ---------------------------------------------------------------------- + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote('abc', 'def'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote(NULL, 'def'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_quote('abc', NULL); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote('"abc"', '"def"'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote(NULL, 'def'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +select json_unquote('"abc"', NULL); + +select json_quote(NULL); +select json_unquote(NULL); + +select json_quote('abc'); +select json_quote(convert('abc' using ascii)); +select json_quote(convert('abc' using latin1)); +select json_quote(convert('abc' using utf8)); +select json_quote(convert('abc' using utf8mb4)); + +select json_unquote('abc'); # should do nothing + +select json_unquote('"abc"'); +select json_unquote(convert('"abc"' using ascii)); +select json_unquote(convert('"abc"' using latin1)); +select json_unquote(convert('"abc"' using utf8)); +select json_unquote(convert('"abc"' using utf8mb4)); + +select json_quote('"'); +select json_unquote('"'); # should do nothing + +--echo error ER_INCORRECT_TYPE +select json_quote(123); # integer not allowed +--echo error ER_INCORRECT_TYPE +select json_unquote(123); # integer not allowed + +select json_unquote('""'); # empty string +select char_length(json_unquote('""')); # verify empty string +select json_unquote('"" '); # unchanged: no final " +select json_unquote(cast(json_quote('abc') as json)); # round trip + +# No change in this JSON string: it is an object +select cast('{"abc": "foo"}' as json); +select json_unquote(cast('{"abc": "foo"}' as json)); + +# This is a JSON string, so it is actually unquoted +select json_extract(cast('{"abc": "foo"}' as json), '$.abc'); +select json_unquote(json_extract(cast('{"abc": "foo"}' as json), '$.abc')); + +# Bug fix: thse should be the same +select json_unquote('["a", "b", "c"]'); +select json_unquote(cast('["a", "b", "c"]' as json)); + +select charset(json_unquote('"abc"')); + +select json_quote(convert(X'e68891' using utf8)); # chinese "I" (wo3) +select json_quote(convert(X'e68891' using utf8mb4)); # chinese "I" (wo3) + +select cast(json_quote(convert(X'e68891' using utf8)) as json); + +select json_unquote(convert(X'e68891' using utf8)); # chinese "I" (wo3) + +select json_quote(json_quote(json_quote('abc'))); # deep quote +select json_unquote(json_unquote(json_unquote( # long round trip of it + json_quote(json_quote(json_quote('abc')))))); + +# DATE/TIME will lose their quotes, too: +select cast(cast('2015-01-15 23:24:25' as datetime) as json); +select json_unquote(cast(cast('2015-01-15 23:24:25' as datetime) as json)); + +# as well as opaque values: +select cast(st_geomfromtext('point(1 1)') as json); +select json_unquote(cast(st_geomfromtext('point(1 1)') as json)); + +# examples from the wl7909 spec +# returns the SQL string literal abc +SELECT JSON_UNQUOTE( '"abc"' ); + +# returns the SQL string literal "abc +SELECT JSON_UNQUOTE( '"abc' ); + +--echo error ER_INCORRECT_TYPE +SELECT JSON_UNQUOTE( 123 ); + +# returns the SQL string literal abc +SELECT JSON_UNQUOTE +( CAST( CAST( '"abc"' AS JSON ) AS CHAR ) ); + +# returns 1 +SELECT JSON_UNQUOTE +( + CAST( + JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) + AS CHAR + ) +) = 'fred'; + +# returns 0 +SELECT + CAST( + JSON_EXTRACT( '{ "userName" : "fred" }', '$.userName' ) + AS CHAR + ) = 'fred'; + +# returns "abc" +SELECT JSON_QUOTE( 'abc' ); + +--echo error ER_INCORRECT_TYPE +SELECT JSON_QUOTE( 123 ); + +# returns the JSON document consisting of the string scalar "123" +SELECT CAST( JSON_QUOTE( '123' ) AS JSON ); + +--echo # ---------------------------------------------------------------------- +--echo # Test of JSON_CONTAINS +--echo # ---------------------------------------------------------------------- + +--echo # should give NULL +select json_contains(NULL, NULL); +select json_contains(cast('{"a": 1, "b": 2}' as json), NULL); +select json_contains(NULL, cast('null' as json)); +select json_contains(cast('[1]' as json), cast('[1]' as json), NULL); + +--echo # should give 0: +select json_contains(cast(3.14 as json), cast(3 as json)); + +--echo # should give 0: not at top level +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json)); + +--echo # but path argument will fix it: +select json_contains(cast('{"a": {"b": 7}}' as json), cast('{"b": 7}' as json), '$.a'); + +--echo # but arrays "introspect" +select json_contains(cast('[1,[2.0, 3.0]]' as json), cast('[2.0]' as json)); +select json_contains(cast('[1, 2, [3, [4, 5]], 6, 7]' as json), cast('5' as json)); + +--echo # should give 0: just a key +select json_contains(cast('{"a": 1, "b": 2}' as json), cast('"a"' as json)); + +--echo # should give 0: one candidate element doesn't match +select json_contains(cast('[1]' as json), cast('[1,2]' as json)); + +--echo # should all give 1 +select json_contains(cast('null' as json), cast('null' as json)); +--echo # simple object subset +select json_contains(cast('{"a": 1, "b": 2}' as json), cast( '{"a": 1}' as json)); +--echo # simple vector subset +select json_contains(cast('[1, 2, 3]' as json), cast('[1, 3]' as json)); +--echo # auto-wrap, should give 1 +select json_contains(cast('[1, 2, 3]' as json), cast(3 as json)); +--echo # ok even with nested cast off elements +select json_contains(cast('{"person": {"id": 1, "country": "norway"}}' as json), + cast('{"person": {"country": "norway"}}' as json)); +--echo # vector reordering and duplicates is ok +select json_contains(cast('[1,3,5]' as json), cast('[5,3,1,5]' as json)); +--echo # ok even with more elts in candidate than in doc +select json_contains(cast('[{"b": 4, "a":7}]' as json), cast('[{"a":7},{"b":4}]' as json)); +select json_contains(cast('[{"b": 4, "a":7}, 5]' as json), cast('[5, {"a":7, "b":4}]' as json)); +--echo # ok even with mixed number types that compare equal +select json_contains(cast('[{"b": 4, "a":7}, 5.0]' as json), cast('[5, {"a":7.0E0, "b":4}]' as json)); + +# Bug discovered by Rick: used to give 1 (true). +select json_contains( '{"customer": "cust3"}', '{"customer": "cust1"}' ); + +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[3],false]'); +SELECT JSON_CONTAINS('[null,1,[2,3],true,false]', '[null,1,[4],false]'); +SELECT JSON_CONTAINS('[true,false]', '[[true]]'); +SELECT JSON_CONTAINS('[1,2]', '[[1]]'); +SELECT JSON_CONTAINS('[1,2]', '1', '$.abc'); +SELECT JSON_CONTAINS('{}', '{}'); +SELECT JSON_CONTAINS('{}', '{"a":1}'); +SELECT JSON_CONTAINS('{"a":1}', '{"a":1,"b":2}'); + +# examples from the wl7909 spec +# returns 1 +SELECT JSON_CONTAINS +( + CAST('[1, 4, 6]' AS JSON), + CAST('[1, 6]' AS JSON) +); + +# returns 1; even with nested cast off elements +SELECT JSON_CONTAINS +( + CAST('{"person": {"id": 1, "country": "norway"}}' AS JSON), + CAST('{"person": {"country": "norway"}}' AS JSON) +); + +# returns 1; reordering and duplicates are ok +SELECT JSON_CONTAINS +( + CAST('[1,3,5]' AS JSON), + CAST('[5,3,1,5]' AS JSON) +); + +# return 0; no type conversion is performed +SELECT JSON_CONTAINS +( + CAST('[3.14]' AS JSON), + CAST('[3]' AS JSON) +); + +# returns 1, due to auto-wrapping +SELECT JSON_CONTAINS +( + CAST('[1, 2, 3]' AS JSON), + CAST(3 AS JSON) +); + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_CONTAINS(); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_CONTAINS('[1]'); +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT JSON_CONTAINS('[1]', '[1]', '$', '$[0]'); + +--echo # ---------------------------------------------------------------------- +--echo # Wrong collation from JSON_QUOTE caused problems: Set it in +--echo # Item_func_json_quote::fix_length_and_dec. Bug found by Knut. +--echo # Similar issue for JSON_UNQUOTE and JSON_TYPE. +--echo # ---------------------------------------------------------------------- +select json_object("a", ifnull(json_quote('test'), cast('null' as json))); +select cast(concat('[', json_quote('ab'), ']') as json); +select cast(concat('[', json_unquote('"12"'), ']') as json); +select cast(concat('["', json_type(cast(1 as json)), '"]') as json); + +--echo # +--echo # Bug#20912438: ITEM_TYPE_HOLDER::DISPLAY_LENGTH(ITEM*): ASSERTION `0' FAILED +--echo # +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55"}')) UNION ALL +(SELECT JSON_KEYS('{ "key80": "2015-04-20 11:53:55" }') LIMIT 0); +SELECT CAST(1 AS JSON) UNION ALL SELECT CAST(1 AS JSON); + +# Exercise NULL handling and error handling in Item_copy_json::copy(). +SELECT COUNT(*), CAST(NULL AS JSON); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT COUNT(*), JSON_EXTRACT('not valid json!', '$'); + +--echo # ---------------------------------------------------------------------- +--echo # Bug report from John E. +--echo # Crash in Item_copy_json::~Item_copy_json +--echo # ---------------------------------------------------------------------- +EXPLAIN SELECT COUNT(*), JSON_KEYS('{}'); + +select json_search( '{ "a": "foo" }', 'one', 'foo', 'a' ); +select json_search( '{ "a": "foo" }', 'one', 'foo', null ); +select json_search( '{ "a": "foo" }', 'one', 'foo', convert(x'f8' using latin1) ); + +# bad escape arg +--error ER_WRONG_ARGUMENTS +select json_search( '{ "a": "foo" }', 'one', 'foo', 'ab' ); + +--echo # ---------------------------------------------------------------------- +--echo # Wrong results when Json_path_cache primed is accessed +--echo # during the prepare-phase. +--echo #---------------------------------------------------------------------- + +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', null ) is null; + +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', null ) is null'; +execute stmt1; + +--echo error ER_INVALID_JSON_PATH +select json_remove( '[ 1, { "a": true, "b": false, "c": null }, 5 ]', '$.' ) is null; + +--echo error ER_INVALID_JSON_PATH +prepare stmt1 from 'select json_remove( ''[ 1, { "a": true, "b": false, "c": null }, 5 ]'', ''$.'' ) is null'; + +--echo # ---------------------------------------------------------------------- +--echo # Bug#20987329 VALUE OF PREPARED STATEMENT PLACEHOLDER FOR PARAMETER +--echo # IN JSON_EXTRACT IS STICKY +--echo #---------------------------------------------------------------------- + +# should get different results with different parameter values + +# json_extract() + +# json_contains() + +prepare json_stmt1 FROM 'select json_contains( ''{ "keyA": [1, 2, 3], "keyB": [4, 5, 6] }'', ''[2]'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt1 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt1 USING @mypath; + +# json_contains_path() + +prepare json_stmt2 FROM 'select json_contains_path( ''{ "keyA": [1, 2, 3] }'', ''all'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt2 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt2 USING @mypath; + +# json_length() + +prepare json_stmt3 FROM 'select json_length( ''{ "keyA": [1, 2, 3], "keyB": [1, 2, 3, 4] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt3 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt3 USING @mypath; + +# json_keys() + +prepare json_stmt4 FROM 'select json_keys( ''[ { "keyA": true }, { "keyB": false } ]'', ? )'; +set @mypath = '$[0]'; +execute json_stmt4 USING @mypath; +set @mypath = '$[1]'; +execute json_stmt4 USING @mypath; + +# json_array_append() + +prepare json_stmt5 FROM 'select json_array_append( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA'; +execute json_stmt5 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt5 USING @mypath; + +# json_insert() + +prepare json_stmt6 FROM 'select json_insert( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt6 USING @mypath; +set @mypath = '$.keyB[2]'; +execute json_stmt6 USING @mypath; + +# json_set() + +prepare json_stmt7 FROM 'select json_set( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[2]'; +execute json_stmt7 USING @mypath; +set @mypath = '$.keyB[2]'; +execute json_stmt7 USING @mypath; + +# json_replace() + +prepare json_stmt8 FROM 'select json_replace( ''{ "keyA": [1, 2], "keyB": [3, 4] }'', ?, 5 )'; +set @mypath = '$.keyA[1]'; +execute json_stmt8 USING @mypath; +set @mypath = '$.keyB[1]'; +execute json_stmt8 USING @mypath; + +# json_search() + +prepare json_stmt9 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ''all'', ''foo%'', null, ? )'; +set @mypath = '$.keyA'; +execute json_stmt9 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt9 USING @mypath; + +# json_remove() + +prepare json_stmt10 FROM 'select json_remove( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ? )'; +set @mypath = '$.keyA'; +execute json_stmt10 USING @mypath; +set @mypath = '$.keyB'; +execute json_stmt10 USING @mypath; + +# similar caching problem for the oneOrAll args + +prepare json_stmt11 FROM 'select json_contains_path( ''{ "keyA": true }'', ?, ''$.keyA'', ''$.keyB'' )'; +set @mypath = 'one'; +execute json_stmt11 USING @mypath; +set @mypath = 'all'; +execute json_stmt11 USING @mypath; + +prepare json_stmt12 FROM 'select json_search( ''{ "keyA": [ "foot" ], "keyB": [ "food" ] }'', ?, ''foo%'' )'; +set @mypath = 'one'; +execute json_stmt12 USING @mypath; +set @mypath = 'all'; +execute json_stmt12 USING @mypath; + +--echo # +--echo # Bug#21128632 JSON_QUOTE(JSON_TYPE(...)) GIVES ERROR 3139 ER_INVALID_JSON_CHARSET +--echo # + +select json_quote( json_type( json_object() ) ); +select json_quote( json_type( cast('{}' as json) ) ); + +--echo # +--echo # Bug#21148020 OUTPUT FROM JSON_TYPE() IS TRUNCATED +--echo # WHEN EXECUTED IN A VIEW OR JOIN +--echo # + +SELECT JSON_TYPE(JSON_OBJECT()); +CREATE VIEW v1 AS SELECT JSON_TYPE(JSON_OBJECT()); +SELECT * FROM v1; +drop view v1; + +# SELECT JSON_TYPE(CAST(CAST('2015-05-25 11:23:55' AS DATETIME) AS JSON)); +# CREATE VIEW v2 AS SELECT JSON_TYPE(CAST(CAST('2015-05-25 11:23:55' AS +# DATETIME) AS JSON)); +# SELECT * FROM v2; +# drop view v2; + +--echo # +--echo # Bug#21198333 SIG 6 IN ITEM_CACHE_JSON::CACHE_VALUE AT SQL/ITEM.CC:9470 +--echo # +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT MIN(JSON_EXTRACT('not json', '$')); + +--echo # +--echo # Bug#21200657 DATA FROM DERIVED TABLE BASED +--echo # ON JSN_QUOTE()/JSN_UNQUOTE() CALL IS TRUNCATED +--echo # +SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1; +SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1; + +SELECT * FROM (SELECT JSON_QUOTE('This is a string that should not be truncated') AS field1) AS DERIVED_TABLE; +SELECT * FROM (SELECT JSON_UNQUOTE("This is a string that should not be truncated") AS field1) AS DERIVED_TABLE; +SELECT * FROM (SELECT JSON_UNQUOTE(JSON_QUOTE('This is a string that should not be truncated')) AS field1) AS DERIVED_TABLE; + +--echo # +--echo # Bug#21296173 JSON_OBJECT('KEY', BOOLEAN_LITERAL) USES VALUES 0, 1 +--echo # FOR BOOL WHEN USED VIA VIEW +--echo # + +SELECT JSON_OBJECT('key1', false, 'key2', true); +SELECT JSON_ARRAY('key1', false, 'key2', true); +CREATE VIEW v1 AS SELECT JSON_OBJECT('key1', false, 'key2', true); +SELECT * FROM v1; +CREATE VIEW v2 AS SELECT JSON_ARRAY('key1', false, 'key2', true); +SELECT * FROM v2; + +drop view v1; +drop view v2; + +--echo # +--echo # Bug#21293089 JSON_CONTAINS() RETURNS WRONG RESULT WITH EMPTY JSON ARRAY +--echo # +SELECT JSON_CONTAINS('[]', '{"a" : 1}'); +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, 5]'); +SELECT JSON_CONTAINS('[]', '[1, 2, 3, 4, {"a" : 1}]'); +SELECT JSON_CONTAINS('[]', '{"a" : [1, 2, 3, 4, 5]}'); +SELECT JSON_CONTAINS('[]', '[]'); + +--echo # +--echo # Bug#21377136 STACK OVERFLOW IN RAPIDJSON::GENERICREADER +--echo # +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[', 100000)); +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":', 100000)); +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('{"a":[', 100000)); +--echo error ER_JSON_DOCUMENT_TOO_DEEP +SELECT JSON_VALID(REPEAT('[{"a":', 100000)); + +--echo # +--echo # Bug#21381806 JSON: ASSERTION FAILED: ARG->NULL_VALUE +--echo # +SELECT JSON_SET(CASE WHEN 1 THEN NULL ELSE NULL END, '{}', '{}'); +SELECT JSON_VALID(CASE WHEN 1 THEN NULL ELSE NULL END); +SELECT JSON_ARRAY(CASE WHEN 1 THEN NULL ELSE NULL END); + +--echo # +--echo # Bug#21384048 ASSERTION FAILED: N >= 0 && N <= 308 +--echo # IN RAPIDJSON::INTERNAL::FASTPATH +--echo # +SELECT JSON_EXTRACT('-1E-36181012216111515851075235238', '$'); +SELECT JSON_EXTRACT('1E-36181012216111515851075235238', '$'); +SELECT JSON_EXTRACT('1E-325', '$'); +SELECT JSON_EXTRACT('1E-324', '$'); +SELECT JSON_EXTRACT('1E-323', '$'); +SELECT JSON_EXTRACT('1E+308', '$'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+309', '$'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('1E+36181012216111515851075235238', '$'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT JSON_EXTRACT('-1E+36181012216111515851075235238', '$'); + +--echo # +--echo # Bug#21383284: ASSERTION IN SELECT_LEX::SETUP_CONDS +--echo # +--error ER_WRONG_ARGUMENTS +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', 'too-long-escape'); +--echo error ER_INVALID_JSON_TEXT_IN_PARAM +SELECT 1 FROM dual WHERE JSON_SEARCH('{}', 'one', 'foo', JSON_EXTRACT('', '$')); + +--echo # +--echo # Bug#21442624 INCORRECT RESULT FROM JSON_SET WITH AUTO-WRAPPING +--echo # + +SELECT JSON_SET('1', '$', 100); +SELECT JSON_SET('1', '$[0]', 100); +SELECT JSON_SET('1', '$[0][0]', 100); +SELECT JSON_SET('1', '$[0][0][0]', 100); + +SELECT JSON_SET('[]', '$', 100); +SELECT JSON_SET('[]', '$[0]', 100); +SELECT JSON_SET('[]', '$[0][0]', 100); +SELECT JSON_SET('[]', '$[0][0][0]', 100); + +SELECT JSON_SET('[1]', '$', 100); +SELECT JSON_SET('[1]', '$[0]', 100); +SELECT JSON_SET('[1]', '$[0][0]', 100); +SELECT JSON_SET('[1]', '$[0][0][0]', 100); + +SELECT JSON_SET('[[1]]', '$', 100); +SELECT JSON_SET('[[1]]', '$[0]', 100); +SELECT JSON_SET('[[1]]', '$[0][0]', 100); +SELECT JSON_SET('[[1]]', '$[0][0][0]', 100); + +SELECT JSON_SET('[[[1]]]', '$', 100); +SELECT JSON_SET('[[[1]]]', '$[0]', 100); +SELECT JSON_SET('[[[1]]]', '$[0][0]', 100); +SELECT JSON_SET('[[[1]]]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('1', '$', 100); +SELECT JSON_REPLACE('1', '$[0]', 100); +SELECT JSON_REPLACE('1', '$[0][0]', 100); +SELECT JSON_REPLACE('1', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[]', '$', 100); +SELECT JSON_REPLACE('[]', '$[0]', 100); +SELECT JSON_REPLACE('[]', '$[0][0]', 100); +SELECT JSON_REPLACE('[]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[1]', '$', 100); +SELECT JSON_REPLACE('[1]', '$[0]', 100); +SELECT JSON_REPLACE('[1]', '$[0][0]', 100); +SELECT JSON_REPLACE('[1]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[[1]]', '$', 100); +SELECT JSON_REPLACE('[[1]]', '$[0]', 100); +SELECT JSON_REPLACE('[[1]]', '$[0][0]', 100); +SELECT JSON_REPLACE('[[1]]', '$[0][0][0]', 100); + +SELECT JSON_REPLACE('[[[1]]]', '$', 100); +SELECT JSON_REPLACE('[[[1]]]', '$[0]', 100); +SELECT JSON_REPLACE('[[[1]]]', '$[0][0]', 100); +SELECT JSON_REPLACE('[[[1]]]', '$[0][0][0]', 100); + + +--echo # +--echo # Bug#21828321: JSON FUNCS CALL DBUG_ABORT OR EXIT() ON WINDOWS! +--echo # +# LEAST and GREATEST treat JSON arguments as strings for now. They used to hit +# an assertion if used in a JSON context and all arguments were JSON values, or +# a mix of NULLs and JSON values. +SELECT JSON_ARRAY(LEAST(NULL, NULL), GREATEST(NULL, NULL), LEAST(j1, NULL), + GREATEST(NULL, j2), LEAST(j1, j2), GREATEST(j1, j2)) AS j +FROM (SELECT CAST('1' AS JSON) AS j1, CAST('2' AS JSON) AS j2) t; + diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 7ab136f177c..455f1a722ea 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -78,6 +78,8 @@ select json_extract('[10, 20, [30, 40]]', '$[2][*]'); select json_extract('[10, 20, [{"a":3}, 30, 40]]', '$[2][*]'); select json_extract('1', '$'); select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]'); +select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]'); +select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a'); select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word'); select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3); diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index b0576fbdaba..e97f00dae8e 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -168,6 +168,7 @@ void report_json_error_ex(String *js, json_engine_t *je, #define NO_WILDCARD_ALLOWED 1 #define SHOULD_END_WITH_ARRAY 2 +#define TRIVIAL_PATH_NOT_ALLOWED 3 #define report_path_error(js, je, n_param) \ report_path_error_ex(js, je, func_name(), n_param,\ @@ -205,6 +206,11 @@ static void report_path_error_ex(String *ps, json_path_t *p, code= ER_JSON_PATH_NO_WILDCARD; break; + case TRIVIAL_PATH_NOT_ALLOWED: + code= ER_JSON_PATH_EMPTY; + break; + + default: return; } @@ -547,22 +553,43 @@ void Item_func_json_extract::fix_length_and_dec() } +static bool path_exact(const json_path_with_flags *paths_list, int n_paths, + const json_path_t *p) +{ + for (; n_paths > 0; n_paths--, paths_list++) + { + if (json_path_compare(&paths_list->p, p) == 0) + return TRUE; + } + return FALSE; +} + + +static bool path_ok(const json_path_with_flags *paths_list, int n_paths, + const json_path_t *p) +{ + for (; n_paths > 0; n_paths--, paths_list++) + { + if (json_path_compare(&paths_list->p, p) >= 0) + return TRUE; + } + return FALSE; +} + + String *Item_func_json_extract::val_str(String *str) { String *js= args[0]->val_str(&tmp_js); - json_engine_t je; - bool multiple_values_found= FALSE; + json_engine_t je, sav_je; + json_path_t p; const uchar *value; - const char *first_value= NULL; - uint n_arg, v_len, first_len; - uint array_counters[JSON_DEPTH_LIMIT]; + int not_first_value= 0; + uint n_arg, v_len; + int possible_multiple_values; if ((null_value= args[0]->null_value)) return 0; - str->set_charset(js->charset()); - str->length(0); - for (n_arg=1; n_arg < arg_count; n_arg++) { json_path_with_flags *c_path= paths + n_arg - 1; @@ -572,76 +599,66 @@ String *Item_func_json_extract::val_str(String *str) if (s_p && json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(), (const uchar *) s_p->ptr() + s_p->length())) + { + report_path_error(s_p, &c_path->p, n_arg); goto return_null; + } c_path->parsed= c_path->constant; } + } - if (args[n_arg]->null_value) - goto return_null; + possible_multiple_values= arg_count > 2 || + (paths[0].p.types_used & (JSON_PATH_WILD | JSON_PATH_DOUBLE_WILD)); - json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), - (const uchar *) js->ptr() + js->length()); + str->set_charset(js->charset()); + str->length(0); - c_path->cur_step= c_path->p.steps; + if (possible_multiple_values && str->append("[", 1)) + goto error; - while (!json_find_path(&je, &c_path->p, &c_path->cur_step, array_counters)) + json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length(), &p); + + while (json_get_path_next(&je, &p) == 0) + { + if (!path_exact(paths, arg_count-1, &p)) + continue; + + value= je.value_begin; + + if (json_value_scalar(&je)) + v_len= je.value_end - value; + else { - if (json_read_value(&je)) + if (possible_multiple_values) + sav_je= je; + if (json_skip_level(&je)) goto error; - - value= je.value_begin; - if (json_value_scalar(&je)) - v_len= je.value_end - value; - else - { - if (json_skip_level(&je)) - goto error; - v_len= je.s.c_str - value; - } - - if (!multiple_values_found) - { - if (first_value == NULL) - { - /* - Just remember the first value as we don't know yet - if we need to create an array out of it or not. - */ - first_value= (const char *) value; - first_len= v_len; - } - else - { - multiple_values_found= TRUE; /* We have to make an JSON array. */ - if (str->append("[", 1) || - str->append(first_value, first_len)) - goto error; /* Out of memory. */ - } - - } - if (multiple_values_found && - (str->append(", ", 2) || - str->append((const char *) value, v_len))) - goto error; /* Out of memory. */ - - if (json_scan_next(&je)) - break; - + v_len= je.s.c_str - value; + if (possible_multiple_values) + je= sav_je; } + + if ((not_first_value && str->append(", ", 2)) || + str->append((const char *) value, v_len)) + goto error; /* Out of memory. */ + + not_first_value= 1; + + if (!possible_multiple_values) + break; } if (je.s.error) goto error; - if (first_value == NULL) + if (!not_first_value) { /* Nothing was found. */ goto return_null; } - if (multiple_values_found ? - str->append("]") : - str->append(first_value, first_len)) + if (possible_multiple_values && str->append("]")) goto error; /* Out of memory. */ return str; @@ -796,12 +813,14 @@ static int check_contains(json_engine_t *js, json_engine_t *value) { while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END) { - json_level_t c_level; + int c_level, v_scalar; DBUG_ASSERT(js->state == JST_VALUE); if (json_read_value(js)) return FALSE; - c_level= json_value_scalar(js) ? NULL : json_get_level(js); + if (!(v_scalar= json_value_scalar(js))) + c_level= json_get_level(js); + if (check_contains(js, value)) { if (json_skip_level(js)) @@ -809,7 +828,7 @@ static int check_contains(json_engine_t *js, json_engine_t *value) return TRUE; } if (value->s.error || js->s.error || - (c_level && json_skip_to_level(js, c_level))) + (!v_scalar && json_skip_to_level(js, c_level))) return FALSE; } return FALSE; @@ -955,6 +974,8 @@ return_null: bool Item_func_json_contains_path::fix_fields(THD *thd, Item **ref) { return alloc_tmp_paths(thd, arg_count-2, &paths, &tmp_paths) || + (p_found= (bool *) alloc_root(thd->mem_root, + (arg_count-2)*sizeof(bool))) == NULL || Item_int_func::fix_fields(thd, ref); } @@ -1010,6 +1031,7 @@ static int parse_one_or_all(const Item_func *f, Item *ooa_arg, } +#ifdef DUMMY longlong Item_func_json_contains_path::val_int() { String *js= args[0]->val_str(&tmp_js); @@ -1076,6 +1098,87 @@ return_null: null_value= 1; return 0; } +#endif /*DUMMY*/ + +longlong Item_func_json_contains_path::val_int() +{ + String *js= args[0]->val_str(&tmp_js); + json_engine_t je; + uint n_arg; + longlong result; + json_path_t p; + int n_found; + + if ((null_value= args[0]->null_value)) + return 0; + + if (parse_one_or_all(this, args[1], &ooa_parsed, ooa_constant, &mode_one)) + goto null_return;; + + for (n_arg=2; n_arg < arg_count; n_arg++) + { + json_path_with_flags *c_path= paths + n_arg - 2; + if (!c_path->parsed) + { + String *s_p= args[n_arg]->val_str(tmp_paths + (n_arg-2)); + if (s_p && + json_path_setup(&c_path->p,s_p->charset(),(const uchar *) s_p->ptr(), + (const uchar *) s_p->ptr() + s_p->length())) + { + report_path_error(s_p, &c_path->p, n_arg); + goto null_return; + } + c_path->parsed= c_path->constant; + } + if (args[n_arg]->null_value) + goto null_return; + } + + json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length(), &p); + + + if (!mode_one) + { + bzero(p_found, (arg_count-2) * sizeof(bool)); + n_found= arg_count - 2; + } + + result= 0; + while (json_get_path_next(&je, &p) == 0) + { + int n_path= arg_count - 2; + json_path_with_flags *c_path= paths; + for (; n_path > 0; n_path--, c_path++) + { + if (json_path_compare(&c_path->p, &p) >= 0) + { + if (mode_one) + { + result= 1; + break; + } + /* mode_all */ + if (p_found[n_path-1]) + continue; /* already found */ + if (--n_found == 0) + { + result= 1; + break; + } + p_found[n_path-1]= TRUE; + } + } + } + + if (je.s.error == 0) + return result; + + report_json_error(js, &je, 0); +null_return: + null_value= 1; + return 0; +} static int append_json_value(String *str, Item *item, String *tmp_val) @@ -1626,10 +1729,10 @@ longlong Item_func_json_length::val_int() { String *s_p= args[1]->val_str(&tmp_path); if (s_p && - json_path_setup(&path.p, s_p->charset(), (const uchar *) s_p->ptr(), - (const uchar *) s_p->ptr() + s_p->length())) + path_setup_nwc(&path.p, s_p->charset(), (const uchar *) s_p->ptr(), + (const uchar *) s_p->ptr() + s_p->length())) { - report_path_error(s_p, &path.p, 2); + report_path_error(s_p, &path.p, 1); goto null_return; } path.parsed= path.constant; @@ -2040,7 +2143,7 @@ String *Item_func_json_remove::val_str(String *str) str->set_charset(js->charset()); json_string_set_cs(&key_name, js->charset()); - for (n_arg=1, n_path=0; n_arg < arg_count; n_arg+=2, n_path++) + for (n_arg=1, n_path=0; n_arg < arg_count; n_arg++, n_path++) { uint array_counters[JSON_DEPTH_LIMIT]; json_path_with_flags *c_path= paths + n_path; @@ -2064,7 +2167,11 @@ String *Item_func_json_remove::val_str(String *str) /* We search to the last step. */ c_path->p.last_step--; if (c_path->p.last_step < c_path->p.steps) + { + c_path->p.s.error= TRIVIAL_PATH_NOT_ALLOWED; + report_path_error(s_p, &c_path->p, n_arg); goto null_return; + } } c_path->parsed= c_path->constant; } @@ -2371,60 +2478,6 @@ static int append_json_path(String *str, const json_path_t *p) } -static int json_path_compare(const json_path_t *a, const json_path_t *b) -{ - const json_path_step_t *sa= a->steps + 1; - const json_path_step_t *sb= b->steps + 1; - - if (a->last_step - sa > b->last_step - sb) - return -2; - - while (sa <= a->last_step) - { - if (sb > b->last_step) - return -2; - - if (!((sa->type & sb->type) & JSON_PATH_KEY_OR_ARRAY)) - goto step_failed; - - if (sa->type & JSON_PATH_ARRAY) - { - if (!(sa->type & JSON_PATH_WILD) && sa->n_item != sb->n_item) - goto step_failed; - } - else /* JSON_PATH_KEY */ - { - if (!(sa->type & JSON_PATH_WILD) && - (sa->key_end - sa->key != sb->key_end - sb->key || - memcmp(sa->key, sb->key, sa->key_end - sa->key) != 0)) - goto step_failed; - } - sb++; - sa++; - continue; - -step_failed: - if (!(sa->type & JSON_PATH_DOUBLE_WILD)) - return -1; - sb++; - } - - return sb <= b->last_step; -} - - -static bool path_ok(const json_path_with_flags *paths_list, int n_paths, - const json_path_t *p) -{ - for (; n_paths > 0; n_paths--, paths_list++) - { - if (json_path_compare(&paths_list->p, p) >= 0) - return TRUE; - } - return FALSE; -} - - String *Item_func_json_search::val_str(String *str) { String *js= args[0]->val_str(&tmp_js); @@ -2462,75 +2515,38 @@ String *Item_func_json_search::val_str(String *str) goto null_return; } - json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), - (const uchar *) js->ptr() + js->length()); + json_get_path_start(&je, js->charset(),(const uchar *) js->ptr(), + (const uchar *) js->ptr() + js->length(), &p); - p.last_step= p.steps; - p.steps[0].type= JSON_PATH_ARRAY_WILD; - p.steps[0].n_item= 0; - - do + while (json_get_path_next(&je, &p) == 0) { - switch (je.state) + if (json_value_scalar(&je)) { - case JST_KEY: - p.last_step->key= je.s.c_str; - while (json_read_keyname_chr(&je) == 0) - p.last_step->key_end= je.s.c_str; - if (je.s.error) - goto js_error; - /* Now we have je.state == JST_VALUE, so let's handle it. */ - - case JST_VALUE: - if (json_read_value(&je)) - goto js_error; - if (json_value_scalar(&je)) + if ((arg_count < 5 || path_ok(paths, arg_count - 4, &p)) && + compare_json_value_wild(&je, s_str) != 0) { - if ((arg_count < 5 || path_ok(paths, n_arg - 4, &p)) && - compare_json_value_wild(&je, s_str) != 0) + ++n_path_found; + if (n_path_found == 1) { - ++n_path_found; - if (n_path_found == 1) - { - sav_path= p; - sav_path.last_step= sav_path.steps + (p.last_step - p.steps); - } - else - { - if (n_path_found == 2) - { - if (str->append("[", 1) || - append_json_path(str, &sav_path)) - goto js_error; - } - if (str->append(", ", 2) || append_json_path(str, &p)) - goto js_error; - } - - if (mode_one) - goto end; + sav_path= p; + sav_path.last_step= sav_path.steps + (p.last_step - p.steps); } - if (p.last_step->type & JSON_PATH_ARRAY) - p.last_step->n_item++; - + else + { + if (n_path_found == 2) + { + if (str->append("[", 1) || + append_json_path(str, &sav_path)) + goto js_error; + } + if (str->append(", ", 2) || append_json_path(str, &p)) + goto js_error; + } + if (mode_one) + goto end; } - else - { - p.last_step++; - p.last_step->type= (enum json_path_step_types) je.value_type; - p.last_step->n_item= 0; - } - break; - case JST_OBJ_END: - case JST_ARRAY_END: - p.last_step--; - if (p.last_step->type & JSON_PATH_ARRAY) - p.last_step->n_item++; - break; - default: - break; } - } while (json_scan_next(&je) == 0); + } if (je.s.error) goto js_error; diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h index 07741536f55..2ce94985a00 100644 --- a/sql/item_jsonfunc.h +++ b/sql/item_jsonfunc.h @@ -197,6 +197,7 @@ protected: String *tmp_paths; bool mode_one; bool ooa_constant, ooa_parsed; + bool *p_found; public: Item_func_json_contains_path(THD *thd, List &list): diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 7f5df13ad97..b526760b8de 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7446,3 +7446,5 @@ ER_GEOJSON_TOO_FEW_POINTS eng "Incorrect GeoJSON format - too few points for linestring specified." ER_GEOJSON_NOT_CLOSED eng "Incorrect GeoJSON format - polygon not closed." +ER_JSON_PATH_EMPTY + eng "Path expression '$' is not allowed in argument %d to function '%s'." diff --git a/strings/json_lib.c b/strings/json_lib.c index 16d7436ab6e..66b075a997b 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1,4 +1,5 @@ #include +#include #include @@ -126,9 +127,9 @@ static int syntax_error(json_engine_t *j) static int mark_object(json_engine_t *j) { j->state= JST_OBJ_START; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_OBJ_CONT; + j->stack[j->stack_p]= JST_OBJ_CONT; return 0; } j->s.error= JE_DEPTH; @@ -142,9 +143,9 @@ static int read_obj(json_engine_t *j) j->state= JST_OBJ_START; j->value_type= JSON_VALUE_OBJECT; j->value= j->value_begin; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_OBJ_CONT; + j->stack[j->stack_p]= JST_OBJ_CONT; return 0; } j->s.error= JE_DEPTH; @@ -156,9 +157,9 @@ static int read_obj(json_engine_t *j) static int mark_array(json_engine_t *j) { j->state= JST_ARRAY_START; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_ARRAY_CONT; + j->stack[j->stack_p]= JST_ARRAY_CONT; j->value= j->value_begin; return 0; } @@ -172,9 +173,9 @@ static int read_array(json_engine_t *j) j->state= JST_ARRAY_START; j->value_type= JSON_VALUE_ARRAY; j->value= j->value_begin; - if ((++j->stack_p) - j->stack < JSON_DEPTH_LIMIT) + if (++j->stack_p < JSON_DEPTH_LIMIT) { - *j->stack_p= JST_ARRAY_CONT; + j->stack[j->stack_p]= JST_ARRAY_CONT; return 0; } j->s.error= JE_DEPTH; @@ -376,7 +377,7 @@ static int skip_str_constant(json_engine_t *j) return j->s.error= json_eos(&j->s) ? JE_EOS : JE_BAD_CHR; } - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return 0; } @@ -397,7 +398,7 @@ static int read_strn(json_engine_t *j) if (skip_str_constant(j)) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= (j->s.c_str - j->value) - 1; return 0; } @@ -469,7 +470,7 @@ static int json_num_states[NS_NUM_STATES][N_NUM_CLASSES]= /*GO*/ { NS_GO1, JE_SYN, NS_Z, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*GO1*/ { JE_SYN, JE_SYN, NS_Z1, NS_INT, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, /*ZERO*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, -/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, JE_SYN, JE_BAD_CHR }, +/*ZE1*/ { JE_SYN, JE_SYN, JE_SYN, JE_SYN, NS_FRAC, JE_SYN, NS_OK, JE_BAD_CHR }, /*INT*/ { JE_SYN, JE_SYN, NS_INT, NS_INT, NS_FRAC, NS_EX, NS_OK, JE_BAD_CHR }, /*FRAC*/ { JE_SYN, JE_SYN, NS_FRAC, NS_FRAC,JE_SYN, NS_EX, NS_OK, JE_BAD_CHR }, /*EX*/ { NS_EX1, NS_EX1, NS_EX1, NS_EX1, JE_SYN, JE_SYN, JE_SYN, JE_BAD_CHR }, @@ -517,7 +518,7 @@ static int skip_num_constant(json_engine_t *j) break; } - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return 0; } @@ -570,7 +571,7 @@ static int v_false(json_engine_t *j) { if (skip_string_verbatim(&j->s, "alse")) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return json_scan_next(j); } @@ -580,7 +581,7 @@ static int v_null(json_engine_t *j) { if (skip_string_verbatim(&j->s, "ull")) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return json_scan_next(j); } @@ -590,7 +591,7 @@ static int v_true(json_engine_t *j) { if (skip_string_verbatim(&j->s, "rue")) return 1; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; return json_scan_next(j); } @@ -600,7 +601,7 @@ static int read_false(json_engine_t *j) { j->value_type= JSON_VALUE_FALSE; j->value= j->value_begin; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= 5; return skip_string_verbatim(&j->s, "alse"); } @@ -611,7 +612,7 @@ static int read_null(json_engine_t *j) { j->value_type= JSON_VALUE_NULL; j->value= j->value_begin; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= 4; return skip_string_verbatim(&j->s, "ull"); } @@ -622,7 +623,7 @@ static int read_true(json_engine_t *j) { j->value_type= JSON_VALUE_TRUE; j->value= j->value_begin; - j->state= *j->stack_p; + j->state= j->stack[j->stack_p]; j->value_len= 4; return skip_string_verbatim(&j->s, "rue"); } @@ -791,7 +792,7 @@ int json_scan_start(json_engine_t *je, { json_string_setup(&je->s, i_cs, str, end); je->stack[0]= JST_DONE; - je->stack_p= je->stack; + je->stack_p= 0; je->state= JST_VALUE; return 0; } @@ -839,7 +840,7 @@ static int skip_key(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_eos(json_engine_t *j) -{ return json_actions[*j->stack_p][C_EOS](j); } +{ return json_actions[j->stack[j->stack_p]][C_EOS](j); } /* @@ -849,7 +850,7 @@ static int struct_end_eos(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_cb(json_engine_t *j) -{ return json_actions[*j->stack_p][C_RCURB](j); } +{ return json_actions[j->stack[j->stack_p]][C_RCURB](j); } /* @@ -859,7 +860,7 @@ static int struct_end_cb(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_qb(json_engine_t *j) -{ return json_actions[*j->stack_p][C_RSQRB](j); } +{ return json_actions[j->stack[j->stack_p]][C_RSQRB](j); } /* @@ -869,7 +870,7 @@ static int struct_end_qb(json_engine_t *j) run our 'state machine' accordingly. */ static int struct_end_cm(json_engine_t *j) -{ return json_actions[*j->stack_p][C_COMMA](j); } +{ return json_actions[j->stack[j->stack_p]][C_COMMA](j); } int json_read_keyname_chr(json_engine_t *j) @@ -1107,8 +1108,6 @@ int json_path_setup(json_path_t *p, continue; case PS_KWD: case PS_AWD: - if (p->last_step->type & JSON_PATH_DOUBLE_WILD) - return p->s.error= JE_SYN; p->last_step->type|= JSON_PATH_WILD; p->types_used|= JSON_PATH_WILD; continue; @@ -1158,7 +1157,7 @@ int json_path_setup(json_path_t *p, } -int json_skip_to_level(json_engine_t *j, json_level_t level) +int json_skip_to_level(json_engine_t *j, int level) { do { if (j->stack_p < level) @@ -1595,3 +1594,118 @@ int json_escape(CHARSET_INFO *str_cs, return json - json_start; } + + +int json_get_path_start(json_engine_t *je, CHARSET_INFO *i_cs, + const uchar *str, const uchar *end, + json_path_t *p) +{ + json_scan_start(je, i_cs, str, end); + p->last_step= p->steps - 1; + return 0; +} + + +int json_get_path_next(json_engine_t *je, json_path_t *p) +{ + if (p->last_step < p->steps) + { + if (json_read_value(je)) + return 1; + + p->last_step= p->steps; + p->steps[0].type= JSON_PATH_ARRAY_WILD; + p->steps[0].n_item= 0; + return 0; + } + else + { + if (json_value_scalar(je)) + { + if (p->last_step->type & JSON_PATH_ARRAY) + p->last_step->n_item++; + } + else + { + p->last_step++; + p->last_step->type= (enum json_path_step_types) je->value_type; + p->last_step->n_item= 0; + } + + if (json_scan_next(je)) + return 1; + } + + do + { + switch (je->state) + { + case JST_KEY: + p->last_step->key= je->s.c_str; + while (json_read_keyname_chr(je) == 0) + p->last_step->key_end= je->s.c_str; + if (je->s.error) + return 1; + /* Now we have je.state == JST_VALUE, so let's handle it. */ + + case JST_VALUE: + if (json_read_value(je)) + return 1; + return 0; + case JST_OBJ_END: + case JST_ARRAY_END: + p->last_step--; + if (p->last_step->type & JSON_PATH_ARRAY) + p->last_step->n_item++; + break; + default: + break; + } + } while (json_scan_next(je) == 0); + + return 1; +} + + +int json_path_compare(const json_path_t *a, const json_path_t *b) +{ + const json_path_step_t *sa= a->steps + 1; + const json_path_step_t *sb= b->steps + 1; + + if (a->last_step - sa > b->last_step - sb) + return -2; + + while (sa <= a->last_step) + { + if (sb > b->last_step) + return -2; + + if (!((sa->type & sb->type) & JSON_PATH_KEY_OR_ARRAY)) + goto step_failed; + + if (sa->type & JSON_PATH_ARRAY) + { + if (!(sa->type & JSON_PATH_WILD) && sa->n_item != sb->n_item) + goto step_failed; + } + else /* JSON_PATH_KEY */ + { + if (!(sa->type & JSON_PATH_WILD) && + (sa->key_end - sa->key != sb->key_end - sb->key || + memcmp(sa->key, sb->key, sa->key_end - sa->key) != 0)) + goto step_failed; + } + sb++; + sa++; + continue; + +step_failed: + if (!(sa->type & JSON_PATH_DOUBLE_WILD)) + return -1; + sb++; + } + + return sb <= b->last_step; +} + + From 6cdbf2027e4f6dff40e0ea5da8d6cc6b9b6e255b Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 24 Jan 2017 19:52:15 +0530 Subject: [PATCH 112/167] MDEV-11108: adjusted test results --- mysql-test/r/subselect_sj2_jcl6.result | 13 +++++++++++++ mysql-test/r/subselect_sj2_mat.result | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result index 021646a7599..61519234f44 100644 --- a/mysql-test/r/subselect_sj2_jcl6.result +++ b/mysql-test/r/subselect_sj2_jcl6.result @@ -1333,6 +1333,19 @@ id 1 2 drop table t1,t2,t3; +# +# MDEV-11108: Assertion `uniq_tuple_length_arg <= table->file->max_key_length()' failed in SJ_TMP_TABLE::create_sj_weedout_tmp_table +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (pk BLOB, b INT, PRIMARY KEY(pk(1000))) ENGINE=InnoDB; +CREATE TABLE t3 (c INT) ENGINE=InnoDB; +CREATE OR REPLACE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3; +INSERT INTO t3 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +SELECT * FROM t1, t2 +WHERE a IN ( SELECT b FROM t2 LEFT JOIN v3 ON ( c = b ) ) ; +a pk b +DROP TABLE t1,t2,t3; +DROP VIEW v3; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; # diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result index 46da52fe0eb..a06742241cf 100644 --- a/mysql-test/r/subselect_sj2_mat.result +++ b/mysql-test/r/subselect_sj2_mat.result @@ -1320,6 +1320,19 @@ id 1 2 drop table t1,t2,t3; +# +# MDEV-11108: Assertion `uniq_tuple_length_arg <= table->file->max_key_length()' failed in SJ_TMP_TABLE::create_sj_weedout_tmp_table +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (pk BLOB, b INT, PRIMARY KEY(pk(1000))) ENGINE=InnoDB; +CREATE TABLE t3 (c INT) ENGINE=InnoDB; +CREATE OR REPLACE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3; +INSERT INTO t3 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +SELECT * FROM t1, t2 +WHERE a IN ( SELECT b FROM t2 LEFT JOIN v3 ON ( c = b ) ) ; +a pk b +DROP TABLE t1,t2,t3; +DROP VIEW v3; # This must be the last in the file: set optimizer_switch=@subselect_sj2_tmp; set optimizer_switch=default; From 1782102d978caeea282147ff6ca89e325a3da512 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 24 Jan 2017 22:39:55 +0400 Subject: [PATCH 113/167] MDEV-11042 Implement GeoJSON functions. Typenames made into proper character case. --- mysql-test/r/gis-json.result | 14 +++++++------- sql/spatial.cc | 25 ++++++++++++++----------- sql/spatial.h | 4 +++- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/gis-json.result b/mysql-test/r/gis-json.result index 14b532784f7..8625a5bfb74 100644 --- a/mysql-test/r/gis-json.result +++ b/mysql-test/r/gis-json.result @@ -1,24 +1,24 @@ select st_asgeojson(geomfromtext('POINT(1 1)')); st_asgeojson(geomfromtext('POINT(1 1)')) -{"type": "POINT", "coordinates": [1, 1]} +{"type": "Point", "coordinates": [1, 1]} select st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')); st_asgeojson(geomfromtext('LINESTRING(10 10,20 10,20 20,10 20,10 10)')) -{"type": "LINESTRING", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} +{"type": "LineString", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} select st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')); st_asgeojson(geomfromtext('POLYGON((10 10,20 10,20 20,10 20,10 10))')) -{"type": "POLYGON", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} +{"type": "Polygon", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} select st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')); st_asgeojson(geomfromtext('MULTIPOLYGON(((10 10,20 10,20 20,10 20,10 10)))')) -{"type": "MULTIPOLYGON", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]} +{"type": "MultiPolygon", "coordinates": [[[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]]} select st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')); st_asgeojson(geomfromtext('multilinestring((10 10,20 10,20 20,10 20,10 10))')) -{"type": "MULTILINESTRING", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} +{"type": "MultiLineString", "coordinates": [[[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]]} select st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')); st_asgeojson(geomfromtext('multipoint(10 10,20 10,20 20,10 20,10 10)')) -{"type": "MULTIPOINT", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} +{"type": "MultiPoint", "coordinates": [[10, 10], [20, 10], [20, 20], [10, 20], [10, 10]]} select st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')); st_asgeojson(st_geomfromtext('GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))')) -{"type": "GEOMETRYCOLLECTION", "geometries": [{"type": "POINT", "coordinates": [100, 0]}, {"type": "LINESTRING", "coordinates": [[101, 0], [102, 1]]}]} +{"type": "GeometryCollection", "geometries": [{"type": "Point", "coordinates": [100, 0]}, {"type": "LineString", "coordinates": [[101, 0], [102, 1]]}]} SELECT st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')); st_astext(st_geomfromgeojson('{"type":"point","coordinates":[1,2]}')) POINT(1 2) diff --git a/sql/spatial.cc b/sql/spatial.cc index ef9c24dcef4..0e3976ba573 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -58,12 +58,14 @@ Geometry::Class_info *Geometry::ci_collection[Geometry::wkb_last+1]= static Geometry::Class_info **ci_collection_end= Geometry::ci_collection+Geometry::wkb_last + 1; -Geometry::Class_info::Class_info(const char *name, int type_id, - create_geom_t create_func): +Geometry::Class_info::Class_info(const char *name, const char *geojson_name, + int type_id, create_geom_t create_func): m_type_id(type_id), m_create_func(create_func) { m_name.str= (char *) name; m_name.length= strlen(name); + m_geojson_name.str= (char *) geojson_name; + m_geojson_name.length= strlen(geojson_name); ci_collection[type_id]= this; } @@ -105,26 +107,27 @@ static Geometry *create_geometrycollection(char *buffer) -static Geometry::Class_info point_class("POINT", +static Geometry::Class_info point_class("POINT", "Point", Geometry::wkb_point, create_point); -static Geometry::Class_info linestring_class("LINESTRING", +static Geometry::Class_info linestring_class("LINESTRING", "LineString", Geometry::wkb_linestring, create_linestring); -static Geometry::Class_info polygon_class("POLYGON", +static Geometry::Class_info polygon_class("POLYGON", "Polygon", Geometry::wkb_polygon, create_polygon); -static Geometry::Class_info multipoint_class("MULTIPOINT", +static Geometry::Class_info multipoint_class("MULTIPOINT", "MultiPoint", Geometry::wkb_multipoint, create_multipoint); static Geometry::Class_info -multilinestring_class("MULTILINESTRING", +multilinestring_class("MULTILINESTRING", "MultiLineString", Geometry::wkb_multilinestring, create_multilinestring); -static Geometry::Class_info multipolygon_class("MULTIPOLYGON", +static Geometry::Class_info multipolygon_class("MULTIPOLYGON", "MultiPolygon", Geometry::wkb_multipolygon, create_multipolygon); static Geometry::Class_info -geometrycollection_class("GEOMETRYCOLLECTION",Geometry::wkb_geometrycollection, +geometrycollection_class("GEOMETRYCOLLECTION", "GeometryCollection", + Geometry::wkb_geometrycollection, create_geometrycollection); static void get_point(double *x, double *y, const char *data) @@ -251,14 +254,14 @@ static const int feature_coll_type_len= 17; int Geometry::as_json(String *wkt, uint max_dec_digits, const char **end) { - uint32 len= (uint) get_class_info()->m_name.length; + uint32 len= (uint) get_class_info()->m_geojson_name.length; if (wkt->reserve(4 + type_keyname_len + 2 + len + 2 + 2 + coord_keyname_len + 4, 512)) return 1; wkt->qs_append("{\"", 2); wkt->qs_append((const char *) type_keyname, type_keyname_len); wkt->qs_append("\": \"", 4); - wkt->qs_append(get_class_info()->m_name.str, len); + wkt->qs_append(get_class_info()->m_geojson_name.str, len); wkt->qs_append("\", \"", 4); if (get_class_info() == &geometrycollection_class) wkt->qs_append((const char *) geometries_keyname, geometries_keyname_len); diff --git a/sql/spatial.h b/sql/spatial.h index 926f66d5357..3858c0d2e51 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -265,9 +265,11 @@ public: { public: LEX_STRING m_name; + LEX_STRING m_geojson_name; int m_type_id; create_geom_t m_create_func; - Class_info(const char *name, int type_id, create_geom_t create_func); + Class_info(const char *name, const char *gejson_name, + int type_id, create_geom_t create_func); }; virtual const Class_info *get_class_info() const=0; From 35760c00004615dfa44ba5735dc1f8f9abe24483 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Wed, 25 Jan 2017 00:13:15 +0400 Subject: [PATCH 114/167] MDEV-11557 Port MySQL-5.7 JSON tests to MariaDB. more fixes. --- mysql-test/suite/json/r/json_no_table.result | 28 ++++++++++---------- sql/item_jsonfunc.cc | 8 ++++-- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result index 514b6a775d4..88016ebfd19 100644 --- a/mysql-test/suite/json/r/json_no_table.result +++ b/mysql-test/suite/json/r/json_no_table.result @@ -1355,7 +1355,7 @@ json_extract('{"a": 1, "b": [1,2,3]}', '$.b[2]') 3 select json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL); json_extract('{"a": 1, "b": {"e": "foo", "b": 3}}', '$.a', NULL) -[1] +NULL # returns a JSON value containing just the string "123" SELECT JSON_EXTRACT('{ "a" : "foo", "b" : [ true, { "c" : "123" } ] }', '$.b[ 1 ].c'); @@ -1736,7 +1736,7 @@ json_insert('{"c":4}', '$.a', 4) {"c":4, "a":4} select json_insert('1', '$', 4); json_insert('1', '$', 4) -[1, 4] +1 select json_insert('1', '$[0]', 4); json_insert('1', '$[0]', 4) [1, 4] @@ -2115,7 +2115,7 @@ json_set('{"c":4}', '$.a', 5) {"c":4, "a":5} select json_set('1', '$', 4); json_set('1', '$', 4) -[1, 4] +4 select json_set('1', '$[0]', 4); json_set('1', '$[0]', 4) [1, 4] @@ -2277,7 +2277,7 @@ json_replace('{"c":4}', '$.a', 5) {"c":4} select json_replace('1', '$', 4); json_replace('1', '$', 4) -1 +4 select json_replace('1', '$[0]', 4); json_replace('1', '$[0]', 4) 1 @@ -3486,7 +3486,7 @@ Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_extract # SELECT JSON_SET('1', '$', 100); JSON_SET('1', '$', 100) -[1, 100] +100 SELECT JSON_SET('1', '$[0]', 100); JSON_SET('1', '$[0]', 100) [1, 100] @@ -3502,7 +3502,7 @@ Warnings: Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' SELECT JSON_SET('[]', '$', 100); JSON_SET('[]', '$', 100) -[, 100] +100 SELECT JSON_SET('[]', '$[0]', 100); JSON_SET('[]', '$[0]', 100) [, 100] @@ -3518,7 +3518,7 @@ Warnings: Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' SELECT JSON_SET('[1]', '$', 100); JSON_SET('[1]', '$', 100) -[1, 100] +100 SELECT JSON_SET('[1]', '$[0]', 100); JSON_SET('[1]', '$[0]', 100) [100] @@ -3532,7 +3532,7 @@ Warnings: Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' SELECT JSON_SET('[[1]]', '$', 100); JSON_SET('[[1]]', '$', 100) -[[1], 100] +100 SELECT JSON_SET('[[1]]', '$[0]', 100); JSON_SET('[[1]]', '$[0]', 100) [100] @@ -3544,7 +3544,7 @@ JSON_SET('[[1]]', '$[0][0][0]', 100) [[[1, 100]]] SELECT JSON_SET('[[[1]]]', '$', 100); JSON_SET('[[[1]]]', '$', 100) -[[[1]], 100] +100 SELECT JSON_SET('[[[1]]]', '$[0]', 100); JSON_SET('[[[1]]]', '$[0]', 100) [100] @@ -3556,7 +3556,7 @@ JSON_SET('[[[1]]]', '$[0][0][0]', 100) [[[100]]] SELECT JSON_REPLACE('1', '$', 100); JSON_REPLACE('1', '$', 100) -1 +100 SELECT JSON_REPLACE('1', '$[0]', 100); JSON_REPLACE('1', '$[0]', 100) 1 @@ -3572,7 +3572,7 @@ Warnings: Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' SELECT JSON_REPLACE('[]', '$', 100); JSON_REPLACE('[]', '$', 100) -[] +100 SELECT JSON_REPLACE('[]', '$[0]', 100); JSON_REPLACE('[]', '$[0]', 100) [] @@ -3588,7 +3588,7 @@ Warnings: Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' SELECT JSON_REPLACE('[1]', '$', 100); JSON_REPLACE('[1]', '$', 100) -[1] +100 SELECT JSON_REPLACE('[1]', '$[0]', 100); JSON_REPLACE('[1]', '$[0]', 100) [100] @@ -3602,7 +3602,7 @@ Warnings: Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' SELECT JSON_REPLACE('[[1]]', '$', 100); JSON_REPLACE('[[1]]', '$', 100) -[[1]] +100 SELECT JSON_REPLACE('[[1]]', '$[0]', 100); JSON_REPLACE('[[1]]', '$[0]', 100) [100] @@ -3614,7 +3614,7 @@ JSON_REPLACE('[[1]]', '$[0][0][0]', 100) [[1]] SELECT JSON_REPLACE('[[[1]]]', '$', 100); JSON_REPLACE('[[[1]]]', '$', 100) -[[[1]]] +100 SELECT JSON_REPLACE('[[[1]]]', '$[0]', 100); JSON_REPLACE('[[[1]]]', '$[0]', 100) [100] diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index e97f00dae8e..fc146427bc1 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -605,6 +605,9 @@ String *Item_func_json_extract::val_str(String *str) } c_path->parsed= c_path->constant; } + + if (args[n_arg]->null_value) + goto return_null; } possible_multiple_values= arg_count > 2 || @@ -666,7 +669,6 @@ String *Item_func_json_extract::val_str(String *str) error: report_json_error(js, &je, 0); return_null: - /* TODO: launch error messages. */ null_value= 1; return 0; } @@ -1958,6 +1960,9 @@ String *Item_func_json_insert::val_str(String *str) json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), (const uchar *) js->ptr() + js->length()); + if (c_path->p.last_step < c_path->p.steps) + goto v_found; + c_path->cur_step= c_path->p.steps; if (c_path->p.last_step >= c_path->p.steps && @@ -2572,7 +2577,6 @@ end: js_error: report_json_error(js, &je, 0); null_return: - /* TODO: launch error messages. */ null_value= 1; return 0; } From 423b7da36f1cbe692be449caa8879d37a41b333b Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 24 Jan 2017 13:11:26 -0800 Subject: [PATCH 115/167] Fixed bug mdev-11820. The fields st_select_lex::cond_pushed_into_where and st_select_lex::cond_pushed_into_having should be re-initialized for the unit specifying a derived table at every re-execution of the query that uses this derived table, because the result of condition pushdown may be different for different executions. --- mysql-test/r/derived_cond_pushdown.result | 109 ++++++++++++++++++++++ mysql-test/t/derived_cond_pushdown.test | 34 +++++++ sql/sql_derived.cc | 5 + 3 files changed, 148 insertions(+) diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result index 0be577a9f64..fd58ee038c7 100644 --- a/mysql-test/r/derived_cond_pushdown.result +++ b/mysql-test/r/derived_cond_pushdown.result @@ -8241,3 +8241,112 @@ SELECT * FROM v1 WHERE v1.d IN ( SELECT MIN(d) FROM t2 WHERE 0 ); d DROP VIEW v1; DROP TABLE t1,t2; +# +# MDEV-11820: second execution of PS for query +# with false subquery predicate in WHERE +# +CREATE TABLE t1 (c VARCHAR(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (3), (4); +PREPARE stmt1 FROM +" SELECT * FROM v1 WHERE 1 IN (SELECT a FROM t2) OR c = 'foo'"; +PREPARE stmt2 FROM +"EXPLAIN FORMAT=JSON + SELECT * FROM v1 WHERE 1 IN (SELECT a FROM t2) OR c = 'foo'"; +EXECUTE stmt1; +c +foo +EXECUTE stmt2; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "v1.c = 'foo'", + "materialized": { + "query_block": { + "select_id": 3, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "t1.c = 'foo'" + } + } + } + }, + "subqueries": [ + { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "1 = t2.a" + } + } + } + ] + } +} +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +EXECUTE stmt1; +c +foo +EXECUTE stmt2; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "", + "access_type": "ALL", + "rows": 2, + "filtered": 100, + "attached_condition": "(1,(subquery#2)) or v1.c = 'foo'", + "materialized": { + "query_block": { + "select_id": 3, + "table": { + "table_name": "t1", + "access_type": "ALL", + "rows": 2, + "filtered": 100 + } + } + } + }, + "subqueries": [ + { + "query_block": { + "select_id": 2, + "table": { + "table_name": "t2", + "access_type": "ALL", + "rows": 128, + "filtered": 100, + "attached_condition": "1 = t2.a" + } + } + } + ] + } +} +DEALLOCATE PREPARE stmt1; +DEALLOCATE PREPARE stmt2; +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test index e43751472db..47d01617b83 100644 --- a/mysql-test/t/derived_cond_pushdown.test +++ b/mysql-test/t/derived_cond_pushdown.test @@ -1319,3 +1319,37 @@ SELECT * FROM v1 WHERE v1.d IN ( SELECT MIN(d) FROM t2 WHERE 0 ); DROP VIEW v1; DROP TABLE t1,t2; + +--echo # +--echo # MDEV-11820: second execution of PS for query +--echo # with false subquery predicate in WHERE +--echo # + +CREATE TABLE t1 (c VARCHAR(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (3), (4); + +PREPARE stmt1 FROM +" SELECT * FROM v1 WHERE 1 IN (SELECT a FROM t2) OR c = 'foo'"; +PREPARE stmt2 FROM +"EXPLAIN FORMAT=JSON + SELECT * FROM v1 WHERE 1 IN (SELECT a FROM t2) OR c = 'foo'"; +EXECUTE stmt1; +EXECUTE stmt2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +INSERT INTO t2 SELECT a+1 FROM t2; +EXECUTE stmt1; +EXECUTE stmt2; +DEALLOCATE PREPARE stmt1; +# the result here will change after the merge with the fix for mdev-11859 +DEALLOCATE PREPARE stmt2; + +DROP VIEW v1; +DROP TABLE t1,t2; + diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index c27649ca5e8..76cb27d7d62 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1099,6 +1099,11 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) unit->types.empty(); /* for derived tables & PS (which can't be reset by Item_subselect) */ unit->reinit_exec_mechanism(); + for (st_select_lex *sl= unit->first_select(); sl; sl= sl->next_select()) + { + sl->cond_pushed_into_where= NULL; + sl->cond_pushed_into_having= NULL; + } unit->set_thd(thd); DBUG_RETURN(FALSE); } From 84895c3cd7ce3ca4a33ac03f13b25f2bc0c6db67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 25 Jan 2017 07:39:56 +0200 Subject: [PATCH 116/167] Fix compiler error on x86. --- storage/innobase/include/os0file.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 6a97ff3aa53..0194a876cf3 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -433,7 +433,7 @@ public: dberr_t punch_hole( os_file_t fh, - ulint offset, + os_offset_t offset, ulint len); private: From ddc14d8eb7361ff92b442e3d2fdc2e70e32af6b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 25 Jan 2017 07:51:08 +0200 Subject: [PATCH 117/167] MDEV-10942: innodb_zip.innochecksum_3, innodb_zip.innochecksum_2 fail in buildbot. Fixed test results. --- extra/innochecksum.cc | 2 -- mysql-test/suite/innodb_zip/r/innochecksum_2.result | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index 707451da7fa..393b1af062c 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -1346,10 +1346,8 @@ static struct my_option innochecksum_options[] = { 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Verbose (prints progress every 5 seconds).", &verbose, &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifndef DBUG_OFF {"debug", '#', "Output debug log. See " REFMAN "dbug-package.html", &dbug_setting, &dbug_setting, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, -#endif /* !DBUG_OFF */ {"count", 'c', "Print the count of pages in the file and exits.", &just_count, &just_count, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"start_page", 's', "Start on this page number (0 based).", diff --git a/mysql-test/suite/innodb_zip/r/innochecksum_2.result b/mysql-test/suite/innodb_zip/r/innochecksum_2.result index 649c32b1a87..78d8a1cbf90 100644 --- a/mysql-test/suite/innodb_zip/r/innochecksum_2.result +++ b/mysql-test/suite/innodb_zip/r/innochecksum_2.result @@ -41,7 +41,7 @@ innochecksum Ver #.#.# Copyright (c) YEAR, YEAR , Oracle, MariaDB Corporation Ab and others. InnoDB offline file checksum utility. -Usage: innochecksum [-c] [-s ] [-e ] [-p ] [-v] [-a ] [-n] [-C ] [-w ] [-S] [-D ] [-l ] +Usage: innochecksum [-c] [-s ] [-e ] [-p ] [-v] [-a ] [-n] [-C ] [-w ] [-S] [-D ] [-l ] [-e] -?, --help Displays this help and exits. -I, --info Synonym for --help. -V, --version Displays version information and exits. @@ -63,7 +63,7 @@ Usage: innochecksum [-c] [-s ] [-e ] [-p ] [-v] [-a -D, --page-type-dump=name Dump the page type info for each page in a tablespace. -l, --log=name log output. - -l, --leaf Examine leaf index pages + -e, --leaf Examine leaf index pages -m, --merge=# leaf page count if merge given number of consecutive pages From 17430a802b4867c60e7185807c0e2ae14c878475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 25 Jan 2017 08:43:19 +0200 Subject: [PATCH 118/167] MDEV-11905: encryption.innodb-discard-import test fails Problem was that on import with buffered input/output trim is not possible as we write several pages in one write. --- .../t/innodb-discard-import-change.opt | 1 - storage/innobase/fil/fil0fil.cc | 17 ++++++++++++++--- storage/innobase/fil/fil0pagecompress.cc | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) delete mode 100644 mysql-test/suite/encryption/t/innodb-discard-import-change.opt diff --git a/mysql-test/suite/encryption/t/innodb-discard-import-change.opt b/mysql-test/suite/encryption/t/innodb-discard-import-change.opt deleted file mode 100644 index ebf13f41150..00000000000 --- a/mysql-test/suite/encryption/t/innodb-discard-import-change.opt +++ /dev/null @@ -1 +0,0 @@ ---loose-innodb-use-trim=0 \ No newline at end of file diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 75067bc075e..b6475e133ff 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -5669,7 +5669,9 @@ struct fil_iterator_t { for IO */ byte* io_buffer; /*!< Buffer to use for IO */ fil_space_crypt_t *crypt_data; /*!< MariaDB Crypt data (if encrypted) */ - byte* crypt_io_buffer; /*!< MariaDB IO buffer when encrypted */ + byte* crypt_io_buffer; /*!< MariaDB IO buffer when + encrypted */ + dict_table_t* table; /*!< Imported table */ }; /********************************************************************//** @@ -5877,16 +5879,21 @@ fil_iterate( if (page_compressed) { ulint len = 0; - fil_compress_page(space_id, + + byte * res = fil_compress_page(space_id, src, NULL, size, - fil_space_get_page_compression_level(space_id), + dict_table_page_compression_level(iter.table), fil_space_get_block_size(space_id, offset, size), encrypted, &len, NULL); + if (len != size) { + memset(res+len, 0, size-len); + } + updated = true; } @@ -5936,6 +5943,9 @@ fil_iterate( ib::error() << "os_file_write() failed"; return(err); } + + /* Clean up the temporal buffer. */ + memset(writeptr, 0, n_bytes); } return(DB_SUCCESS); @@ -6054,6 +6064,7 @@ fil_tablespace_iterate( iter.file_size = file_size; iter.n_io_buffers = n_io_buffers; iter.page_size = callback.get_page_size().physical(); + iter.table = table; /* read (optional) crypt data */ iter.crypt_data = fil_space_read_crypt_data( diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 8ebe4513b3f..3e1d9d3698e 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -355,6 +355,7 @@ fil_compress_page( if (allocated) { /* TODO: reduce number of memcpy's */ memcpy(buf, out_buf, len); + goto exit_free; } else { return(out_buf); } @@ -380,6 +381,7 @@ err_exit: srv_stats.pages_page_compression_error.inc(); *out_len = len; +exit_free: if (allocated) { ut_free(out_buf); #ifdef HAVE_LZO From 4b28798f950ccba16378720393277788792b4b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 25 Jan 2017 10:04:14 +0200 Subject: [PATCH 119/167] Fix compiler error on x86. --- storage/innobase/include/os0file.h | 2 +- storage/innobase/os/os0file.cc | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 0194a876cf3..68369a49c5f 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -434,7 +434,7 @@ public: dberr_t punch_hole( os_file_t fh, os_offset_t offset, - ulint len); + os_offset_t len); private: /** Page to be written on write operation. */ diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 9e41e698cb4..904d0c8273c 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -1887,7 +1887,10 @@ LinuxAIOHandler::collect() && slot->type.is_write() && slot->type.punch_hole()) { - slot->err = slot->type.punch_hole(slot->file, slot->offset, slot->len); + slot->err = slot->type.punch_hole( + slot->file, + slot->offset, + static_cast(slot->len)); } else { slot->err = DB_SUCCESS; } @@ -4825,8 +4828,8 @@ os_file_io( && type.is_write() && type.punch_hole()) { *err = type.punch_hole(file, - static_cast(offset), - n); + offset, + static_cast(n)); } else { *err = DB_SUCCESS; @@ -5494,7 +5497,7 @@ IORequest::punch_hole( return(DB_SUCCESS); ); - ulint trim_len = get_trim_length(len); + os_offset_t trim_len = static_cast(get_trim_length(len)); if (trim_len == 0) { return(DB_SUCCESS); @@ -5508,7 +5511,7 @@ IORequest::punch_hole( return DB_IO_NO_PUNCH_HOLE; } - dberr_t err = os_file_punch_hole(fh, off, len); + dberr_t err = os_file_punch_hole(fh, off, trim_len); if (err == DB_SUCCESS) { srv_stats.page_compressed_trim_op.inc(); From 8531e19771883b364fadc645801166425cc7c6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 25 Jan 2017 12:33:39 +0200 Subject: [PATCH 120/167] buf_page_t is class on 10.2 not struct. --- storage/innobase/include/os0api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/include/os0api.h b/storage/innobase/include/os0api.h index ea2a113bdec..63f213b5457 100644 --- a/storage/innobase/include/os0api.h +++ b/storage/innobase/include/os0api.h @@ -29,7 +29,7 @@ implemented on buf0buf.cc and fil0fil.cc. #define OS_API_H 1 /** Page control block */ -struct buf_page_t; +class buf_page_t; /** File Node */ struct fil_node_t; From 8afe4faab9e1ed8a2264cb309c02fca641be1990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Jan 2017 15:53:46 +0200 Subject: [PATCH 121/167] Fix fil_ibd_open() on Windows. In the merge of MDEV-11623 from 10.1 to 10.2, we added a call to fsp_flags_try_adjust() which causes the data file to be opened via the buffer pool while fil_ibd_open() is holding another open handle to the file. --- storage/innobase/fil/fil0fil.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index b6475e133ff..5907fa11b4d 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -4250,6 +4250,9 @@ skip_validate: } if (purpose != FIL_TYPE_IMPORT && !srv_read_only_mode) { + df_remote.close(); + df_dict.close(); + df_default.close(); fsp_flags_try_adjust(id, flags & ~FSP_FLAGS_MEM_MASK); } } From 0b1a40852cd9204b9ed7394bed67e95e02c96a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Jan 2017 15:59:37 +0200 Subject: [PATCH 122/167] Replace fil_node_t::is_open with fil_node_t::is_open(). This should be a non-functional change (apart from removing the redundant data field). --- storage/innobase/fil/fil0fil.cc | 48 ++++++++++++++++-------------- storage/innobase/include/fil0fil.h | 8 +++-- storage/innobase/include/os0file.h | 2 +- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 5907fa11b4d..b09d8ff873a 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -504,6 +504,8 @@ fil_node_create_low( node = reinterpret_cast(ut_zalloc_nokey(sizeof(*node))); + node->handle = OS_FILE_CLOSED; + node->name = mem_strdup(name); ut_a(!is_raw || srv_start_raw_disk_in_use); @@ -577,7 +579,7 @@ fil_node_open_file( ut_ad(mutex_own(&fil_system->mutex)); ut_a(node->n_pending == 0); - ut_a(!node->is_open); + ut_a(!node->is_open()); read_only_mode = !fsp_is_system_temporary(space->id) && srv_read_only_mode; @@ -747,8 +749,7 @@ retry: } ut_a(success); - - node->is_open = true; + ut_a(node->is_open()); fil_system->n_open++; fil_n_file_opened++; @@ -772,7 +773,7 @@ fil_node_close_file( bool ret; ut_ad(mutex_own(&(fil_system->mutex))); - ut_a(node->is_open); + ut_a(node->is_open()); ut_a(node->n_pending == 0); ut_a(node->n_pending_flushes == 0); ut_a(!node->being_extended); @@ -785,7 +786,8 @@ fil_node_close_file( /* printf("Closing file %s\n", node->name); */ - node->is_open = false; + node->handle = OS_FILE_CLOSED; + ut_ad(!node->is_open()); ut_a(fil_system->n_open > 0); fil_system->n_open--; fil_n_file_opened--; @@ -907,7 +909,7 @@ fil_flush_low(fil_space_t* space) continue; } - ut_a(node->is_open); + ut_a(node->is_open()); switch (space->purpose) { case FIL_TYPE_TEMPORARY: @@ -950,7 +952,7 @@ retry: goto retry; } - ut_a(node->is_open); + ut_a(node->is_open()); node->n_pending_flushes++; mutex_exit(&fil_system->mutex); @@ -1269,7 +1271,7 @@ fil_mutex_enter_and_prepare_for_io( the insert buffer. The insert buffer is in tablespace 0, and we cannot end up waiting in this function. */ - } else if (!node || node->is_open) { + } else if (!node || node->is_open()) { /* If the file is already open, no need to do anything; if the space does not exist, we handle the situation in the function which called this @@ -1374,7 +1376,7 @@ fil_node_close_to_free( ut_a(node->n_pending == 0); ut_a(!node->being_extended); - if (node->is_open) { + if (node->is_open()) { /* We fool the assertion in fil_node_close_file() to think there are no unflushed modifications in the file */ @@ -1887,7 +1889,7 @@ fil_space_open( node != NULL; node = UT_LIST_GET_NEXT(chain, node)) { - if (!node->is_open + if (!node->is_open() && !fil_node_open_file(node)) { mutex_exit(&fil_system->mutex); return(false); @@ -1921,7 +1923,7 @@ fil_space_close( node != NULL; node = UT_LIST_GET_NEXT(chain, node)) { - if (node->is_open) { + if (node->is_open()) { fil_node_close_file(node); } } @@ -2012,7 +2014,7 @@ fil_open_log_and_system_tablespace_files(void) node != NULL; node = UT_LIST_GET_NEXT(chain, node)) { - if (!node->is_open) { + if (!node->is_open()) { if (!fil_node_open_file(node)) { /* This func is called during server's startup. If some file of log or system @@ -2070,7 +2072,7 @@ fil_close_all_files(void) node != NULL; node = UT_LIST_GET_NEXT(chain, node)) { - if (node->is_open) { + if (node->is_open()) { fil_node_close_file(node); } } @@ -2116,7 +2118,7 @@ fil_close_log_files( node != NULL; node = UT_LIST_GET_NEXT(chain, node)) { - if (node->is_open) { + if (node->is_open()) { fil_node_close_file(node); } } @@ -3130,7 +3132,7 @@ fil_truncate_tablespace( fil_node_t* node = UT_LIST_GET_FIRST(space->chain); - ut_ad(node->is_open); + ut_ad(node->is_open()); space->size = node->size = size_in_pages; @@ -3544,7 +3546,7 @@ func_exit: } else if (node->modification_counter > node->flush_counter) { /* Flush the space */ sleep = flush = true; - } else if (node->is_open) { + } else if (node->is_open()) { /* Close the file */ fil_node_close_file(node); @@ -4936,7 +4938,7 @@ fil_node_prepare_for_io( << " exceeds the limit " << system->max_n_open; } - if (!node->is_open) { + if (!node->is_open()) { /* File is closed: open it */ ut_a(node->n_pending == 0); @@ -5485,8 +5487,8 @@ struct Check { @param[in] elem file node to visit */ void operator()(const fil_node_t* elem) { - ut_a(elem->is_open || !elem->n_pending); - n_open += elem->is_open; + ut_a(elem->is_open() || !elem->n_pending); + n_open += elem->is_open(); size += elem->size; } @@ -5540,7 +5542,7 @@ fil_validate(void) ut_a(fil_node->n_pending == 0); ut_a(!fil_node->being_extended); - ut_a(fil_node->is_open); + ut_a(fil_node->is_open()); ut_a(fil_space_belongs_in_lru(fil_node->space)); } @@ -6499,7 +6501,7 @@ truncate_t::truncate( space->size = node->size = FIL_IBD_FILE_INITIAL_SIZE; } - const bool already_open = node->is_open; + const bool already_open = node->is_open(); if (!already_open) { @@ -6520,7 +6522,7 @@ truncate_t::truncate( return(DB_ERROR); } - node->is_open = true; + ut_a(node->is_open()); } os_offset_t trunc_size = trunc_to_default @@ -6550,7 +6552,7 @@ truncate_t::truncate( err = DB_ERROR; } else { - node->is_open = false; + node->handle = OS_FILE_CLOSED; } } diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index bd6067fbbee..e3df97d028c 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -201,8 +201,6 @@ struct fil_node_t { fil_space_t* space; /** file name; protected by fil_system->mutex and log_sys->mutex. */ char* name; - /** whether this file is open */ - bool is_open; /** file handle (valid if is_open) */ os_file_t handle; /** event that groups and serializes calls to fsync */ @@ -241,6 +239,12 @@ struct fil_node_t { /** FIL_NODE_MAGIC_N */ ulint magic_n; + + /** @return whether this file is open */ + bool is_open() const + { + return(handle != OS_FILE_CLOSED); + } }; /** Value of fil_node_t::magic_n */ diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 68369a49c5f..4e980c42f85 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -80,7 +80,7 @@ the OS actually supports it: Win 95 does not, NT does. */ # define UNIV_NON_BUFFERED_IO /** File handle */ -# define os_file_t HANDLE +typedef HANDLE os_file_t; /** Convert a C file descriptor to a native file handle @param fd file descriptor From e92ee13254f291623c9d95004e51f8845759a256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Jan 2017 16:05:32 +0200 Subject: [PATCH 123/167] Import and adjust a test from MySQL 5.7. --- .../suite/innodb/r/log_alter_table.result | 16 ++++++ .../suite/innodb/t/log_alter_table.test | 51 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 mysql-test/suite/innodb/r/log_alter_table.result create mode 100644 mysql-test/suite/innodb/t/log_alter_table.test diff --git a/mysql-test/suite/innodb/r/log_alter_table.result b/mysql-test/suite/innodb/r/log_alter_table.result new file mode 100644 index 00000000000..f1ee61e7572 --- /dev/null +++ b/mysql-test/suite/innodb/r/log_alter_table.result @@ -0,0 +1,16 @@ +# +# Bug#21801423 INNODB REDO LOG DOES NOT INDICATE WHEN +# FILES ARE CREATED +# +# Bug#21796691 INNODB REDO LOG DOES NOT INDICATE WHEN +# REDO LOGGING IS SKIPPED +# +CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,2); +ALTER TABLE t1 ADD PRIMARY KEY(a), ALGORITHM=INPLACE; +ALTER TABLE t1 DROP INDEX b, ADD INDEX (b); +# Kill the server +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/log_alter_table.test b/mysql-test/suite/innodb/t/log_alter_table.test new file mode 100644 index 00000000000..f479c6695aa --- /dev/null +++ b/mysql-test/suite/innodb/t/log_alter_table.test @@ -0,0 +1,51 @@ +--source include/have_innodb.inc +--source include/have_debug.inc + +# Embedded server does not support crashing +--source include/not_embedded.inc + +--echo # +--echo # Bug#21801423 INNODB REDO LOG DOES NOT INDICATE WHEN +--echo # FILES ARE CREATED +--echo # +--echo # Bug#21796691 INNODB REDO LOG DOES NOT INDICATE WHEN +--echo # REDO LOGGING IS SKIPPED +--echo # +--source include/no_checkpoint_start.inc +CREATE TABLE t1 (a INT NOT NULL, b INT UNIQUE) ENGINE=InnoDB; +# MLOG_INDEX_LOAD will not be emitted for empty tables. Insert a row. +INSERT INTO t1 VALUES (1,2); +# We should get two MLOG_INDEX_LOAD for this. +ALTER TABLE t1 ADD PRIMARY KEY(a), ALGORITHM=INPLACE; +# And one MLOG_INDEX_LOAD for this. +ALTER TABLE t1 DROP INDEX b, ADD INDEX (b); + +--let CLEANUP_IF_CHECKPOINT=DROP TABLE t1; +--source include/no_checkpoint_end.inc + +--let $restart_parameters= --debug=d,ib_log +--source include/start_mysqld.inc + +let SEARCH_RANGE = -50000; +let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_ABORT=NOT FOUND; +# Look for at least one MLOG_FILE_CREATE2 in the error log. +# Theoretically, it may have been written by this test or an earlier test. +# FIXME: redirect the error log of the restart to a new file, +# and ensure that we have exactly 2 records there. +let SEARCH_PATTERN=scan .*: multi-log rec MLOG_FILE_CREATE2.*page .*:0; +--source include/search_pattern_in_file.inc +# Look for at least one MLOG_INDEX_LOAD in the error log. +# Theoretically, it may have been written by this test or an earlier test. +# FIXME: redirect the error log of the restart to a new file, +# and ensure that we have exactly 3 records there. +let SEARCH_PATTERN=scan .*: log rec MLOG_INDEX_LOAD; +--source include/search_pattern_in_file.inc + +CHECK TABLE t1; + +# Remove the --debug=d,ib_log setting. +--let $restart_parameters= +--source include/restart_mysqld.inc + +DROP TABLE t1; From c6039a11c60c5464ceb4b989bffad8a4a9f926d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Jan 2017 16:38:45 +0200 Subject: [PATCH 124/167] Fix a test. --- .../suite/innodb/include/innodb_simulate_comp_failures.inc | 2 +- .../suite/innodb/r/innodb_simulate_comp_failures.result | 1 + storage/innobase/page/page0zip.cc | 5 ++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc index 28f2b7d1000..6aaa9cd07a9 100644 --- a/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc +++ b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc @@ -8,7 +8,7 @@ --let $simulate_comp_failures_save = `SELECT @@innodb_simulate_comp_failures` # since this test generates lot of errors in log, suppress checking errors -call mtr.add_suppression(".*"); +call mtr.add_suppression("InnoDB: Simulating a compression failure for table `test`\\.`t1`"); --enable_query_log # create the table with compressed pages of size 8K. diff --git a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result index f35e4159603..4ed6ca14f26 100644 --- a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result +++ b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result @@ -1,6 +1,7 @@ # # Testing robustness against random compression failures # +call mtr.add_suppression("InnoDB: Simulating a compression failure for table `test`\\.`t1`"); CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; SHOW CREATE TABLE t1; Table Create Table diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 35ef24c16a6..d49cecdb968 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -1388,9 +1388,8 @@ page_zip_compress( #ifdef UNIV_DEBUG ib::error() - << "InnoDB: Simulating a compression failure" - << " for table " - << (index->table->name.m_name) + << "Simulating a compression failure" + << " for table " << index->table->name << " index " << index->name() << " page " From 45f451c769668e6a351b0c023a994fdf9c07b1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 20 Jan 2017 12:10:13 +0200 Subject: [PATCH 125/167] MDEV-11850: Can't create foreign key referencing a virtual column Both dict_foreign_find_index and dict_foreign_qualify_index did not consider virtual columns as possible foreign key columns and there was assertion to disable virtual columns. Fixed by also looking referencing and referenced column from virtual columns if needed. --- .../suite/innodb/r/innodb-fk-virtual.result | 86 +++++++++++++++++++ .../suite/innodb/t/innodb-fk-virtual.test | 61 +++++++++++++ storage/innobase/dict/dict0dict.cc | 34 ++++++-- 3 files changed, 175 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb-fk-virtual.result create mode 100644 mysql-test/suite/innodb/t/innodb-fk-virtual.test diff --git a/mysql-test/suite/innodb/r/innodb-fk-virtual.result b/mysql-test/suite/innodb/r/innodb-fk-virtual.result new file mode 100644 index 00000000000..a79cd133aa3 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-fk-virtual.result @@ -0,0 +1,86 @@ +create or replace table a ( +cola int(10) primary key, +v_cola int(10) as (cola mod 10) virtual, +p_cola int(10) as (cola mod 10) persistent +) engine=innodb; +create index v_cola on a (v_cola); +create index p_cola on a (p_cola); +create or replace table b( +cola int(10), +v_cola int(10), +p_cola int(10), +c_cola int(10) as (cola + 2) virtual +) engine=innodb; +alter table b add constraint `p_cola_fk` +foreign key (p_cola) references a (p_cola) +on delete restrict +on update restrict; +show warnings; +Level Code Message +show create table b; +Table Create Table +b CREATE TABLE `b` ( + `cola` int(10) DEFAULT NULL, + `v_cola` int(10) DEFAULT NULL, + `p_cola` int(10) DEFAULT NULL, + `c_cola` int(10) GENERATED ALWAYS AS (`cola` + 2) VIRTUAL, + KEY `p_cola_fk` (`p_cola`), + CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +alter table b add constraint `v_cola_fk` +foreign key (v_cola) references a (v_cola) +on delete restrict +on update restrict; +show warnings; +Level Code Message +show create table b; +Table Create Table +b CREATE TABLE `b` ( + `cola` int(10) DEFAULT NULL, + `v_cola` int(10) DEFAULT NULL, + `p_cola` int(10) DEFAULT NULL, + `c_cola` int(10) GENERATED ALWAYS AS (`cola` + 2) VIRTUAL, + KEY `p_cola_fk` (`p_cola`), + KEY `v_cola_fk` (`v_cola`), + CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`), + CONSTRAINT `v_cola_fk` FOREIGN KEY (`v_cola`) REFERENCES `a` (`v_cola`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +alter table b add constraint `c_cola_fk` +foreign key (c_cola) references a (cola) +on delete restrict +on update restrict; +show warnings; +Level Code Message +show create table b; +Table Create Table +b CREATE TABLE `b` ( + `cola` int(10) DEFAULT NULL, + `v_cola` int(10) DEFAULT NULL, + `p_cola` int(10) DEFAULT NULL, + `c_cola` int(10) GENERATED ALWAYS AS (`cola` + 2) VIRTUAL, + KEY `p_cola_fk` (`p_cola`), + KEY `v_cola_fk` (`v_cola`), + KEY `c_cola_fk` (`c_cola`), + CONSTRAINT `c_cola_fk` FOREIGN KEY (`c_cola`) REFERENCES `a` (`cola`), + CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`), + CONSTRAINT `v_cola_fk` FOREIGN KEY (`v_cola`) REFERENCES `a` (`v_cola`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +insert into a(cola) values (12); +select * from a; +cola v_cola p_cola +12 2 2 +insert into b(cola, v_cola, p_cola) values (10,2,2); +select * from b; +cola v_cola p_cola c_cola +10 2 2 12 +insert into b(cola, v_cola, p_cola) values (10,1,1); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`b`, CONSTRAINT `p_cola_fk` FOREIGN KEY (`p_cola`) REFERENCES `a` (`p_cola`)) +delete from a; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`b`, CONSTRAINT `c_cola_fk` FOREIGN KEY (`c_cola`) REFERENCES `a` (`cola`)) +select * from a; +cola v_cola p_cola +12 2 2 +select * from b; +cola v_cola p_cola c_cola +10 2 2 12 +drop table b, a; diff --git a/mysql-test/suite/innodb/t/innodb-fk-virtual.test b/mysql-test/suite/innodb/t/innodb-fk-virtual.test new file mode 100644 index 00000000000..094fda35abb --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-fk-virtual.test @@ -0,0 +1,61 @@ +--source include/have_innodb.inc + +# +# MDEV-11850: Can't create foreign key referencing a virtual column +# + +create or replace table a ( + cola int(10) primary key, + v_cola int(10) as (cola mod 10) virtual, + p_cola int(10) as (cola mod 10) persistent +) engine=innodb; + +create index v_cola on a (v_cola); +create index p_cola on a (p_cola); + +create or replace table b( +cola int(10), +v_cola int(10), +p_cola int(10), +c_cola int(10) as (cola + 2) virtual +) engine=innodb; + +alter table b add constraint `p_cola_fk` +foreign key (p_cola) references a (p_cola) +on delete restrict +on update restrict; + +show warnings; +show create table b; + +alter table b add constraint `v_cola_fk` +foreign key (v_cola) references a (v_cola) +on delete restrict +on update restrict; + +show warnings; +show create table b; + +alter table b add constraint `c_cola_fk` +foreign key (c_cola) references a (cola) +on delete restrict +on update restrict; + +show warnings; +show create table b; + +# +# Test that fk really works +# + +insert into a(cola) values (12); +select * from a; +insert into b(cola, v_cola, p_cola) values (10,2,2); +select * from b; +--error 1452 +insert into b(cola, v_cola, p_cola) values (10,1,1); +--error 1451 +delete from a; +select * from a; +select * from b; +drop table b, a; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 73c7bf027ca..21380cffae3 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -3518,7 +3518,6 @@ dict_foreign_find_index( if (types_idx != index && !(index->type & DICT_FTS) && !dict_index_is_spatial(index) - && !dict_index_has_virtual(index) && !index->to_be_dropped && dict_foreign_qualify_index( table, col_names, columns, n_cols, @@ -4026,6 +4025,23 @@ dict_scan_col( break; } } + + for (i = 0; i < dict_table_get_n_v_cols(table); i++) { + + const char* col_name = dict_table_get_v_col_name( + table, i); + + if (0 == innobase_strcasecmp(col_name, *name)) { + /* Found */ + dict_v_col_t * vcol; + *success = TRUE; + vcol = dict_table_get_nth_v_col(table, i); + *column = &vcol->m_col; + strcpy((char*) *name, col_name); + + break; + } + } } return(ptr); @@ -5010,9 +5026,7 @@ col_loop1: for (i = 0; i < foreign->n_fields; i++) { foreign->foreign_col_names[i] = mem_heap_strdup( - foreign->heap, - dict_table_get_col_name(table, - dict_col_get_no(columns[i]))); + foreign->heap, column_names[i]); } ptr = dict_scan_table_name(cs, ptr, &referenced_table, name, @@ -5330,6 +5344,7 @@ try_find_index: ref_column_names, i, foreign->foreign_index, TRUE, FALSE, &index_error, &err_col, &err_index); + if (!index) { mutex_enter(&dict_foreign_err_mutex); dict_foreign_error_report_low(ef, create_name); @@ -7032,8 +7047,6 @@ dict_foreign_qualify_index( field = dict_index_get_nth_field(index, i); col_no = dict_col_get_no(field->col); - ut_ad(!dict_col_is_virtual(field->col)); - if (field->prefix_len != 0) { /* We do not accept column prefix indexes here */ @@ -7059,6 +7072,15 @@ dict_foreign_qualify_index( ? col_names[col_no] : dict_table_get_col_name(table, col_no); + if (dict_col_is_virtual(field->col)) { + for (ulint j = 0; j < table->n_v_def; j++) { + col_name = dict_table_get_v_col_name(table, j); + if (innobase_strcasecmp(field->name,col_name) == 0) { + break; + } + } + } + if (0 != innobase_strcasecmp(columns[i], col_name)) { return(false); } From 71495a1748784a887f42888a2a7b8cac5e088ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 25 Jan 2017 10:11:37 +0200 Subject: [PATCH 126/167] MDEV-11849: Fix storage/innobase/* compile warnings --- cmake/lz4.cmake | 10 +++++++- storage/innobase/btr/btr0cur.cc | 2 +- storage/innobase/btr/btr0scrub.cc | 9 ++++--- storage/innobase/dict/dict0crea.cc | 6 ++--- storage/innobase/fil/fil0crypt.cc | 8 +++--- storage/innobase/fil/fil0fil.cc | 14 ++++++----- storage/innobase/fil/fil0pagecompress.cc | 10 ++++++-- storage/innobase/fsp/fsp0fsp.cc | 1 - storage/innobase/handler/ha_innodb.cc | 10 ++------ storage/innobase/handler/handler0alter.cc | 5 +--- storage/innobase/include/data0data.ic | 1 - storage/innobase/include/dict0dict.h | 19 -------------- storage/innobase/include/dict0dict.ic | 1 - storage/innobase/include/fil0fil.h | 11 +++++---- storage/innobase/include/lock0lock.h | 3 +-- storage/innobase/include/row0merge.h | 4 +-- storage/innobase/include/row0row.ic | 4 +-- storage/innobase/include/ut0timer.ic | 2 +- storage/innobase/lock/lock0lock.cc | 3 +++ storage/innobase/log/log0crypt.cc | 11 ++++----- storage/innobase/log/log0log.cc | 2 +- storage/innobase/os/os0file.cc | 30 +---------------------- storage/innobase/row/row0log.cc | 2 +- storage/innobase/row/row0merge.cc | 30 +++++++++++------------ storage/innobase/row/row0mysql.cc | 7 +++--- storage/innobase/row/row0sel.cc | 2 +- storage/innobase/sync/sync0arr.cc | 2 +- storage/innobase/sync/sync0rw.cc | 2 +- 28 files changed, 86 insertions(+), 125 deletions(-) diff --git a/cmake/lz4.cmake b/cmake/lz4.cmake index 1607c68c5fb..075904589f0 100644 --- a/cmake/lz4.cmake +++ b/cmake/lz4.cmake @@ -19,9 +19,13 @@ MACRO (MYSQL_CHECK_LZ4) IF (WITH_INNODB_LZ4 STREQUAL "ON" OR WITH_INNODB_LZ4 STREQUAL "AUTO") CHECK_INCLUDE_FILES(lz4.h HAVE_LZ4_H) CHECK_LIBRARY_EXISTS(lz4 LZ4_compress_limitedOutput "" HAVE_LZ4_SHARED_LIB) + CHECK_LIBRARY_EXISTS(lz4 LZ4_compress_default "" HAVE_LZ4_COMPRESS_DEFAULT) IF (HAVE_LZ4_SHARED_LIB AND HAVE_LZ4_H) ADD_DEFINITIONS(-DHAVE_LZ4=1) + IF (HAVE_LZ4_COMPRESS_DEFAULT) + ADD_DEFINITIONS(-DHAVE_LZ4_COMPRESS_DEFAULT=1) + ENDIF() LINK_LIBRARIES(lz4) ELSE() IF (WITH_INNODB_LZ4 STREQUAL "ON") @@ -35,9 +39,13 @@ MACRO (MYSQL_CHECK_LZ4_STATIC) IF (WITH_INNODB_LZ4 STREQUAL "ON" OR WITH_INNODB_LZ4 STREQUAL "AUTO") CHECK_INCLUDE_FILES(lz4.h HAVE_LZ4_H) CHECK_LIBRARY_EXISTS(liblz4.a LZ4_compress_limitedOutput "" HAVE_LZ4_LIB) + CHECK_LIBRARY_EXISTS(liblz3.a LZ4_compress_default "" HAVE_LZ4_COMPRESS_DEFAULT) IF(HAVE_LZ4_LIB AND HAVE_LZ4_H) ADD_DEFINITIONS(-DHAVE_LZ4=1) + IF (HAVE_LZ4_COMPRESS_DEFAULT) + ADD_DEFINITIONS(-DHAVE_LZ4_COMPRESS_DEFAULT=1) + ENDIF() LINK_LIBRARIES(liblz4.a) ELSE() IF (WITH_INNODB_LZ4 STREQUAL "ON") @@ -45,4 +53,4 @@ MACRO (MYSQL_CHECK_LZ4_STATIC) ENDIF() ENDIF() ENDIF() -ENDMACRO() \ No newline at end of file +ENDMACRO() diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 4d0499418a2..8b139d58b96 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3638,7 +3638,7 @@ btr_cur_update_in_place( #ifdef UNIV_DEBUG { rec_printer p(rec, offsets); - DBUG_PRINT("ib_cur", ("update-in-place %s (" IB_ID_FMT ") by "IB_ID_FMT ": %s", + DBUG_PRINT("ib_cur", ("update-in-place %s (" IB_ID_FMT ") by " IB_ID_FMT ": %s", index->name(), index->id, trx_id, p.str().c_str())); } diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc index f361a9d8b1e..8051c517e3a 100644 --- a/storage/innobase/btr/btr0scrub.cc +++ b/storage/innobase/btr/btr0scrub.cc @@ -121,8 +121,8 @@ bool btr_scrub_lock_dict_func(ulint space, bool lock_to_close_table, const char * file, uint line) { - uint start = time(0); - uint last = start; + time_t start = time(0); + time_t last = start; while (mutex_enter_nowait(&(dict_sys->mutex))) { /* if we lock to close a table, we wait forever @@ -136,10 +136,11 @@ btr_scrub_lock_dict_func(ulint space, bool lock_to_close_table, } os_thread_sleep(250000); - uint now = time(0); + time_t now = time(0); + if (now >= last + 30) { fprintf(stderr, - "WARNING: %s:%u waited %u seconds for" + "WARNING: %s:%u waited %lu seconds for" " dict_sys lock, space: %lu" " lock_to_close_table: %u\n", file, line, now - start, space, diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index c5d8e7ee21f..9321faed9c6 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -2007,7 +2007,7 @@ dict_foreign_def_get( char* fk_def = (char *)mem_heap_alloc(foreign->heap, 4*1024); const char* tbname; char tablebuf[MAX_TABLE_NAME_LEN + 1] = ""; - int i; + unsigned i; char* bufend; tbname = dict_remove_db_name(foreign->id); @@ -2025,7 +2025,7 @@ dict_foreign_def_get( strlen(foreign->foreign_col_names[i]), trx->mysql_thd); strcat(fk_def, buf); - if (i < foreign->n_fields-1) { + if (i < static_cast(foreign->n_fields-1)) { strcat(fk_def, (char *)","); } } @@ -2049,7 +2049,7 @@ dict_foreign_def_get( trx->mysql_thd); buf[bufend - buf] = '\0'; strcat(fk_def, buf); - if (i < foreign->n_fields-1) { + if (i < (uint)foreign->n_fields-1) { strcat(fk_def, (char *)","); } } diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index c5bae8a2b85..7f545cb4060 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1200,7 +1200,7 @@ struct rotate_thread_t { uint estimated_max_iops; /*!< estimation of max iops */ uint allocated_iops; /*!< allocated iops */ uint cnt_waited; /*!< #times waited during this slot */ - uint sum_waited_us; /*!< wait time during this slot */ + uintmax_t sum_waited_us; /*!< wait time during this slot */ fil_crypt_stat_t crypt_stat; // statistics @@ -2457,8 +2457,8 @@ fil_space_crypt_close_tablespace( return; } - uint start = time(0); - uint last = start; + time_t start = time(0); + time_t last = start; mutex_enter(&crypt_data->mutex); mutex_exit(&fil_crypt_threads_mutex); @@ -2480,7 +2480,7 @@ fil_space_crypt_close_tablespace( cnt = crypt_data->rotate_state.active_threads; flushing = crypt_data->rotate_state.flushing; - uint now = time(0); + time_t now = time(0); if (now >= last + 30) { ib::warn() << "Waited " diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index b09d8ff873a..18252b64a78 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -703,7 +703,7 @@ retry: extent_size); } - node->size = size_bytes / psize; + node->size = static_cast(size_bytes / psize); space->size += node->size; } } @@ -6892,7 +6892,7 @@ fil_node_t* fil_space_get_node( fil_space_t* space, /*!< in: file spage */ ulint space_id, /*!< in: space id */ - ulint* block_offset, /*!< in/out: offset in number of blocks */ + os_offset_t* block_offset, /*!< in/out: offset in number of blocks */ ulint byte_offset, /*!< in: remainder of offset in bytes; in aio this must be divisible by the OS block size */ @@ -6928,14 +6928,16 @@ fil_space_get_node( /********************************************************************//** Return block size of node in file space +@param[in] space_id space id +@param[in] block_offset page offset +@param[in] len page len @return file block size */ UNIV_INTERN ulint fil_space_get_block_size( -/*=====================*/ - ulint space_id, - ulint block_offset, - ulint len) + ulint space_id, + os_offset_t block_offset, + ulint len) { ulint block_size = 512; ut_ad(!mutex_own(&fil_system->mutex)); diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 3e1d9d3698e..18f95c94d75 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -162,8 +162,14 @@ fil_compress_page( switch(comp_method) { #ifdef HAVE_LZ4 case PAGE_LZ4_ALGORITHM: + +#ifdef HAVE_LZ4_COMPRESS_DEFAULT + err = LZ4_compress_default((const char *)buf, + (char *)out_buf+header_len, len, write_size); +#else err = LZ4_compress_limitedOutput((const char *)buf, (char *)out_buf+header_len, len, write_size); +#endif /* HAVE_LZ4_COMPRESS_DEFAULT */ write_size = err; if (err == 0) { @@ -414,7 +420,7 @@ fil_decompress_page( { int err = 0; ulint actual_size = 0; - ulint compression_alg = 0; + ib_uint64_t compression_alg = 0; byte *in_buf; ulint ptype; ulint header_len; @@ -463,7 +469,7 @@ fil_decompress_page( /* Get compression algorithm */ if (ptype == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { - compression_alg = mach_read_from_2(buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE); + compression_alg = static_cast(mach_read_from_2(buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE)); } else { compression_alg = mach_read_from_8(buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION); } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 27990e8243e..6886c5164f7 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -3262,7 +3262,6 @@ fseg_free_extent( ulint descr_n_used; ulint i; - ut_ad(seg_inode != NULL); ut_ad(mtr != NULL); descr = xdes_get_descriptor(space, page, page_size, mtr); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 271abc3e86d..5ed02a92e0e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5499,14 +5499,8 @@ innobase_kill_query( trx_mutex_taken = true; } -#ifdef UNIV_DEBUG - dberr_t err = -#endif lock_trx_handle_wait(trx, true, true); - ut_ad(err == DB_SUCCESS || err == DB_LOCK_WAIT - || err == DB_DEADLOCK); - if (lock_mutex_taken) { lock_mutex_exit(); } @@ -11950,7 +11944,7 @@ err_col: err = row_create_table_for_mysql( table, m_trx, false, (fil_encryption_t)options->encryption, - options->encryption_key_id); + (ulint)options->encryption_key_id); } @@ -12904,7 +12898,7 @@ index_bad: m_use_data_dir, options->page_compressed, options->page_compression_level == 0 ? - default_compression_level : options->page_compression_level, + default_compression_level : static_cast(options->page_compression_level), 0); /* Set the flags2 when create table or alter tables */ diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 341c341f112..a2fbb47c46d 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -5166,9 +5166,6 @@ innobase_check_foreign_key_index( ulint n_drop_fk) /*!< in: Number of foreign keys to drop */ { - ut_ad(index != NULL); - ut_ad(indexed_table != NULL); - const dict_foreign_set* fks = &indexed_table->referenced_set; /* Check for all FK references from other tables to the index. */ @@ -7257,7 +7254,7 @@ innobase_enlarge_columns_try( == IS_EQUAL_PACK_LENGTH && innobase_enlarge_column_try( user_table, trx, table_name, - idx, cf->length, is_v)) { + idx, static_cast(cf->length), is_v)) { return(true); } diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic index 71698cc12b3..2fe5190591b 100644 --- a/storage/innobase/include/data0data.ic +++ b/storage/innobase/include/data0data.ic @@ -467,7 +467,6 @@ dtuple_create_from_mem( dtuple_t* tuple; ulint n_t_fields = n_fields + n_v_fields; - ut_ad(buf != NULL); ut_a(buf_size >= DTUPLE_EST_ALLOC(n_t_fields)); tuple = (dtuple_t*) buf; diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 6e86cd3eb4a..77a2013927e 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -1006,25 +1006,6 @@ dict_tf_set( ulint page_compression_level, ulint not_used); -/** Initialize a dict_table_t::flags pointer. -@param[in] compact, Table uses Compact or greater -@param[in] zip_ssize Zip Shift Size (log 2 minus 9) -@param[in] atomic_blobs Table uses Compressed or Dynamic -@param[in] data_dir Table uses DATA DIRECTORY -@param[in] page_compressed Table uses page compression -@param[in] page_compression_level Page compression level -@param[in] not_used For future */ -UNIV_INLINE -ulint -dict_tf_init( - bool compact, - ulint zip_ssize, - bool atomic_blobs, - bool data_dir, - bool page_compressed, - ulint page_compression_level, - ulint not_used); - /** Convert a 32 bit integer table flags to the 32 bit FSP Flags. Fsp Flags are written into the tablespace header at the offset FSP_SPACE_FLAGS and are also stored in the fil_space_t::flags field. diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index a75f0b245af..905a1b78782 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1242,7 +1242,6 @@ ulint dict_index_get_n_unique_in_tree_nonleaf( const dict_index_t* index) { - ut_ad(index != NULL); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); ut_ad(index->cached); diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index e3df97d028c..047e43d34e4 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1572,15 +1572,16 @@ void test_make_filepath(); /*******************************************************************//** Returns the block size of the file space +@param[in] space_id space id +@param[in] offset page offset +@param[in] len page len @return block size */ UNIV_INTERN ulint fil_space_get_block_size( -/*=====================*/ - ulint id, /*!< in: space id */ - ulint offset, /*!< in: page offset */ - ulint len); /*!< in: page len */ - + ulint id, + os_offset_t offset, + ulint len); /*******************************************************************//** Increments the count of pending operation, if space is not being deleted. @return TRUE if being deleted, and operation should be skipped */ diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index f6bbd571907..16ef863f6a7 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -892,8 +892,7 @@ lock_trx_handle_wait( /*=================*/ trx_t* trx, /*!< in/out: trx lock state */ bool lock_mutex_taken, - bool trx_mutex_taken) - MY_ATTRIBUTE((nonnull(1), warn_unused_result)); + bool trx_mutex_taken); /*********************************************************************//** Get the number of locks on a table. @return number of locks */ diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h index 8cb9eb7976e..9e71ee42bb0 100644 --- a/storage/innobase/include/row0merge.h +++ b/storage/innobase/include/row0merge.h @@ -431,8 +431,8 @@ row_merge_sort( row_merge_block_t* block, int* tmpfd, const bool update_progress, - const float pct_progress, - const float pct_cost, + const double pct_progress, + const double pct_cost, fil_space_crypt_t* crypt_data, row_merge_block_t* crypt_block, ulint space, diff --git a/storage/innobase/include/row0row.ic b/storage/innobase/include/row0row.ic index 9243fae839a..8a32bb3ffd2 100644 --- a/storage/innobase/include/row0row.ic +++ b/storage/innobase/include/row0row.ic @@ -201,13 +201,13 @@ row_parse_int( case DATA_FLOAT: ut_a(len == sizeof(float)); - value = mach_float_read(data); + value = static_cast(mach_float_read(data)); break; case DATA_DOUBLE: ut_a(len == sizeof(double)); - value = mach_double_read(data); + value = static_cast(mach_double_read(data)); break; default: diff --git a/storage/innobase/include/ut0timer.ic b/storage/innobase/include/ut0timer.ic index 027e89c6279..46dcd0cb718 100644 --- a/storage/innobase/include/ut0timer.ic +++ b/storage/innobase/include/ut0timer.ic @@ -106,7 +106,7 @@ ut_microseconds_to_timer( /*=====================*/ ulonglong when) /*!< in: time where to calculate */ { - double ret = when; + double ret = (double)when; ret *= (double)(ut_timer.frequency); ret /= 1000000.0; return (ulonglong)ret; diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 379d00b00d7..3916bf9961f 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -7770,6 +7770,9 @@ lock_trx_handle_wait( trx_mutex_exit(trx); } + ut_ad(err == DB_SUCCESS || err == DB_LOCK_WAIT + || err == DB_DEADLOCK); + return(err); } diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc index 3a4447d2b85..b0a89be8de2 100644 --- a/storage/innobase/log/log0crypt.cc +++ b/storage/innobase/log/log0crypt.cc @@ -142,14 +142,13 @@ log_crypt_print_checkpoint_keys( ib_uint64_t checkpoint_no = log_block_get_checkpoint_no(log_block); if (crypt_info.size()) { - fprintf(stderr, "InnoDB: redo log checkpoint: %lu [ chk key ]: ", (ulong) checkpoint_no); + ib::info() << "Redo log checkpoint encryption: " << checkpoint_no << " [ chk key ]: "; for (size_t i = 0; i < crypt_info.size(); i++) { struct crypt_info_t* it = &crypt_info[i]; - fprintf(stderr, "[ %lu %u ] ", - (ulong) it->checkpoint_no, - it->key_version); + ib::info() << "[" << it->checkpoint_no + << "," << it->key_version + << "]"; } - fprintf(stderr, "\n"); } } @@ -498,7 +497,7 @@ log_crypt_write_checkpoint_buf( buf += 2; for (size_t i = 0; i < crypt_info.size(); i++) { struct crypt_info_t* it = &crypt_info[i]; - mach_write_to_4(buf + 0, it->checkpoint_no); + mach_write_to_4(buf + 0, static_cast(it->checkpoint_no)); mach_write_to_4(buf + 4, it->key_version); memcpy(buf + 8, it->crypt_msg, MY_AES_BLOCK_SIZE); memcpy(buf + 24, it->crypt_nonce, MY_AES_BLOCK_SIZE); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 39afc4e9680..95e64784718 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2596,7 +2596,7 @@ DECLARE_THREAD(log_scrub_thread)(void*) /* log scrubbing interval in µs. */ ulonglong interval = 1000*1000*512/innodb_scrub_log_speed; - os_event_wait_time(log_scrub_event, interval); + os_event_wait_time(log_scrub_event, static_cast(interval)); log_scrub(); diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 904d0c8273c..0cf0e0545c3 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2755,43 +2755,15 @@ os_file_readdir_next_file( int ret; struct stat statinfo; -#ifdef HAVE_READDIR_R - char dirent_buf[sizeof(struct dirent) - + _POSIX_PATH_MAX + 100]; - /* In /mysys/my_lib.c, _POSIX_PATH_MAX + 1 is used as - the max file name len; but in most standards, the - length is NAME_MAX; we add 100 to be even safer */ -#endif /* HAVE_READDIR_R */ - next_file: -#ifdef HAVE_READDIR_R - ret = readdir_r(dir, (struct dirent*) dirent_buf, &ent); - - if (ret != 0) { - - ib::error() - << "Cannot read directory " << dirname - << " error: " << ret; - - return(-1); - } - - if (ent == NULL) { - /* End of directory */ - - return(1); - } - - ut_a(strlen(ent->d_name) < _POSIX_PATH_MAX + 100 - 1); -#else ent = readdir(dir); if (ent == NULL) { return(1); } -#endif /* HAVE_READDIR_R */ + ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH); if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) { diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 9de1277e712..d43fb333cdc 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -526,7 +526,7 @@ err_exit: my_atomic_addlint(&onlineddl_rowlog_rows, 1); /* 10000 means 100.00%, 4525 means 45.25% */ - onlineddl_rowlog_pct_used = (log->tail.total * 10000) / srv_online_max_size; + onlineddl_rowlog_pct_used = static_cast((log->tail.total * 10000) / srv_online_max_size); } #ifdef UNIV_DEBUG diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index fbcb6149add..57dd8f75e8e 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -378,9 +378,9 @@ row_merge_insert_index_tuples( const row_merge_buf_t* row_buf, BtrBulk* btr_bulk, const ib_uint64_t table_total_rows, /*!< in: total rows of old table */ - const float pct_progress, /*!< in: total progress + const double pct_progress, /*!< in: total progress percent until now */ - const float pct_cost, /*!< in: current progress percent + const double pct_cost, /*!< in: current progress percent */ fil_space_crypt_t* crypt_data,/*!< in: table crypt data */ row_merge_block_t* crypt_block, /*!< in: crypt buf or NULL */ @@ -1820,7 +1820,7 @@ row_merge_read_clustered_index( bool skip_pk_sort, int* tmpfd, ut_stage_alter_t* stage, - float pct_cost, + double pct_cost, fil_space_crypt_t* crypt_data, row_merge_block_t* crypt_block, struct TABLE* eval_table) @@ -1855,7 +1855,7 @@ row_merge_read_clustered_index( mtuple_t prev_mtuple; mem_heap_t* conv_heap = NULL; FlushObserver* observer = trx->flush_observer; - float curr_progress = 0.0; + double curr_progress = 0.0; ib_uint64_t read_rows = 0; ib_uint64_t table_total_rows = 0; @@ -3268,10 +3268,10 @@ row_merge_sort( const bool update_progress, /*!< in: update progress status variable or not */ - const float pct_progress, + const double pct_progress, /*!< in: total progress percent until now */ - const float pct_cost, /*!< in: current progress percent */ + const double pct_cost, /*!< in: current progress percent */ fil_space_crypt_t* crypt_data,/*!< in: table crypt data */ row_merge_block_t* crypt_block, /*!< in: crypt buf or NULL */ ulint space, /*!< in: space id */ @@ -3283,7 +3283,7 @@ row_merge_sort( dberr_t error = DB_SUCCESS; ulint merge_count = 0; ulint total_merge_sort_count; - float curr_progress = 0; + double curr_progress = 0; DBUG_ENTER("row_merge_sort"); @@ -3296,7 +3296,7 @@ row_merge_sort( /* Find the number N which 2^N is greater or equal than num_runs */ /* N is merge sort running count */ - total_merge_sort_count = (ulint) ceil(my_log2f(num_runs)); + total_merge_sort_count = (ulint) ceil(my_log2f((float)num_runs)); if(total_merge_sort_count <= 0) { total_merge_sort_count=1; } @@ -3482,9 +3482,9 @@ row_merge_insert_index_tuples( const row_merge_buf_t* row_buf, BtrBulk* btr_bulk, const ib_uint64_t table_total_rows, /*!< in: total rows of old table */ - const float pct_progress, /*!< in: total progress + const double pct_progress, /*!< in: total progress percent until now */ - const float pct_cost, /*!< in: current progress percent + const double pct_cost, /*!< in: current progress percent */ fil_space_crypt_t* crypt_data,/*!< in: table crypt data */ row_merge_block_t* crypt_block, /*!< in: crypt buf or NULL */ @@ -3501,7 +3501,7 @@ row_merge_insert_index_tuples( ulint n_rows = 0; dtuple_t* dtuple; ib_uint64_t inserted_rows = 0; - float curr_progress = 0; + double curr_progress = 0; dict_index_t* old_index = NULL; const mrec_t* mrec = NULL; ulint n_ext = 0; @@ -4661,11 +4661,11 @@ row_merge_build_indexes( bool fts_psort_initiated = false; fil_space_crypt_t * crypt_data = NULL; - float total_static_cost = 0; - float total_dynamic_cost = 0; + double total_static_cost = 0; + double total_dynamic_cost = 0; uint total_index_blocks = 0; - float pct_cost=0; - float pct_progress=0; + double pct_cost=0; + double pct_progress=0; DBUG_ENTER("row_merge_build_indexes"); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 60b375dd4c5..9356f25bcb0 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3435,8 +3435,8 @@ void fil_wait_crypt_bg_threads( dict_table_t* table) { - uint start = time(0); - uint last = start; + time_t start = time(0); + time_t last = start; if (table->space != 0) { fil_space_crypt_mark_space_closing(table->space, table->crypt_data); } @@ -3445,7 +3445,8 @@ fil_wait_crypt_bg_threads( dict_mutex_exit_for_mysql(); os_thread_sleep(20000); dict_mutex_enter_for_mysql(); - uint now = time(0); + time_t now = time(0); + if (now >= last + 30) { ib::warn() << "Waited " << now - start diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 967d0ac98cd..d8ab01cd16e 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -5273,7 +5273,7 @@ locks_ok: This optimization can avoid many IOs for certain schemas. */ ibool row_contains_all_values = TRUE; - int i; + uint i; for (i = 0; i < prebuilt->n_template; i++) { /* Condition (1) from above: is the field in the index (prefix or not)? */ diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc index f01149f8a8d..c9423a04fba 100644 --- a/storage/innobase/sync/sync0arr.cc +++ b/storage/innobase/sync/sync0arr.cc @@ -1340,7 +1340,7 @@ sync_arr_fill_sys_semphore_waits_table( */ OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_FILE], innobase_basename(cell->file))); OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LINE], cell->line)); - OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_TIME], (longlong)difftime(time(NULL), cell->reservation_time))); + OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAIT_TIME], (ulint)difftime(time(NULL), cell->reservation_time))); if (type == SYNC_MUTEX) { mutex = static_cast(cell->latch.mutex); diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index 5f617ae22f5..5cb90ce5b8d 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -498,7 +498,7 @@ rw_lock_x_lock_wait_func( rw_lock_stats.rw_x_spin_round_count.add(n_spins); if (count_os_wait > 0) { - lock->count_os_wait += count_os_wait; + lock->count_os_wait += static_cast(count_os_wait); rw_lock_stats.rw_x_os_wait_count.add(count_os_wait); } From d96ee168a1f87c090421fb593930515ae8db3d7f Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 26 Jan 2017 16:35:05 +0400 Subject: [PATCH 127/167] MDEV-11557 port MySQL-5.7 JSON tests to MariaDB. paths ending on [0]..[0] should be handled in conforming manner. --- mysql-test/r/func_json.result | 50 ++++++++++++++++ mysql-test/suite/json/r/json_no_table.result | 62 ++++++++------------ mysql-test/t/func_json.test | 18 ++++++ sql/item_jsonfunc.cc | 24 +++++--- strings/json_lib.c | 49 +++++++++++++--- 5 files changed, 150 insertions(+), 53 deletions(-) diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 47993ae9a32..6968cf79d7d 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -444,3 +444,53 @@ json CREATE TABLE `json` ( `j` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table json; +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ) +1 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ) +2 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ) +2 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ) +2 +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ); +json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ) +2 +select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ); +json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ) +2 +select json_set('1', '$[0]', 100); +json_set('1', '$[0]', 100) +100 +select json_set('1', '$[0][0]', 100); +json_set('1', '$[0][0]', 100) +100 +select json_set('1', '$[1]', 100); +json_set('1', '$[1]', 100) +[1, 100] +select json_set('{"a":12}', '$[0]', 100); +json_set('{"a":12}', '$[0]', 100) +100 +select json_set('{"a":12}', '$[0].a', 100); +json_set('{"a":12}', '$[0].a', 100) +{"a":100} +select json_set('{"a":12}', '$[0][0].a', 100); +json_set('{"a":12}', '$[0][0].a', 100) +{"a":100} +select json_set('{"a":12}', '$[0][1].a', 100); +json_set('{"a":12}', '$[0][1].a', 100) +NULL +Warnings: +Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result index 88016ebfd19..97148bdad43 100644 --- a/mysql-test/suite/json/r/json_no_table.result +++ b/mysql-test/suite/json/r/json_no_table.result @@ -420,10 +420,10 @@ json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ) 1 select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ) -NULL +1 select json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ); json_length( '[ 1, [ 2, 3, 4 ], {"a": 1} ]', '$[2][0]' ) -NULL +1 select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ); json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][1]' ) NULL @@ -1694,13 +1694,13 @@ JSON_ARRAY_APPEND # ---------------------------------------------------------------------- select json_array_append('{"a":1}', '$[0]', 100); json_array_append('{"a":1}', '$[0]', 100) -NULL +[{"a":1}, 100] select json_array_append('3', '$[0]', 100); json_array_append('3', '$[0]', 100) -NULL +[3, 100] select json_array_append('3', '$[0][0][0][0]', 100); json_array_append('3', '$[0][0][0][0]', 100) -NULL +[3, 100] # ---------------------------------------------------------------------- # Test of JSON_INSERT function. # ---------------------------------------------------------------------- @@ -2118,7 +2118,7 @@ json_set('1', '$', 4) 4 select json_set('1', '$[0]', 4); json_set('1', '$[0]', 4) -[1, 4] +4 select json_set('1', '$[1]', 4); json_set('1', '$[1]', 4) [1, 4] @@ -2127,13 +2127,13 @@ json_set('1', '$[10]', '4', '$[11]', 5) [1, "4", 5] select json_set('[1,2,3]', '$[2][0]', 4); json_set('[1,2,3]', '$[2][0]', 4) -[1,2,[3, 4]] +[1,2,4] select json_set('[1,2,3]', '$[2][2]', 4); json_set('[1,2,3]', '$[2][2]', 4) [1,2,[3, 4]] select json_set('{"a": 3}', '$.a[0]', 4); json_set('{"a": 3}', '$.a[0]', 4) -{"a": [3, 4]} +{"a": 4} select json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); json_set('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') {"a": [3, 4, "5"]} @@ -2280,7 +2280,7 @@ json_replace('1', '$', 4) 4 select json_replace('1', '$[0]', 4); json_replace('1', '$[0]', 4) -1 +4 select json_replace('1', '$[1]', 4); json_replace('1', '$[1]', 4) 1 @@ -2289,13 +2289,13 @@ json_replace('1', '$[10]', '4', '$[11]', 5) 1 select json_replace('[1,2,3]', '$[2][0]', 4); json_replace('[1,2,3]', '$[2][0]', 4) -[1,2,3] +[1,2,4] select json_replace('[1,2,3]', '$[2][2]', 4); json_replace('[1,2,3]', '$[2][2]', 4) [1,2,3] select json_replace('{"a": 3}', '$.a[0]', 4); json_replace('{"a": 3}', '$.a[0]', 4) -{"a": 3} +{"a": 4} select json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5'); json_replace('{"a": 3}', '$.a[1]', 4, '$.a[2]', '5') {"a": 3} @@ -2312,7 +2312,7 @@ true); JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.a[0]', true) -{ "a" : "foo", "b" : [ 1, 2, 3 ] } +{ "a" : true, "b" : [ 1, 2, 3 ] } SELECT JSON_REPLACE('{ "a" : "foo", "b" : [ 1, 2, 3 ] }', '$.b[5]', true); @@ -3489,23 +3489,19 @@ JSON_SET('1', '$', 100) 100 SELECT JSON_SET('1', '$[0]', 100); JSON_SET('1', '$[0]', 100) -[1, 100] +100 SELECT JSON_SET('1', '$[0][0]', 100); JSON_SET('1', '$[0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +100 SELECT JSON_SET('1', '$[0][0][0]', 100); JSON_SET('1', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +100 SELECT JSON_SET('[]', '$', 100); JSON_SET('[]', '$', 100) 100 SELECT JSON_SET('[]', '$[0]', 100); JSON_SET('[]', '$[0]', 100) -[, 100] +[100] SELECT JSON_SET('[]', '$[0][0]', 100); JSON_SET('[]', '$[0][0]', 100) NULL @@ -3524,12 +3520,10 @@ JSON_SET('[1]', '$[0]', 100) [100] SELECT JSON_SET('[1]', '$[0][0]', 100); JSON_SET('[1]', '$[0][0]', 100) -[[1, 100]] +[100] SELECT JSON_SET('[1]', '$[0][0][0]', 100); JSON_SET('[1]', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_set' +[100] SELECT JSON_SET('[[1]]', '$', 100); JSON_SET('[[1]]', '$', 100) 100 @@ -3541,7 +3535,7 @@ JSON_SET('[[1]]', '$[0][0]', 100) [[100]] SELECT JSON_SET('[[1]]', '$[0][0][0]', 100); JSON_SET('[[1]]', '$[0][0][0]', 100) -[[[1, 100]]] +[[100]] SELECT JSON_SET('[[[1]]]', '$', 100); JSON_SET('[[[1]]]', '$', 100) 100 @@ -3559,17 +3553,13 @@ JSON_REPLACE('1', '$', 100) 100 SELECT JSON_REPLACE('1', '$[0]', 100); JSON_REPLACE('1', '$[0]', 100) -1 +100 SELECT JSON_REPLACE('1', '$[0][0]', 100); JSON_REPLACE('1', '$[0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +100 SELECT JSON_REPLACE('1', '$[0][0][0]', 100); JSON_REPLACE('1', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +100 SELECT JSON_REPLACE('[]', '$', 100); JSON_REPLACE('[]', '$', 100) 100 @@ -3594,12 +3584,10 @@ JSON_REPLACE('[1]', '$[0]', 100) [100] SELECT JSON_REPLACE('[1]', '$[0][0]', 100); JSON_REPLACE('[1]', '$[0][0]', 100) -[1] +[100] SELECT JSON_REPLACE('[1]', '$[0][0][0]', 100); JSON_REPLACE('[1]', '$[0][0][0]', 100) -NULL -Warnings: -Warning 4037 Unexpected end of JSON text in argument 1 to function 'json_update' +[100] SELECT JSON_REPLACE('[[1]]', '$', 100); JSON_REPLACE('[[1]]', '$', 100) 100 @@ -3611,7 +3599,7 @@ JSON_REPLACE('[[1]]', '$[0][0]', 100) [[100]] SELECT JSON_REPLACE('[[1]]', '$[0][0][0]', 100); JSON_REPLACE('[[1]]', '$[0][0][0]', 100) -[[1]] +[[100]] SELECT JSON_REPLACE('[[[1]]]', '$', 100); JSON_REPLACE('[[[1]]]', '$', 100) 100 diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 455f1a722ea..b9b4ab3726a 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -179,3 +179,21 @@ create table json (j INT); show create table json; drop table json; +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2]' ); +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], 5 ]', '$[2][0][0][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0]' ); +select json_length( '[ 1, [ 2, 3, 4 ], {"a":5, "b":6} ]', '$[2][0][0][0]' ); +select json_length( '{"a":{"b":{"d":1}}, "a":{"c":{"d":1, "j":2}}}', '$.a[0][0][0].c' ); + +select json_set('1', '$[0]', 100); +select json_set('1', '$[0][0]', 100); +select json_set('1', '$[1]', 100); +select json_set('{"a":12}', '$[0]', 100); +select json_set('{"a":12}', '$[0].a', 100); +select json_set('{"a":12}', '$[0][0].a', 100); +select json_set('{"a":12}', '$[0][1].a', 100); + diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index fc146427bc1..4731bada6ab 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -1983,13 +1983,22 @@ String *Item_func_json_insert::val_str(String *str) if (je.value_type != JSON_VALUE_ARRAY) { const uchar *v_from= je.value_begin; - if (!mode_insert) - continue; + int do_array_autowrap; + + if (mode_insert) + do_array_autowrap= !mode_replace || lp->n_item; + else + { + if (lp->n_item) + continue; + do_array_autowrap= 0; + } + str->length(0); /* Wrap the value as an array. */ if (append_simple(str, js->ptr(), (const char *) v_from - js->ptr()) || - str->append("[", 1)) + (do_array_autowrap && str->append("[", 1))) goto js_error; /* Out of memory. */ if (je.value_type == JSON_VALUE_OBJECT) @@ -1998,10 +2007,11 @@ String *Item_func_json_insert::val_str(String *str) goto js_error; } - if (append_simple(str, v_from, je.s.c_str - v_from) || - str->append(", ", 2) || + if ((do_array_autowrap && + (append_simple(str, v_from, je.s.c_str - v_from) || + str->append(", ", 2))) || append_json_value(str, args[n_arg+1], &tmp_val) || - str->append("]", 1) || + (do_array_autowrap && str->append("]", 1)) || append_simple(str, je.s.c_str, js->end()-(const char *) je.s.c_str)) goto js_error; /* Out of memory. */ @@ -2033,7 +2043,7 @@ String *Item_func_json_insert::val_str(String *str) v_to= (const char *) (je.s.c_str - je.sav_c_len); str->length(0); if (append_simple(str, js->ptr(), v_to - js->ptr()) || - str->append(", ", 2) || + (n_item > 0 && str->append(", ", 2)) || append_json_value(str, args[n_arg+1], &tmp_val) || append_simple(str, v_to, js->end() - v_to)) goto js_error; /* Out of memory. */ diff --git a/strings/json_lib.c b/strings/json_lib.c index 66b075a997b..18bdce2613f 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -1187,6 +1187,8 @@ int json_skip_key(json_engine_t *j) } +#define SKIPPED_STEP_MARK ((uint) ~0) + /* Current step of the patch matches the JSON construction. Now we should either stop the search or go to the next @@ -1195,24 +1197,48 @@ int json_skip_key(json_engine_t *j) static int handle_match(json_engine_t *je, json_path_t *p, json_path_step_t **p_cur_step, uint *array_counters) { + json_path_step_t *next_step= *p_cur_step + 1; + DBUG_ASSERT(*p_cur_step < p->last_step); if (json_read_value(je)) return 1; if (json_value_scalar(je)) - return 0; - - (*p_cur_step)++; - array_counters[*p_cur_step - p->steps]= 0; - - if ((int) je->value_type != - (int) ((*p_cur_step)->type & JSON_PATH_KEY_OR_ARRAY)) { - (*p_cur_step)--; - return json_skip_level(je); + while (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0) + { + if (++next_step > p->last_step) + { + je->s.c_str= je->value_begin; + return 1; + } + } + return 0; } + if (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0 && + je->value_type & JSON_VALUE_OBJECT) + { + do + { + array_counters[next_step - p->steps]= SKIPPED_STEP_MARK; + if (++next_step > p->last_step) + { + je->s.c_str= je->value_begin; + return 1; + } + } while (next_step->type == JSON_PATH_ARRAY && next_step->n_item == 0); + } + + + array_counters[next_step - p->steps]= 0; + + if ((int) je->value_type != + (int) (next_step->type & JSON_PATH_KEY_OR_ARRAY)) + return json_skip_level(je); + + *p_cur_step= next_step; return 0; } @@ -1277,6 +1303,11 @@ int json_find_path(json_engine_t *je, json_skip_array_item(je); break; case JST_OBJ_END: + do + { + (*p_cur_step)--; + } while (array_counters[(*p_cur_step) - p->steps] == SKIPPED_STEP_MARK); + break; case JST_ARRAY_END: (*p_cur_step)--; break; From def258061b884df91624562c27c818f9d1fa2d5c Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 4 Nov 2016 13:00:11 +0000 Subject: [PATCH 128/167] increase default for max threads in the pool to max allowed value (64K) currently --- mysql-test/r/mysqld--help,win.rdiff | 28 +++++++++---------- mysql-test/r/mysqld--help.result | 2 +- .../r/sysvars_server_notembedded.result | 4 +-- .../r/thread_pool_max_threads_basic.result | 10 +++---- sql/sys_vars.cc | 2 +- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/mysqld--help,win.rdiff b/mysql-test/r/mysqld--help,win.rdiff index 4d66e8bad60..77a1427d893 100644 --- a/mysql-test/r/mysqld--help,win.rdiff +++ b/mysql-test/r/mysqld--help,win.rdiff @@ -1,5 +1,5 @@ ---- mysqld--help.result 2016-09-21 13:50:58.682767100 +0000 -+++ mysqld--help,win.reject 2016-09-21 13:57:57.494626000 +0000 +--- mysqld--help.result 2016-11-04 13:35:06.665881700 +0000 ++++ mysqld--help,win.reject 2016-11-04 13:58:39.030512500 +0000 @@ -318,7 +318,6 @@ The number of segments in a key cache -L, --language=name Client error messages in given language. May be given as @@ -8,7 +8,7 @@ --lc-messages=name Set the language used for the error messages. -L, --lc-messages-dir=name Directory where error messages are -@@ -517,6 +516,7 @@ +@@ -521,6 +520,7 @@ Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME, DATETIME, TIMESTAMP columns. (Defaults to on; use --skip-mysql56-temporal-format to disable.) @@ -16,7 +16,7 @@ --net-buffer-length=# Buffer length for TCP/IP and socket communication --net-read-timeout=# -@@ -924,6 +924,9 @@ +@@ -931,6 +931,9 @@ characteristics (isolation level, read only/read write,snapshot - but not any work done / data modified within the transaction). @@ -26,7 +26,7 @@ --show-slave-auth-info Show user and password in SHOW SLAVE HOSTS on this master. -@@ -1036,6 +1039,10 @@ +@@ -1043,6 +1046,10 @@ Log slow queries to given log file. Defaults logging to 'hostname'-slow.log. Must be enabled to activate other slow log options @@ -37,7 +37,7 @@ --socket=name Socket file to use for connection --sort-buffer-size=# Each thread that needs to do a sort allocates a buffer of -@@ -1054,6 +1061,7 @@ +@@ -1061,6 +1068,7 @@ NO_ENGINE_SUBSTITUTION, PAD_CHAR_TO_FULL_LENGTH --stack-trace Print a symbolic stack trace on failure (Defaults to on; use --skip-stack-trace to disable.) @@ -45,7 +45,7 @@ --standards-compliant-cte Allow only standards compiant CTE (Defaults to on; use --skip-standards-compliant-cte to disable.) -@@ -1102,6 +1110,11 @@ +@@ -1109,6 +1117,11 @@ --thread-pool-max-threads=# Maximum allowed number of worker threads in the thread pool @@ -57,7 +57,7 @@ --thread-pool-oversubscribe=# How many additional active worker threads in a group are allowed. -@@ -1132,8 +1145,8 @@ +@@ -1139,8 +1152,8 @@ size, MySQL will automatically convert it to an on-disk MyISAM or Aria table -t, --tmpdir=name Path for temporary files. Several paths may be specified, @@ -68,7 +68,7 @@ --transaction-alloc-block-size=# Allocation block size for transactions to be stored in binary log -@@ -1257,7 +1270,6 @@ +@@ -1264,7 +1277,6 @@ key-cache-division-limit 100 key-cache-file-hash-size 512 key-cache-segments 0 @@ -76,7 +76,7 @@ lc-messages en_US lc-messages-dir MYSQL_SHAREDIR/ lc-time-names en_US -@@ -1324,6 +1336,7 @@ +@@ -1333,6 +1345,7 @@ myisam-stats-method NULLS_UNEQUAL myisam-use-mmap FALSE mysql56-temporal-format TRUE @@ -84,7 +84,7 @@ net-buffer-length 16384 net-read-timeout 30 net-retry-count 10 -@@ -1424,6 +1437,8 @@ +@@ -1434,6 +1447,8 @@ session-track-state-change FALSE session-track-system-variables session-track-transaction-info OFF @@ -93,7 +93,7 @@ show-slave-auth-info FALSE silent-startup FALSE skip-grant-tables TRUE -@@ -1448,6 +1463,7 @@ +@@ -1458,6 +1473,7 @@ slave-type-conversions slow-launch-time 2 slow-query-log FALSE @@ -101,7 +101,7 @@ sort-buffer-size 2097152 sql-mode NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION stack-trace TRUE -@@ -1461,14 +1477,16 @@ +@@ -1471,14 +1487,16 @@ sync-relay-log 10000 sync-relay-log-info 10000 sysdate-is-now FALSE @@ -114,7 +114,7 @@ tc-heuristic-recover OFF thread-cache-size 151 thread-pool-idle-timeout 60 - thread-pool-max-threads 1000 + thread-pool-max-threads 65536 +thread-pool-min-threads 1 +thread-pool-mode windows thread-pool-oversubscribe 3 diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index c6797eab5ae..5938da489f7 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1487,7 +1487,7 @@ table-open-cache-instances 8 tc-heuristic-recover OFF thread-cache-size 151 thread-pool-idle-timeout 60 -thread-pool-max-threads 1000 +thread-pool-max-threads 65536 thread-pool-oversubscribe 3 thread-pool-prio-kickup-timer 1000 thread-pool-priority auto diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 9f006cbdb9b..8ee6ce6492c 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -4785,9 +4785,9 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME THREAD_POOL_MAX_THREADS SESSION_VALUE NULL -GLOBAL_VALUE 1000 +GLOBAL_VALUE 65536 GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 1000 +DEFAULT_VALUE 65536 VARIABLE_SCOPE GLOBAL VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Maximum allowed number of worker threads in the thread pool diff --git a/mysql-test/suite/sys_vars/r/thread_pool_max_threads_basic.result b/mysql-test/suite/sys_vars/r/thread_pool_max_threads_basic.result index 289c0d56092..5622d97cb68 100644 --- a/mysql-test/suite/sys_vars/r/thread_pool_max_threads_basic.result +++ b/mysql-test/suite/sys_vars/r/thread_pool_max_threads_basic.result @@ -1,21 +1,21 @@ SET @start_global_value = @@global.thread_pool_max_threads; select @@global.thread_pool_max_threads; @@global.thread_pool_max_threads -1000 +65536 select @@session.thread_pool_max_threads; ERROR HY000: Variable 'thread_pool_max_threads' is a GLOBAL variable show global variables like 'thread_pool_max_threads'; Variable_name Value -thread_pool_max_threads 1000 +thread_pool_max_threads 65536 show session variables like 'thread_pool_max_threads'; Variable_name Value -thread_pool_max_threads 1000 +thread_pool_max_threads 65536 select * from information_schema.global_variables where variable_name='thread_pool_max_threads'; VARIABLE_NAME VARIABLE_VALUE -THREAD_POOL_MAX_THREADS 1000 +THREAD_POOL_MAX_THREADS 65536 select * from information_schema.session_variables where variable_name='thread_pool_max_threads'; VARIABLE_NAME VARIABLE_VALUE -THREAD_POOL_MAX_THREADS 1000 +THREAD_POOL_MAX_THREADS 65536 set global thread_pool_max_threads=1; select @@global.thread_pool_max_threads; @@global.thread_pool_max_threads diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index c21fc4f7f49..fa723e2707f 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -3359,7 +3359,7 @@ static Sys_var_uint Sys_threadpool_max_threads( "thread_pool_max_threads", "Maximum allowed number of worker threads in the thread pool", GLOBAL_VAR(threadpool_max_threads), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1, 65536), DEFAULT(1000), BLOCK_SIZE(1), + VALID_RANGE(1, 65536), DEFAULT(65536), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_tp_max_threads) ); From a5f6b4f9fdf21ed6cf88f87c808825a61695bc3e Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 26 Jan 2017 17:39:15 +0000 Subject: [PATCH 129/167] Fix the code to determine sector size on Windows volume. DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY) needs volume handle, not the handle to ordinary file. --- storage/innobase/os/os0file.cc | 69 +++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 0cf0e0545c3..488a9ff88dc 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -828,27 +828,62 @@ os_file_get_block_size( } #endif /* UNIV_LINUX */ #ifdef _WIN32 - DWORD outsize; - STORAGE_PROPERTY_QUERY storageQuery; - memset(&storageQuery, 0, sizeof(storageQuery)); - storageQuery.PropertyId = StorageAccessAlignmentProperty; - storageQuery.QueryType = PropertyStandardQuery; - STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment; - BOOL result = os_win32_device_io_control(file, - IOCTL_STORAGE_QUERY_PROPERTY, - &storageQuery, - sizeof(STORAGE_PROPERTY_QUERY), - &diskAlignment, - sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), - &outsize); + fblock_size = 0; - if (!result) { - os_file_handle_error_no_exit(name, "DeviceIoControl()", FALSE); - fblock_size = 0; + // Open volume for this file, find out it "physical bytes per sector" + + HANDLE volume_handle = INVALID_HANDLE_VALUE; + char volume[MAX_PATH + 4]="\\\\.\\"; // Special prefix required for volume names. + if (!GetVolumePathName(name , volume + 4, MAX_PATH)) { + os_file_handle_error_no_exit(name, + "GetVolumePathName()", FALSE); + goto end; } - fblock_size = diskAlignment.BytesPerPhysicalSector; + size_t len = strlen(volume); + if (volume[len - 1] == '\\') { + // Trim trailing backslash from volume name. + volume[len - 1] = 0; + } + + volume_handle = CreateFile(volume, FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + 0, OPEN_EXISTING, 0, 0); + + if (volume_handle == INVALID_HANDLE_VALUE) { + os_file_handle_error_no_exit(volume, + "CreateFile()", FALSE); + goto end; + } + + DWORD tmp; + STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR disk_alignment; + + STORAGE_PROPERTY_QUERY storage_query; + memset(&storage_query, 0, sizeof(storage_query)); + storage_query.PropertyId = StorageAccessAlignmentProperty; + storage_query.QueryType = PropertyStandardQuery; + + BOOL result = os_win32_device_io_control(volume_handle, + IOCTL_STORAGE_QUERY_PROPERTY, + &storage_query, + sizeof(storage_query), + &disk_alignment, + sizeof(disk_alignment), + &tmp); + + CloseHandle(volume_handle); + + if (!result) { + os_file_handle_error_no_exit(volume, + "DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY)", FALSE); + goto end; + } + + fblock_size = disk_alignment.BytesPerPhysicalSector; + +end: #endif /* _WIN32 */ /* Currently we support file block size up to 4Kb */ From fea4959a0d54aa3d74c41f483ba4016b9e3364cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 27 Jan 2017 09:08:15 +0200 Subject: [PATCH 130/167] Fix test failure on gcol.innodb_virtual_basic. --- mysql-test/suite/gcol/r/innodb_virtual_basic.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/gcol/r/innodb_virtual_basic.result b/mysql-test/suite/gcol/r/innodb_virtual_basic.result index 06a307fc761..f55085ce2f8 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_basic.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_basic.result @@ -209,7 +209,7 @@ CREATE TABLE t1(a INT); CREATE INDEX idx ON t1(a); CREATE TABLE t3(a INT, b INT , INDEX(b), CONSTRAINT x FOREIGN KEY(b) REFERENCES t1(a)); CREATE TABLE t2(a INT, b INT generated always as (a+1) virtual, INDEX(b), CONSTRAINT x FOREIGN KEY(b) REFERENCES t1(a)); -ERROR HY000: Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed") +ERROR HY000: Can't create table `test`.`t2` (errno: 121 "Duplicate key on write or update") CREATE TABLE t2(a INT, b INT generated always as (a+1) virtual, INDEX(b)); DROP TABLE t3; DROP TABLE t2; From ebdf70db2a36bba0ccdab7c680a252040c350a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 27 Jan 2017 09:13:48 +0200 Subject: [PATCH 131/167] Fix test failure on innodb-wl5522 Added flush tables to avoid corruption of mtr/test_suppressions table. --- mysql-test/suite/innodb/r/innodb-wl5522.result | 2 ++ mysql-test/suite/innodb/t/innodb-wl5522.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb-wl5522.result b/mysql-test/suite/innodb/r/innodb-wl5522.result index 4075c8a1486..2ae994e8f3d 100644 --- a/mysql-test/suite/innodb/r/innodb-wl5522.result +++ b/mysql-test/suite/innodb/r/innodb-wl5522.result @@ -1,4 +1,5 @@ call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); +FLUSH TABLES; CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b char(22), @@ -1013,3 +1014,4 @@ DROP TABLE t1; call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); +FLUSH TABLES; diff --git a/mysql-test/suite/innodb/t/innodb-wl5522.test b/mysql-test/suite/innodb/t/innodb-wl5522.test index 138e02e1214..d2b6fca4d4a 100644 --- a/mysql-test/suite/innodb/t/innodb-wl5522.test +++ b/mysql-test/suite/innodb/t/innodb-wl5522.test @@ -4,6 +4,7 @@ -- source include/have_innodb.inc call mtr.add_suppression("InnoDB: Unable to import tablespace .* because it already exists. Please DISCARD the tablespace before IMPORT."); +FLUSH TABLES; let $MYSQLD_TMPDIR = `SELECT @@tmpdir`; let $MYSQLD_DATADIR = `SELECT @@datadir`; @@ -858,6 +859,7 @@ DROP TABLE t1; call mtr.add_suppression("Got error -1 when reading table '.*'"); call mtr.add_suppression("InnoDB: Error: tablespace id and flags in file '.*'.*"); call mtr.add_suppression("InnoDB: The table .* doesn't have a corresponding tablespace, it was discarded"); +FLUSH TABLES; # cleanup --remove_file $MYSQLTEST_VARDIR/tmp/t1.cfg From 4ee7174479932034ce6b9dd4abfbb26d275b52bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 27 Jan 2017 11:26:28 +0200 Subject: [PATCH 132/167] Fix test failure on innodb-trim. Do wait only if innodb_num_page_compressed_trim_op shows that we have succeed to do at least few trim operations (and that will happen on insert if possible). --- mysql-test/suite/innodb/t/innodb-trim.test | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mysql-test/suite/innodb/t/innodb-trim.test b/mysql-test/suite/innodb/t/innodb-trim.test index 1b64321116c..6be4826a974 100644 --- a/mysql-test/suite/innodb/t/innodb-trim.test +++ b/mysql-test/suite/innodb/t/innodb-trim.test @@ -31,8 +31,18 @@ call innodb_insert_proc(16000); commit; set autocommit=1; +--disable_warnings +--disable_query_log +--disable_result_log +let $success= SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_num_page_compressed_trim_op'; + +if ($success) { let $wait_condition= SELECT variable_value > 5 FROM information_schema.global_status WHERE variable_name = 'innodb_num_page_compressed_trim_op'; --source include/wait_condition.inc +} +--enable_warnings +--enable_query_log +--enable_result_log DROP PROCEDURE innodb_insert_proc; DROP TABLE innodb_page_compressed; From 8daa87dc064e1d32e1b27dd809cf8dc4489352d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Jan 2017 12:21:31 +0200 Subject: [PATCH 133/167] Fix a test. --- .../suite/innodb/include/innodb_simulate_comp_failures.inc | 2 +- mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result | 1 - .../suite/innodb/r/innodb_simulate_comp_failures_small.result | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc index 6aaa9cd07a9..d9c0294faf5 100644 --- a/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc +++ b/mysql-test/suite/innodb/include/innodb_simulate_comp_failures.inc @@ -7,7 +7,7 @@ --let $simulate_comp_failures_save = `SELECT @@innodb_simulate_comp_failures` -# since this test generates lot of errors in log, suppress checking errors +--disable_query_log call mtr.add_suppression("InnoDB: Simulating a compression failure for table `test`\\.`t1`"); --enable_query_log diff --git a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result index 4ed6ca14f26..f35e4159603 100644 --- a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result +++ b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures.result @@ -1,7 +1,6 @@ # # Testing robustness against random compression failures # -call mtr.add_suppression("InnoDB: Simulating a compression failure for table `test`\\.`t1`"); CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; SHOW CREATE TABLE t1; Table Create Table diff --git a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result index cc61f811e62..099c673bca7 100644 --- a/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result +++ b/mysql-test/suite/innodb/r/innodb_simulate_comp_failures_small.result @@ -1,7 +1,6 @@ # # Testing robustness against random compression failures # -call mtr.add_suppression(".*"); CREATE TABLE t1(id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255), KEY msg_i(msg)) ENGINE=INNODB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; SHOW CREATE TABLE t1; Table Create Table From 3271da11c4fa802854a9c3fd808f80aaf0ba9de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Jan 2017 15:11:46 +0200 Subject: [PATCH 134/167] MDEV-11814 Refuse innodb_read_only startup if crash recovery is needed recv_scan_log_recs(): Remember if redo log apply is needed, even if starting up in innodb_read_only mode. recv_recovery_from_checkpoint_start_func(): Refuse innodb_read_only startup if redo log apply is needed. --- .../suite/innodb/r/log_file_size.result | 31 +++ mysql-test/suite/innodb/t/log_file_size.test | 188 ++++++++++++++++++ storage/innobase/include/srv0start.h | 2 +- storage/innobase/log/log0recv.cc | 13 +- 4 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/innodb/r/log_file_size.result create mode 100644 mysql-test/suite/innodb/t/log_file_size.test diff --git a/mysql-test/suite/innodb/r/log_file_size.result b/mysql-test/suite/innodb/r/log_file_size.result new file mode 100644 index 00000000000..d83af099979 --- /dev/null +++ b/mysql-test/suite/innodb/r/log_file_size.result @@ -0,0 +1,31 @@ +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 VALUES (42); +# Kill and restart: --innodb-log-file-size=6M +SELECT * FROM t1; +a +INSERT INTO t1 VALUES (42); +BEGIN; +DELETE FROM t1; +# Kill and restart: --innodb-log-files-in-group=3 --innodb-log-file-size=5M +SELECT * FROM t1; +a +42 +INSERT INTO t1 VALUES (123); +BEGIN; +DELETE FROM t1; +# Kill the server +--innodb-force-recovery-crash=1 +--innodb-force-recovery-crash=3 +--innodb-force-recovery-crash=4 +--innodb-force-recovery-crash=5 +--innodb-force-recovery-crash=6 +--innodb-force-recovery-crash=7 +--innodb-force-recovery-crash=8 +--innodb-force-recovery-crash=9 +--innodb-force-recovery-crash=10 +SELECT * FROM t1; +a +42 +123 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test new file mode 100644 index 00000000000..d2da6e4f3b2 --- /dev/null +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -0,0 +1,188 @@ +# Test resizing the InnoDB redo log. + +--source include/have_innodb.inc + +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc +# innodb-force-recovery-crash needs debug +--source include/have_debug.inc + +if (`SELECT @@innodb_log_file_size = 1048576`) { + --skip Test requires innodb_log_file_size>1M. +} + +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 VALUES (42); + +let $restart_parameters = --innodb-log-file-size=6M; +--source include/kill_and_restart_mysqld.inc + +SELECT * FROM t1; + +INSERT INTO t1 VALUES (42); +BEGIN; +DELETE FROM t1; + +let $restart_parameters = --innodb-log-files-in-group=3 --innodb-log-file-size=5M; +--source include/kill_and_restart_mysqld.inc + +SELECT * FROM t1; + +INSERT INTO t1 VALUES (123); + +let MYSQLD_DATADIR= `select @@datadir`; +let SEARCH_ABORT = NOT FOUND; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; +# MDEV-11689 FIXME: add --core-file to $args, and remove all ,134 below +let $args=--innodb --unknown-option --loose-console > $SEARCH_FILE 2>&1; +let $crash=$args --innodb-force-recovery-crash; + +BEGIN; +DELETE FROM t1; + +--source include/kill_mysqld.inc + +--error 2 +--exec $MYSQLD_CMD $args --innodb-log-group-home-dir=foo\;bar +let SEARCH_PATTERN= syntax error in innodb_log_group_home_dir; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +--echo --innodb-force-recovery-crash=1 +--error 3,134 +--exec $MYSQLD_CMD $crash=1 +let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE +--echo --innodb-force-recovery-crash=3 +--error 3,134 +--exec $MYSQLD_CMD $crash=3 +let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +--error 2 +--exec $MYSQLD_CMD $args --innodb-read-only +let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +--echo --innodb-force-recovery-crash=4 +--error 3,134 +--exec $MYSQLD_CMD $crash=4 +let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE +--echo --innodb-force-recovery-crash=5 +--error 3,134 +--exec $MYSQLD_CMD $crash=5 +let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +--error 2 +--exec $MYSQLD_CMD $args --innodb-read-only +let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +--echo --innodb-force-recovery-crash=6 +--error 3,134 +--exec $MYSQLD_CMD $crash=6 +let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE +--echo --innodb-force-recovery-crash=7 +--error 3,134 +--exec $MYSQLD_CMD $crash=7 +# this crashes right after deleting all log files +--remove_file $SEARCH_FILE + +--error 2 +--exec $MYSQLD_CMD $args --innodb-read-only +let SEARCH_PATTERN= InnoDB: Cannot create log files in read-only mode; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +--echo --innodb-force-recovery-crash=8 +--error 3,134 +--exec $MYSQLD_CMD $crash=8 +let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE +--echo --innodb-force-recovery-crash=9 +--error 3,134 +--exec $MYSQLD_CMD $crash=9 +let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +# We should have perfectly synced files here. +# Rename the log files, and trigger an error in recovery. +--move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0 +--move_file $MYSQLD_DATADIR/ib_logfile1 $MYSQLD_DATADIR/ib_logfile1_hidden +--error 2,134 +--exec $MYSQLD_CMD $args +let SEARCH_PATTERN= InnoDB: Only one log file found; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE +--move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101 + +perl; +die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile0"); +print FILE "garbage"; +close(FILE); +EOF +--error 2,134 +--exec $MYSQLD_CMD $args +let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile0 size 7 is not a multiple of innodb_page_size; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE +--remove_file $MYSQLD_DATADIR/ib_logfile0 +--move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0 + +perl; +die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile1"); +print FILE "junkfill" x 131072; +close(FILE); +EOF + +--error 2,134 +--exec $MYSQLD_CMD $args +let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile1 is of different size 1048576 bytes than other log files; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE +--remove_file $MYSQLD_DATADIR/ib_logfile1 +--move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101 +--move_file $MYSQLD_DATADIR/ib_logfile1_hidden $MYSQLD_DATADIR/ib_logfile1 + +--echo --innodb-force-recovery-crash=10 +--error 3,134 +--exec $MYSQLD_CMD $crash=10 +let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= InnoDB: Renaming log file .*ib_logfile101 to .*ib_logfile0; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +--let $restart_parameters= +--source include/start_mysqld.inc + +--disable_query_log +call mtr.add_suppression("InnoDB: Resizing redo log"); +call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files"); +call mtr.add_suppression("InnoDB: New log files created"); +call mtr.add_suppression("InnoDB: The log sequence numbers [0-9]+ and [0-9]+ in ibdata files do not match the log sequence number [0-9]+ in the ib_logfiles"); +--enable_query_log + +SELECT * FROM t1; +DROP TABLE t1; diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index 31085838807..f08e6e71a78 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -42,7 +42,7 @@ struct dict_table_t; fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \ srv_force_recovery_crash); \ fflush(stderr); \ - abort(); \ + exit(3); \ } \ } while (0) #endif /* DBUG_OFF */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index ce5b37565af..dc44ae3505d 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -2848,10 +2848,9 @@ recv_scan_log_recs( recv_init_crash_recovery(); } else { - - ib::warn() << "Recovery skipped," - " --innodb-read-only set!"; - + ib::warn() << "innodb_read_only" + " prevents crash recovery"; + recv_needed_recovery = true; return(true); } } @@ -3263,6 +3262,10 @@ recv_recovery_from_checkpoint_start( ut_ad(recv_sys->n_addrs == 0); ut_ad(!recv_sys->found_corrupt_fs); + if (srv_read_only_mode && recv_needed_recovery) { + return(DB_READ_ONLY); + } + if (recv_sys->found_corrupt_log && !srv_force_recovery) { log_mutex_exit(); ib::error() << "Found corrupted log when looking checkpoint lsn: " From 406e113e9abc2139e40018ec7bd1b1fb018642c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 26 Jan 2017 14:05:00 +0200 Subject: [PATCH 135/167] MDEV-11915 Detect InnoDB system tablespace size mismatch early InnoDB would refuse to start up if there is a mismatch on the size of the system tablespace files. However, before this check is conducted, the system tablespace may already have been heavily modified. InnoDB should perform the size check as early as possible. recv_recovery_from_checkpoint_finish(): Move the recv_apply_hashed_log_recs() call to innobase_start_or_create_for_mysql(). innobase_start_or_create_for_mysql(): Test the mutex functionality before doing anything else. Use a compile_time_assert() for a sizeof() constraint. Check the size of the system tablespace as early as possible. --- storage/innobase/srv/srv0start.cc | 168 ++++++++++++------------------ 1 file changed, 68 insertions(+), 100 deletions(-) diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 2b6946d70c1..3403534d36b 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1411,8 +1411,6 @@ innobase_start_or_create_for_mysql(void) { bool create_new_db = false; lsn_t flushed_lsn; - ulint sum_of_data_file_sizes; - ulint tablespace_size_in_header; dberr_t err; ulint srv_n_log_files_found = srv_n_log_files; mtr_t mtr; @@ -1447,13 +1445,7 @@ innobase_start_or_create_for_mysql(void) } #endif /* HAVE_LZO1X */ - if (sizeof(ulint) != sizeof(void*)) { - ib::error() << "Size of InnoDB's ulint is " << sizeof(ulint) - << ", but size of void* is " << sizeof(void*) - << ". The sizes should be the same so that on" - " a 64-bit platforms you can allocate more than 4 GB" - " of memory."; - } + compile_time_assert(sizeof(ulint) == sizeof(void*)); #ifdef UNIV_DEBUG ib::info() << "!!!!!!!! UNIV_DEBUG switched on !!!!!!!!!"; @@ -2089,8 +2081,6 @@ files_checked: trx_sys_create(); if (create_new_db) { - dberr_t err = DB_SUCCESS; - ut_a(!srv_read_only_mode); mtr_start(&mtr); @@ -2182,10 +2172,13 @@ files_checked: if (err == DB_SUCCESS) { /* Initialize the change buffer. */ err = dict_boot(); - } else { + } + + if (err != DB_SUCCESS) { return(srv_init_abort(err)); } + /* This must precede recv_apply_hashed_log_recs(TRUE). */ purge_queue = trx_sys_init_at_db_start(); if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { @@ -2193,12 +2186,11 @@ files_checked: respective file pages, for the last batch of recv_group_scan_log_recs(). */ - dberr_t err = recv_apply_hashed_log_recs(TRUE); + err = recv_apply_hashed_log_recs(TRUE); DBUG_PRINT("ib_log", ("apply completed")); if (err != DB_SUCCESS) { - ib::warn() << "recv_apply_hashed_log_recs " - << " failed with error " << err; + return(srv_init_abort(err)); } if (recv_needed_recovery) { @@ -2217,6 +2209,65 @@ files_checked: " InnoDB database from a backup!"; } + if (!srv_read_only_mode) { + const ulint flags = FSP_FLAGS_PAGE_SSIZE(); + for (ulint id = 0; id <= srv_undo_tablespaces; id++) { + if (fil_space_get(id)) { + fsp_flags_try_adjust(id, flags); + } + } + + if (sum_of_new_sizes > 0) { + /* New data file(s) were added */ + mtr.start(); + fsp_header_inc_size(0, sum_of_new_sizes, &mtr); + mtr.commit(); + /* Immediately write the log record about + increased tablespace size to disk, so that it + is durable even if mysqld would crash + quickly */ + log_buffer_flush_to_disk(); + } + } + + const ulint tablespace_size_in_header + = fsp_header_get_tablespace_size(); + const ulint sum_of_data_file_sizes + = srv_sys_space.get_sum_of_sizes(); + /* Compare the system tablespace file size to what is + stored in FSP_SIZE. In open_or_create_data_files() + we already checked that the file sizes match the + innodb_data_file_path specification. */ + if (srv_read_only_mode + || sum_of_data_file_sizes == tablespace_size_in_header) { + /* Do not complain about the size. */ + } else if (!srv_sys_space.can_auto_extend_last_file() + || sum_of_data_file_sizes + < tablespace_size_in_header) { + ib::error() << "Tablespace size stored in header is " + << tablespace_size_in_header + << " pages, but the sum of data file sizes is " + << sum_of_data_file_sizes << " pages"; + + if (srv_force_recovery == 0 + && sum_of_data_file_sizes + < tablespace_size_in_header) { + ib::error() << + "Cannot start InnoDB. The tail of" + " the system tablespace is" + " missing. Have you edited" + " innodb_data_file_path in my.cnf" + " in an inappropriate way, removing" + " data files from there?" + " You can set innodb_force_recovery=1" + " in my.cnf to force" + " a startup if you are trying to" + " recover a badly corrupt database."; + + return(srv_init_abort(DB_ERROR)); + } + } + /* The purge system needs to create the purge view and therefore requires that the trx_sys is inited. */ @@ -2285,8 +2336,6 @@ files_checked: && !recv_sys->found_corrupt_log && (srv_log_file_size_requested != srv_log_file_size || srv_n_log_files_found != srv_n_log_files)) { - dberr_t err = DB_SUCCESS; - /* Prepare to replace the redo log files. */ if (srv_read_only_mode) { @@ -2352,20 +2401,8 @@ files_checked: trx_sys_file_format_tag_init(); } - if (!create_new_db && sum_of_new_sizes > 0) { - /* New data file(s) were added */ - mtr_start(&mtr); - - fsp_header_inc_size(0, sum_of_new_sizes, &mtr); - - mtr_commit(&mtr); - - /* Immediately write the log record about increased tablespace - size to disk, so that it is durable even if mysqld would crash - quickly */ - - log_buffer_flush_to_disk(); - } + ut_ad(err == DB_SUCCESS); + ut_a(sum_of_new_sizes != ULINT_UNDEFINED); /* Open temp-tablespace and keep it open until shutdown. */ @@ -2417,13 +2454,6 @@ files_checked: srv_startup_is_before_trx_rollback_phase = false; if (!srv_read_only_mode) { - const ulint flags = FSP_FLAGS_PAGE_SSIZE(); - for (ulint id = 0; id <= srv_undo_tablespaces; id++) { - if (fil_space_get(id)) { - fsp_flags_try_adjust(id, flags); - } - } - /* Create the thread which watches the timeouts for lock waits */ thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create( @@ -2528,68 +2558,6 @@ files_checked: } } - sum_of_data_file_sizes = srv_sys_space.get_sum_of_sizes(); - ut_a(sum_of_new_sizes != ULINT_UNDEFINED); - - tablespace_size_in_header = fsp_header_get_tablespace_size(); - - if (!srv_read_only_mode - && !srv_sys_space.can_auto_extend_last_file() - && sum_of_data_file_sizes != tablespace_size_in_header) { - - ib::error() << "Tablespace size stored in header is " - << tablespace_size_in_header << " pages, but the sum" - " of data file sizes is " << sum_of_data_file_sizes - << " pages"; - - if (srv_force_recovery == 0 - && sum_of_data_file_sizes < tablespace_size_in_header) { - /* This is a fatal error, the tail of a tablespace is - missing */ - - ib::error() - << "Cannot start InnoDB." - " The tail of the system tablespace is" - " missing. Have you edited" - " innodb_data_file_path in my.cnf in an" - " inappropriate way, removing" - " ibdata files from there?" - " You can set innodb_force_recovery=1" - " in my.cnf to force" - " a startup if you are trying" - " to recover a badly corrupt database."; - - return(srv_init_abort(DB_ERROR)); - } - } - - if (!srv_read_only_mode - && srv_sys_space.can_auto_extend_last_file() - && sum_of_data_file_sizes < tablespace_size_in_header) { - - ib::error() << "Tablespace size stored in header is " - << tablespace_size_in_header << " pages, but the sum" - " of data file sizes is only " - << sum_of_data_file_sizes << " pages"; - - if (srv_force_recovery == 0) { - - ib::error() - << "Cannot start InnoDB. The tail of" - " the system tablespace is" - " missing. Have you edited" - " innodb_data_file_path in my.cnf in an" - " InnoDB: inappropriate way, removing" - " ibdata files from there?" - " You can set innodb_force_recovery=1" - " in my.cnf to force" - " InnoDB: a startup if you are trying to" - " recover a badly corrupt database."; - - return(srv_init_abort(DB_ERROR)); - } - } - if (srv_print_verbose_log) { ib::info() << INNODB_VERSION_STR << " started; log sequence number " From 3dd6fca7740682f04432027a9587c66d215515f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 27 Jan 2017 14:17:36 +0200 Subject: [PATCH 136/167] Fix test failure on innodb-trim. Skip test if system can't do trim operation. --- mysql-test/suite/innodb/t/innodb-trim.test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/innodb/t/innodb-trim.test b/mysql-test/suite/innodb/t/innodb-trim.test index 6be4826a974..0f38ea5ba84 100644 --- a/mysql-test/suite/innodb/t/innodb-trim.test +++ b/mysql-test/suite/innodb/t/innodb-trim.test @@ -31,18 +31,18 @@ call innodb_insert_proc(16000); commit; set autocommit=1; ---disable_warnings + +let $success= `SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_num_page_compressed_trim_op'`; + +if (!$success) { --disable_query_log --disable_result_log -let $success= SELECT variable_value FROM information_schema.global_status WHERE variable_name = 'innodb_num_page_compressed_trim_op'; - -if ($success) { -let $wait_condition= SELECT variable_value > 5 FROM information_schema.global_status WHERE variable_name = 'innodb_num_page_compressed_trim_op'; ---source include/wait_condition.inc -} ---enable_warnings + DROP PROCEDURE innodb_insert_proc; + DROP TABLE innodb_page_compressed; --enable_query_log --enable_result_log + --skip "Test requires TRIM"; +} DROP PROCEDURE innodb_insert_proc; DROP TABLE innodb_page_compressed; From 0f34160d1dfa0efa2abfc591fc688e8076bc8a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Jan 2017 16:14:20 +0200 Subject: [PATCH 137/167] Clean up a few tests that kill the server. As noted in MDEV-8841, any test that kills the server must issue FLUSH TABLES, so that tables of crash-unsafe storage engines will not be corrupted. Consistently issue this statement after any call mtr.add_suppression() calls. Also, do not invoke shutdown_server directly, but use helpers instead. --- .../suite/innodb/r/101_compatibility.result | 1 - .../suite/innodb/r/innodb_bug59641.result | 6 +--- mysql-test/suite/innodb/r/xa_recovery.result | 3 +- .../suite/innodb/t/101_compatibility.test | 3 ++ mysql-test/suite/innodb/t/doublewrite.test | 3 +- .../suite/innodb/t/innodb_bug59641.test | 31 ++++--------------- mysql-test/suite/innodb/t/log_file_size.test | 15 ++++----- mysql-test/suite/innodb/t/xa_recovery.test | 10 ++---- 8 files changed, 22 insertions(+), 50 deletions(-) diff --git a/mysql-test/suite/innodb/r/101_compatibility.result b/mysql-test/suite/innodb/r/101_compatibility.result index 2529eb96190..bc4d37916df 100644 --- a/mysql-test/suite/innodb/r/101_compatibility.result +++ b/mysql-test/suite/innodb/r/101_compatibility.result @@ -2,7 +2,6 @@ # MDEV-11623 MariaDB 10.1 fails to start datadir created with # MariaDB 10.0/MySQL 5.6 using innodb-page-size!=16K # -call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of tablespace"); CREATE TABLE tr(a INT)ENGINE=InnoDB ROW_FORMAT=REDUNDANT; CREATE TABLE tc(a INT)ENGINE=InnoDB ROW_FORMAT=COMPACT; CREATE TABLE td(a INT)ENGINE=InnoDB ROW_FORMAT=DYNAMIC; diff --git a/mysql-test/suite/innodb/r/innodb_bug59641.result b/mysql-test/suite/innodb/r/innodb_bug59641.result index f22d39654de..2c042585745 100644 --- a/mysql-test/suite/innodb/r/innodb_bug59641.result +++ b/mysql-test/suite/innodb/r/innodb_bug59641.result @@ -1,5 +1,3 @@ -call mtr.add_suppression("Found 3 prepared XA transactions"); -flush tables; CREATE TABLE t(a INT PRIMARY KEY, b INT)ENGINE=InnoDB; INSERT INTO t VALUES(2,2),(4,4),(8,8),(16,16),(32,32); COMMIT; @@ -8,20 +6,18 @@ INSERT INTO t VALUES(1,1); XA END '123'; XA PREPARE '123'; CONNECT con1,localhost,root,,; -connection con1; XA START '456'; INSERT INTO t VALUES(3,47),(5,67); UPDATE t SET b=2*b WHERE a BETWEEN 5 AND 8; XA END '456'; XA PREPARE '456'; CONNECT con2,localhost,root,,; -connection con2; XA START '789'; UPDATE t SET b=4*a WHERE a=32; XA END '789'; XA PREPARE '789'; CONNECT con3,localhost,root,,; -connection con3; +# Kill and restart SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t; a b diff --git a/mysql-test/suite/innodb/r/xa_recovery.result b/mysql-test/suite/innodb/r/xa_recovery.result index ae3a06ab9c3..7a9448ad9f0 100644 --- a/mysql-test/suite/innodb/r/xa_recovery.result +++ b/mysql-test/suite/innodb/r/xa_recovery.result @@ -6,8 +6,7 @@ UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; connection default; -call mtr.add_suppression("Found 1 prepared XA transactions"); -# Kill the server +# Kill and restart disconnect con1; connect con1,localhost,root; SELECT * FROM t1 LOCK IN SHARE MODE; diff --git a/mysql-test/suite/innodb/t/101_compatibility.test b/mysql-test/suite/innodb/t/101_compatibility.test index 5b94a24852a..83ab7914a69 100644 --- a/mysql-test/suite/innodb/t/101_compatibility.test +++ b/mysql-test/suite/innodb/t/101_compatibility.test @@ -9,7 +9,10 @@ # This is actually testing the opposite: starting the fixed 10.1 with # buggy 10.1 files (by manually converting the flags in the files). +--disable_query_log call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of tablespace"); +FLUSH TABLES; +--enable_query_log let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let MYSQLD_DATADIR=`select @@datadir`; diff --git a/mysql-test/suite/innodb/t/doublewrite.test b/mysql-test/suite/innodb/t/doublewrite.test index bb0733fd1a0..a153ad66b19 100644 --- a/mysql-test/suite/innodb/t/doublewrite.test +++ b/mysql-test/suite/innodb/t/doublewrite.test @@ -10,14 +10,13 @@ # Slow shutdown and restart to make sure ibuf merge is finished SET GLOBAL innodb_fast_shutdown = 0; ---source include/restart_mysqld.inc - --disable_query_log call mtr.add_suppression("Header page consists of zero bytes"); call mtr.add_suppression("Checksum mismatch in datafile"); call mtr.add_suppression("but the innodb_page_size start-up parameter is"); call mtr.add_suppression("adjusting FSP_SPACE_FLAGS"); --enable_query_log +--source include/restart_mysqld.inc let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let MYSQLD_DATADIR=`select @@datadir`; diff --git a/mysql-test/suite/innodb/t/innodb_bug59641.test b/mysql-test/suite/innodb/t/innodb_bug59641.test index bca3f4a92c1..5f7528cf01a 100644 --- a/mysql-test/suite/innodb/t/innodb_bug59641.test +++ b/mysql-test/suite/innodb/t/innodb_bug59641.test @@ -2,11 +2,11 @@ # Bug #59641 Prepared XA transaction causes shutdown hang after a crash -- source include/not_embedded.inc -# The server would issue this warning on restart. -call mtr.add_suppression("Found 3 prepared XA transactions"); -# Close tables used by other tests (to not get crashed myisam tables) -flush tables; +--disable_query_log +call mtr.add_suppression("Found 3 prepared XA transactions"); +FLUSH TABLES; +--enable_query_log CREATE TABLE t(a INT PRIMARY KEY, b INT)ENGINE=InnoDB; INSERT INTO t VALUES(2,2),(4,4),(8,8),(16,16),(32,32); @@ -17,7 +17,6 @@ XA END '123'; XA PREPARE '123'; CONNECT (con1,localhost,root,,); -CONNECTION con1; XA START '456'; INSERT INTO t VALUES(3,47),(5,67); @@ -26,7 +25,6 @@ XA END '456'; XA PREPARE '456'; CONNECT (con2,localhost,root,,); -CONNECTION con2; XA START '789'; UPDATE t SET b=4*a WHERE a=32; @@ -34,30 +32,13 @@ XA END '789'; XA PREPARE '789'; CONNECT (con3,localhost,root,,); -CONNECTION con3; -# Kill the server without sending a shutdown command --- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- shutdown_server 0 --- source include/wait_until_disconnected.inc - -# Restart the server. --- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- enable_reconnect --- source include/wait_until_connected_again.inc +--source include/kill_and_restart_mysqld.inc SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t; COMMIT; -# Shut down the server. This would hang because of the bug. --- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- shutdown_server --- source include/wait_until_disconnected.inc - -# Restart the server. --- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- enable_reconnect --- source include/wait_until_connected_again.inc +--source include/restart_mysqld.inc SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t; diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index d2da6e4f3b2..371d761ba86 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -13,6 +13,14 @@ if (`SELECT @@innodb_log_file_size = 1048576`) { --skip Test requires innodb_log_file_size>1M. } +--disable_query_log +call mtr.add_suppression("InnoDB: Resizing redo log"); +call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files"); +call mtr.add_suppression("InnoDB: New log files created"); +call mtr.add_suppression("InnoDB: The log sequence numbers [0-9]+ and [0-9]+ in ibdata files do not match the log sequence number [0-9]+ in the ib_logfiles"); +FLUSH TABLES; +--enable_query_log + CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; BEGIN; INSERT INTO t1 VALUES (42); @@ -177,12 +185,5 @@ let SEARCH_PATTERN= InnoDB: Renaming log file .*ib_logfile101 to .*ib_logfile0; --let $restart_parameters= --source include/start_mysqld.inc ---disable_query_log -call mtr.add_suppression("InnoDB: Resizing redo log"); -call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files"); -call mtr.add_suppression("InnoDB: New log files created"); -call mtr.add_suppression("InnoDB: The log sequence numbers [0-9]+ and [0-9]+ in ibdata files do not match the log sequence number [0-9]+ in the ib_logfiles"); ---enable_query_log - SELECT * FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/xa_recovery.test b/mysql-test/suite/innodb/t/xa_recovery.test index 9f25e4d1f30..f5c2b655545 100644 --- a/mysql-test/suite/innodb/t/xa_recovery.test +++ b/mysql-test/suite/innodb/t/xa_recovery.test @@ -1,7 +1,3 @@ -if (`select plugin_auth_version <= "5.6.24" from information_schema.plugins where plugin_name='innodb'`) -{ - --skip Not fixed in InnoDB as of 5.6.24 or earlier -} --source include/have_innodb.inc # Embedded server does not support restarting. --source include/not_embedded.inc @@ -9,6 +5,7 @@ if (`select plugin_auth_version <= "5.6.24" from information_schema.plugins wher # MDEV-8841 - close tables opened by previous tests, # so they don't get marked crashed when the server gets crashed --disable_query_log +call mtr.add_suppression("Found 1 prepared XA transactions"); FLUSH TABLES; --enable_query_log @@ -18,10 +15,7 @@ connect (con1,localhost,root); XA START 'x'; UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; connection default; -call mtr.add_suppression("Found 1 prepared XA transactions"); - ---source include/kill_mysqld.inc ---source include/start_mysqld.inc +--source include/kill_and_restart_mysqld.inc disconnect con1; connect (con1,localhost,root); From 2de0e42af577eb803278187e3b82a5bb17ac3b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Jan 2017 15:11:46 +0200 Subject: [PATCH 138/167] Import and adjust the InnoDB redo log tests from MySQL 5.7. --- .../suite/innodb/include/log_file_cleanup.inc | 16 + .../suite/innodb/r/log_corruption.result | 19 + mysql-test/suite/innodb/r/log_file.result | 344 ++++++++++++++++++ .../suite/innodb/r/log_file_name.result | 77 ++++ .../suite/innodb/r/log_file_name_debug.result | 8 + .../innodb/r/log_file_size_checkpoint.result | 4 + mysql-test/suite/innodb/t/log_corruption.test | 148 ++++++++ mysql-test/suite/innodb/t/log_corruption.zip | Bin 0 -> 94694 bytes mysql-test/suite/innodb/t/log_corruption0.zip | Bin 0 -> 1211 bytes mysql-test/suite/innodb/t/log_corruption1.zip | Bin 0 -> 1257 bytes mysql-test/suite/innodb/t/log_corruption2.zip | Bin 0 -> 1304 bytes mysql-test/suite/innodb/t/log_corruption3.zip | Bin 0 -> 1304 bytes mysql-test/suite/innodb/t/log_corruption4.zip | Bin 0 -> 1308 bytes .../suite/innodb/t/log_corruption4a.zip | Bin 0 -> 1310 bytes mysql-test/suite/innodb/t/log_corruption5.zip | Bin 0 -> 1308 bytes mysql-test/suite/innodb/t/log_corruption6.zip | Bin 0 -> 1311 bytes mysql-test/suite/innodb/t/log_file.test | 261 +++++++++++++ mysql-test/suite/innodb/t/log_file_name.test | 268 ++++++++++++++ .../suite/innodb/t/log_file_name_debug.test | 31 ++ .../innodb/t/log_file_size_checkpoint.test | 32 ++ storage/innobase/handler/ha_innodb.cc | 10 +- storage/innobase/srv/srv0start.cc | 2 + 22 files changed, 1214 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/innodb/include/log_file_cleanup.inc create mode 100644 mysql-test/suite/innodb/r/log_corruption.result create mode 100644 mysql-test/suite/innodb/r/log_file.result create mode 100644 mysql-test/suite/innodb/r/log_file_name.result create mode 100644 mysql-test/suite/innodb/r/log_file_name_debug.result create mode 100644 mysql-test/suite/innodb/r/log_file_size_checkpoint.result create mode 100644 mysql-test/suite/innodb/t/log_corruption.test create mode 100644 mysql-test/suite/innodb/t/log_corruption.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption0.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption1.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption2.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption3.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption4.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption4a.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption5.zip create mode 100644 mysql-test/suite/innodb/t/log_corruption6.zip create mode 100644 mysql-test/suite/innodb/t/log_file.test create mode 100644 mysql-test/suite/innodb/t/log_file_name.test create mode 100644 mysql-test/suite/innodb/t/log_file_name_debug.test create mode 100644 mysql-test/suite/innodb/t/log_file_size_checkpoint.test diff --git a/mysql-test/suite/innodb/include/log_file_cleanup.inc b/mysql-test/suite/innodb/include/log_file_cleanup.inc new file mode 100644 index 00000000000..ef57d58b788 --- /dev/null +++ b/mysql-test/suite/innodb/include/log_file_cleanup.inc @@ -0,0 +1,16 @@ +# Remove ibtmp* which are re-generated after each mysqld invocation +# skip auto generated auto.cnf from list_files +--remove_files_wildcard $bugdir ibtmp* +--remove_files_wildcard $bugdir auto.cnf +--list_files $bugdir +--remove_files_wildcard $bugdir ibdata* +--remove_files_wildcard $bugdir ib_logfile* +--remove_files_wildcard $bugdir undo00* +--copy_file $bugdir/bak_ibdata1 $bugdir/ibdata1 +--copy_file $bugdir/bak_ibdata2 $bugdir/ibdata2 +--copy_file $bugdir/bak_ib_logfile0 $bugdir/ib_logfile0 +--copy_file $bugdir/bak_ib_logfile1 $bugdir/ib_logfile1 +--copy_file $bugdir/bak_ib_logfile2 $bugdir/ib_logfile2 +--copy_file $bugdir/bak_undo001 $bugdir/undo001 +--copy_file $bugdir/bak_undo002 $bugdir/undo002 +--copy_file $bugdir/bak_undo003 $bugdir/undo003 diff --git a/mysql-test/suite/innodb/r/log_corruption.result b/mysql-test/suite/innodb/r/log_corruption.result new file mode 100644 index 00000000000..64a8824189f --- /dev/null +++ b/mysql-test/suite/innodb/r/log_corruption.result @@ -0,0 +1,19 @@ +# redo log from before MySQL 5.7.9 +# redo log from before MySQL 5.7.9, with corrupted log checkpoint +# redo log from before MySQL 5.7.9, with corrupted log block +# redo log from "after" MySQL 5.7.9, but with invalid header checksum +# distant future redo log format, with valid header checksum +# valid header, but old-format checkpoint blocks +# valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2, invalid block checksum +# --innodb-force-recovery=6 (skip the entire redo log) +# valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2, invalid block number +# --innodb-force-recovery=6 (skip the entire redo log) +# Test a corrupted MLOG_FILE_NAME record. +# valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2 +# Test a corrupted MLOG_FILE_NAME record. +# valid header, invalid checkpoint 1, valid checkpoint 2 +ib_logfile0 +ib_logfile1 +ibdata1 +my.cnf +my_restart.err diff --git a/mysql-test/suite/innodb/r/log_file.result b/mysql-test/suite/innodb/r/log_file.result new file mode 100644 index 00000000000..a1ebdf037fa --- /dev/null +++ b/mysql-test/suite/innodb/r/log_file.result @@ -0,0 +1,344 @@ +# Testcase for the following bugs +# Bug#16691130 - ASSERT WHEN INNODB_LOG_GROUP_HOME_DIR DOES NOT EXIST +# Bug#16418661 - CHANGING NAME IN FOR INNODB_DATA_FILE_PATH SHOULD NOT SUCCEED WITH LOG FILES +# Write tmp/log_file/my.cnf +# Start mysqld without the possibility to create innodb_undo_tablespaces +# Remove undo001,undo002,ibdata1,ibdata2,ib_logfile1,ib_logfile2,ib_logfile101 +my.cnf +my_restart.err +# Start mysqld with non existent innodb_log_group_home_dir +# Remove ibdata1 & ibdata2 +my.cnf +my_restart.err +# Start mysqld to create tablespaces according to my.cnf +# Backup tmp/logfile/* +# 1. With ibdata2, Without ibdata1 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +ibdata2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 +# 2. With ibdata1, without ibdata2 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 +# 3. Without ibdata1 & ibdata2 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 +# 4. Without ibdata*, ib_logfile* and with undo00* +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +my.cnf +my_restart.err +undo001 +undo002 +undo003 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +my.cnf +my_restart.err +undo001 +undo002 +undo003 +# 5. Without ibdata*,ib_logfile* files & Without undo002 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +my.cnf +my_restart.err +undo001 +undo003 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +my.cnf +my_restart.err +undo001 +undo003 +# 6. Without ibdata*,ib_logfile* files & Without undo001, undo002 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +my.cnf +my_restart.err +undo003 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +my.cnf +my_restart.err +undo003 +# 7. With ibdata files & Without undo002 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo001 +undo003 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo001 +undo003 +# 8. With ibdata files & Without undo001, undo002 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo003 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo003 +# 9. Without ibdata*, without undo*, Without ib_logfile1 and with ib_logfile2 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile2 +my.cnf +my_restart.err +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile2 +my.cnf +my_restart.err +# 11. With ibdata*, without ib_logfile1 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 +# 12. With ibdata*, without ib_logfile2 +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 +# Cleanup +bak_ib_logfile0 +bak_ib_logfile1 +bak_ib_logfile2 +bak_ibdata1 +bak_ibdata2 +bak_undo001 +bak_undo002 +bak_undo003 +ib_buffer_pool +ib_logfile0 +ib_logfile1 +ib_logfile2 +ibdata1 +ibdata2 +my.cnf +my_restart.err +undo001 +undo002 +undo003 diff --git a/mysql-test/suite/innodb/r/log_file_name.result b/mysql-test/suite/innodb/r/log_file_name.result new file mode 100644 index 00000000000..84107403cf2 --- /dev/null +++ b/mysql-test/suite/innodb/r/log_file_name.result @@ -0,0 +1,77 @@ +SET GLOBAL innodb_file_per_table=ON; +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t3(a INT PRIMARY KEY) ENGINE=InnoDB; +BEGIN; +INSERT INTO t3 VALUES (33101),(347); +INSERT INTO t1 VALUES (42),(9),(101); +RENAME TABLE t1 TO t2; +UPDATE t2 SET a=347 where a=42; +COMMIT; +# Kill the server +# Fault 0 (no real fault): Orphan file with duplicate space_id. +# Fault 1: Two dirty files with the same space_id. +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +# Fault 2: Wrong space_id in a dirty file, and a missing file. +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +# Fault 3: Wrong space_id in a dirty file, and no missing file. +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +# Fault 4: Missing data file +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +# Fault 5: Wrong type of data file +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +SELECT * FROM t2; +a +9 +101 +347 +SELECT * FROM t3; +a +347 +33101 +SHOW TABLES; +Tables_in_test +t2 +t3 +DROP TABLE t2,t3; +CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB; +ERROR HY000: Tablespace for table '`test`.`t0`' exists. Please DISCARD the tablespace before IMPORT +CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t0; +CREATE TABLE u1(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE u2(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE u3(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE u4(a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO u4 VALUES(1); +RENAME TABLE u4 TO u5; +RENAME TABLE u5 TO u6; +INSERT INTO u6 VALUES(2); +# Kill the server +# Fault 6: All-zero data file and innodb_force_recovery +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +# Fault 7: Missing or wrong data file and innodb_force_recovery +SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS +DROP TABLE u1,u2,u3,u6; +# List of files: +SHOW TABLES; +Tables_in_test diff --git a/mysql-test/suite/innodb/r/log_file_name_debug.result b/mysql-test/suite/innodb/r/log_file_name_debug.result new file mode 100644 index 00000000000..e82feef870c --- /dev/null +++ b/mysql-test/suite/innodb/r/log_file_name_debug.result @@ -0,0 +1,8 @@ +# +# Bug#19685095 DO NOT CARE ABOUT UNRESOLVED MLOG_FILE_NAME +# IF THERE ARE NO OPERATIONS TO APPLY +# +SET GLOBAL DEBUG_DBUG='+d,fil_names_write_bogus'; +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; +# Kill the server +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/log_file_size_checkpoint.result b/mysql-test/suite/innodb/r/log_file_size_checkpoint.result new file mode 100644 index 00000000000..068b1368e1e --- /dev/null +++ b/mysql-test/suite/innodb/r/log_file_size_checkpoint.result @@ -0,0 +1,4 @@ +CREATE DATABASE logtest; +USE logtest; +# Kill and restart: --innodb-log-files-in-group=2 --innodb-log-file-size=4M --innodb-buffer-pool-size=50M +DROP DATABASE logtest; diff --git a/mysql-test/suite/innodb/t/log_corruption.test b/mysql-test/suite/innodb/t/log_corruption.test new file mode 100644 index 00000000000..725c8db6360 --- /dev/null +++ b/mysql-test/suite/innodb/t/log_corruption.test @@ -0,0 +1,148 @@ +--source include/have_innodb.inc +--source include/have_innodb_16k.inc + +let bugdir= $MYSQLTEST_VARDIR/tmp/log_corruption; +--mkdir $bugdir +--let SEARCH_RANGE = -50000 +--let SEARCH_FILE = $bugdir/my_restart.err +--let SEARCH_ABORT=NOT FOUND +--let $args=--defaults-file=$bugdir/my.cnf --loose-console >> $SEARCH_FILE 2>&1 + +perl; +die unless open IN, "<", "$ENV{MYSQLTEST_VARDIR}/my.cnf"; +my $found; +while () { $found=$1 if /^(lc-messages-dir=.*)/ } +close IN; + +die unless defined $found; +die unless open OUT, ">", "$ENV{bugdir}/my.cnf"; +print OUT "[mysqld] +$found +innodb_data_home_dir = $ENV{bugdir} +datadir = $ENV{bugdir} +secure_file_priv= +skip_aria +core_file +"; +EOF + +--echo # redo log from before MySQL 5.7.9 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption.zip -d $bugdir > $SEARCH_FILE +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported. This redo log was created before MySQL 5\\.7\\.9\\.; +--source include/search_pattern_in_file.inc + +--echo # redo log from before MySQL 5.7.9, with corrupted log checkpoint +--remove_file $bugdir/ib_logfile0 +--copy_file $bugdir/ib_logfile1 $bugdir/ib_logfile0 +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported. This redo log was created before MySQL 5\\.7\\.9, and we did not find a valid checkpoint; +--source include/search_pattern_in_file.inc + +--echo # redo log from before MySQL 5.7.9, with corrupted log block +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption0.zip -d $bugdir > $SEARCH_FILE +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported. This redo log was created before MySQL 5\\.7\\.9, and it appears corrupted; +--source include/search_pattern_in_file.inc + +--echo # redo log from "after" MySQL 5.7.9, but with invalid header checksum +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption1.zip -d $bugdir > $SEARCH_FILE +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: Invalid redo log header checksum; +--source include/search_pattern_in_file.inc + +--echo # distant future redo log format, with valid header checksum +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption2.zip -d $bugdir > $SEARCH_FILE +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: Unsupported redo log format. The redo log was created with malicious intentions, or perhaps\. Please follow the instructions at http://dev.mysql.com/doc/refman/5.7/en/upgrading-downgrading.html; +--source include/search_pattern_in_file.inc + +--echo # valid header, but old-format checkpoint blocks +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption3.zip -d $bugdir > $SEARCH_FILE +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: No valid checkpoint found .corrupted redo log; +--source include/search_pattern_in_file.inc + +--echo # valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2, invalid block checksum +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption4.zip -d $bugdir > $SEARCH_FILE +# Anything below innodb_force_recovery=6 must find a valid redo log. +# Missing tablespace files are tolerated already with innodb_force_recovery=1. +--error 1 +--exec $MYSQLD $args --innodb-force-recovery=5 +let SEARCH_PATTERN=InnoDB: Log block 2372 at lsn 1213952 has valid header, but checksum field contains 144444122, should be 3362026715; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=InnoDB: Ignoring the redo log due to missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\.; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=Plugin 'InnoDB' registration as a STORAGE ENGINE failed; +--source include/search_pattern_in_file.inc +--echo # --innodb-force-recovery=6 (skip the entire redo log) +--error 1 +--exec $MYSQLD $args --innodb-force-recovery=6 +let SEARCH_PATTERN=InnoDB: Cannot create sys_virtual system tables. running in read-only mode; +--source include/search_pattern_in_file.inc + +--echo # valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2, invalid block number +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption4a.zip -d $bugdir > $SEARCH_FILE +# Anything below innodb_force_recovery=6 must find a valid redo log. +# Missing tablespace files are tolerated already with innodb_force_recovery=1. +--error 1 +--exec $MYSQLD $args --innodb-force-recovery=5 +let SEARCH_PATTERN=InnoDB: Ignoring the redo log due to missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\.; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=Plugin 'InnoDB' registration as a STORAGE ENGINE failed; +--source include/search_pattern_in_file.inc +--echo # --innodb-force-recovery=6 (skip the entire redo log) +--error 1 +--exec $MYSQLD $args --innodb-force-recovery=6 +let SEARCH_PATTERN=InnoDB: Cannot create sys_virtual system tables. running in read-only mode; +--source include/search_pattern_in_file.inc + +--echo # Test a corrupted MLOG_FILE_NAME record. +--echo # valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2 +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption5.zip -d $bugdir > $SEARCH_FILE +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: Log scan progressed past the checkpoint lsn 1213964; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=InnoDB: ############### CORRUPT LOG RECORD FOUND ##################; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=InnoDB: Log record type 55, page 151:488\. Log parsing proceeded successfully up to 1213973\. Previous log record type 56, is multi 0 Recv offset 9, prev 0; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= len 22. hex 38000000000012860cb7809781e80006626f67757300. asc 8 bogus ; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=InnoDB: Set innodb_force_recovery to ignore this error; +--source include/search_pattern_in_file.inc + +--echo # Test a corrupted MLOG_FILE_NAME record. +--echo # valid header, invalid checkpoint 1, valid checkpoint 2 +--remove_file $bugdir/ib_logfile0 +--exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption6.zip -d $bugdir > $SEARCH_FILE +--error 1 +--exec $MYSQLD $args +let SEARCH_PATTERN=InnoDB: ############### CORRUPT LOG RECORD FOUND ##################; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=InnoDB: Log record type 55, page 151:488\. Log parsing proceeded successfully up to 1213973\. Previous log record type 56, is multi 0 Recv offset 9, prev 0; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=InnoDB: Hex dump starting 0 bytes before and ending 13 bytes after the corrupted record; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= len 22. hex 38000000000012860cb7809781e80006626f67757300. asc 8 bogus ; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=InnoDB: Set innodb_force_recovery to ignore this error; +--source include/search_pattern_in_file.inc + +--list_files $bugdir +--remove_files_wildcard $bugdir +--rmdir $bugdir diff --git a/mysql-test/suite/innodb/t/log_corruption.zip b/mysql-test/suite/innodb/t/log_corruption.zip new file mode 100644 index 0000000000000000000000000000000000000000..6f126c2edf0e70634b468b6bad53633e1a127d22 GIT binary patch literal 94694 zcmeI5c~n!^`uFX%b*L4r16XCKbwEWxMMTCp0arl~QBeYTI$~qG^t9nmj>+BoiZo2ynas^S!{f8K`TBF1xAztcniC5WSzl{Tdf=kOo@Jfx z6GIG>Dp$Yy9!XW;2NHk;{y!q{3>z@};9v97e)kP#N*{J)&Yy8!+CqE2P*ZxmNCdS=l>B|BPg2xbyW~@TcpEQ%>GaTgH0k``Mqq zixPXS+n4BjbKQaU3U!Cr|N3VC`h#qR&fSEAg+Kk`x#1@h_1Lw)F8J-`Pl=;d;q_K! zntmor2^&p!?fly0)c0S1W3qQ=mFSmwUw!la2$Gbf>twmV4Dm?P>kBk)()MpMpzEno ze;8qQ50~*8yLANRQKly+lUTj?jSTeZ&$gJmm{}X@TC`aZ9$Q2REh;NezN(_*D}vc4 zE0{VJKG=oBF{ua42pP=Gkfa&VmKUxLS}BS~DTa2oILgN+v}u!LkAHmB zwG>h@)qq_P7otc+>z$3kDNO4Uo^@znOcGmYC3<1gWOBCv_0WYu*n7Te;9pntzm+*J6QW6~dO@=Jw_~A@syem)&CpZZF9vrFP}7m}uG{N#K|nA~aYgNsxoyBTkkwXn(W{ z(Uc|~ZNE-vmnIzn6_Mh`UtTdmca)auw2;SHzs7IT3GCrLV(d~$CRlrLr69dJv`3sM zt*|br32EvIWZWRlSo`ctgeJ|n!R;l%Tv{guodI%zv`Ok$Oi+(XiZIFx5t5|lV2|t( z)2E7X*dsQOW=DFk3Q3k`mj|-zk!E)uWM?aFX3Rn!T~lHrB|Ah&mC{K8N$FGBVfKi3 zBZT{_*m9s$lC;#C6%)uE>6PU|9^shOL>rKaG%2MhM2Olb%?|W8jx-ax-5#;()YZ{F z;XE%;4+v8mkt=7T#{ke<|D z;W$0o?52XUh^~-at%$BG9=^*-^8Ip7-CH8OUOcr~j+5)xbn4cLD7oUn**yMz zHTG9VqEqRH2 zISF?yCoHcPyx^v7rl?k{hB7W~7O#nr4`JNhY^+pG3}Lu93H_I=&hOWH!L8pc-WWla z>&L#}c5N1GMj%V7%__LZmJ?K~Ybv;*n~lG(R;$=CK_42~EZ!19__kl$DR6rPL9XA+ zNoc;DDBq8%;O<^tL5T9WUETYm9I@wn(yzHX5xvwPL(Pa@Oi;H<^?awK<<*|c4Z_5@ zxl7f)n0qf09Mi8}9?cQ*TL#X!PwXg};9i@X5@>RxSzOqVlk9P%lZl9JQ}&hA_IrjK zd1Vd|j~96kE?8EhZWcTz-EVVPU*qltS3!I1?0Mr~@_E(?EswCqqO1AC2t(_9La-X2 z+kK+RA0Nfrd(ncc@bSKSM0B(n-p^QB?bm)5`h~&9Z1osEa;aJJ*!=AC4pS2}+H?Rf z&Iu1r@nv>-QTyAyTC^9qze;upQ*AI_{bTvMv*sa%N5&PSk~+3-3wYh0V%W7q%{VYS6t|bnH@F7$znmQT&$HnOsOc%RJELpsnZi;g(-Tm|#=S=tWWN;qJ%V zJUwbYxEGGT~!2;76;|Kic^^yG|IpHX)Z? z>;+c_;^*_k1f=j03sG|xA@6zjmli~_keWEtrsbej4xy2k)}!w(ASiu;j|ic#*MD#i zH~wC8y)BEKxz60CD;4`|dSq^l*mlimYgZ~UWU_IKhG;|WL`315bIymd{ZJc@C%sWv z_-j?RVhQWBCX`(Mv2%9w6FkPh*&Wp8cY2)fzfo&G%>qe90 z3aSlJcVgeHbdNo0WdcPvg;Ht}#N zZBFG`vxC@aR3|d+Xd?E>F5kh|6hHf_7>~giF9nqgA6rDj8jc@zvx$_IT92QWANCjZ zT~^!_SUXDEmzLR1GSv>~XKu{KJ}4ExAFKHGri)W(C%!m$i^K%@^I&!n0Je znvKiSy*7?p^PZT8renK4jOR`&B)UI!jO~9$X?Yn=R|;Z)p7D(l!?{9rU^Cm~9+H=p z=n!}eJ5m%D-d`7v6JdfG)@2$7NA1xMOWAj>2pYQZF}R$*K3!H}MBuT?_o&M^!chWp zx^b>9Pm$GERrFd{X$Sp!P<4hSf!^6skU3e-jbFC9zTcc^p?Q084ySW0F4C$oymR%J zZS-#N=R5i6(#>}4L7I8aKD;;@Tau0PFHE8%L=VwzG2wx?#WpAI&!P91UJI|z@ubGy z(C!kLMOMp4(h$3R=*vy_`|1FEDHDf7Sj92rB!9FIYDpG-nONYKa?@%ZY1EB z?(bXuhPx~+C+#ppe;vI@&}hIqjl2D3C6X}_XLgrn)Up`mD;dWsTd_?dh3{|;ahsGM zB-xg4Df7Z5YvYglR_K*gs4_OMSljI2Ux9C3*+|5_EWHxWMmNyfmS>Y)NQot97X)#G zR9#c)g3hpTG^TX^mvm-5TK-#Xvd`=2oc(w)&d8&;CfY@RLWD$<^)nFaV(Rh(7V>@d zsfV_S*Oog44lJlQUlL*(#eX73Oh5-N3`7Wa?6RSr!S@S#6K-^h&J2qCOqjYa8x!mz zRpx~&pKK~#MPp}Dc`A*`j*({N7t6fHilWljido&R9f}=I>uawNUeuom^#a>>&J9Rr)^)bS8 zvJ)-ZYiDYXQZe7mpe2RSu0joR+v=c8=D%rLy7=2^6;F6|jf(dcfi=Rw+M1*oi}w1N z@;c``$VmZB;%3j!S`t0NpAn@_)NO7x$f*CWSJS?X))^_~DQF!}VGB8WV%+e$)`b%@ zk?gm6I@$vAY5yUQ5^JIRYNiTpa*r2xf_t#4j{c5Yd)CiH@?$y4N+pgh)FQImn9(EE zGgi9G827vzWHc6;Xn);8cSe%k{>&~pu>L`pVv`p{k7Uf4k(SsyYq&K93BaKG^G_8Y zpRwJ#v@G=2fZp#s6iQ98a2c3sIK~n`=9z#VS*9^ux;oxHWu}hg*VL#=F{bg58eO)( z%hsNmyX_c`!#@G0kxr&Txq7^N{7gCRcqdStyk~?wYJ1A>sr7cAsoHmGzYlAHr%?`< z89Joangy1jNTKbv?1`%}>bB(vJxVt2Y6*Qbir`o#)`sbS{7bTMI*9Y3WPjE>FJ^eZaYg6cU<(N!D;_AW zYd!B7&JgxI8bjol*%?c2T#?$?wd}JLf7}{U$$M-7uuw%!Zu>IwK!W+G$Jq!~@7Nih z0@m_OR>|2Ke?6~0Gb3jH_8d#6z`shjzCSse&8d~`~@1)>1(0&bZgWm8}+ql zJT3PUALgmfICKQI=YFx6V2imsD4Bontol&u@cArz;DN}^Hu*YRh~gK}9g{6c^%~WC zs1KeXsKc_V6;Q)Y?*hGvN96XV)O!26=jK!Py_rNx=E|%U!%|h52zooZjdO5ok1^>O zA7uj&Ta9bw2TDxdwl|ri{+aD}Hi(4zd)z_0+5`tMM{2!8yHAYV(mL9X&_~o|B`Hv5 zl*@x>g$Aelp+@}pZS*FGfHN^7)7|3jr6$#z}8^9pp2;;S*M=U{#JmSM_gltNX#n-jvvB_NUbaHSe*+*O88Z`>f zm14mHdPC5aSjl7IV#s}_?>C>>zAc?3*FXR>s65TP;+Ip!=I*(J7tJ32Q`hn}n0QzZ z=I$oqF$7=h-QIno{s(LhsMgTWvZ^)mbhOhB%)rzNjJ{_4cr5x{QQ%QfEnAkNtPZT= z=Sj8&e2rX)DC79?6p&=t477VDTV|hUi*RAlgSx#P7omj!8ZKf=) zMpyWumt*DoaWDMLmearM$5r^*E~m@&b6#*on<-1G@fF<5o5h_lwAL8 zC*i*3s^9hRaSGfKfm+z#^n%OWY`nM{^D86HNqA&ALAjdxD}&@DbXbn4MMQ-#ayN^O zBcehX@=k$2MOcM+3{V?dorEWsBTK7YUU1JXN0h3EUvT3#8>?26!LO})FaF%BYhKA+ z8{SbFU!f~j#{_FW>kb=E8|%7gMqaW*P|b)c z<9fXccz9Z;U8)wFYI#_Wd`sQ^-IrNDBi}lJ@@3+|M3SaHe(qYT-+uSp;RvirdbhSm zw=yxstv@bxPerHADBG+;BpT4vHVe+Ej@y_cPyB9?iGz>-F62i>z~Fin-QULsE}frq zv%SG zTq*Xif8X)QK#Q5%%sk4$*OaqcKK6O3n`KQjPOHjJOaJ=uZ~({|5jBplr*+%z7a$VV zd!#5+&Y`E1nn3Cy2~!3hWZEjMuM9r2kcUWx$)IE4>abLn^8>P+RLTwZ0aqGQf$jkK zRjM-v?FHZAM+|gLe-mMWrZ=Uu-q0B!NQH8|E4a~4n$6*bJj{A&;`0l6;qz5~eQSn@ zc>TLEJAV@uub8NjiiS0>ual*vmOTy;YD|6Ac6~~<6-??3V5darJqvj?QcYP4$cWr6SYCQ_Nl7W11A6~54Z^SgB!p9Pd7%sRwx{60Z%m?_Yc<*%+~YCXbS<-zma%s zN&+h)TkX50&kqwnk_55b5l?^cjy!BFbX*OdC7OJH{(+;kB62@nZzNtScUDE2_P1W< zCfwKfq4Q{wlcA?`{U7hGG5Cpd=7GYA{wRm?zFW(hfAz4&n=efcth*|zZ{a27yh_nI z**{{V7MFG(zn@jHHdO0)@yClm$>_u*tT`IZ9V2mBRXx2Swa2a9s&e)>93YJO(k#2M z1-x~m+3`twKKo0Zs)Az2eVzrIZ*)JpqUh;KAKk9W1id_$#+!5RkWL zh*m`XW$oO?F1KC2IouW&+S~N9j~o?QJ6^ziW57C}I}+l?S?BWV_Tn;wvUZ_==qvQo zGh|^hMKL?!RykJ7CzDqGv>|q77AlK$(tc?}!s3PBZ8GrxIkA`iYz2mYir>2cYFALZ z`hTWfHJvN%d1Jkl6FGuVw`U-jFtNcSKQl#>^VaV*h9kD!Bqp@!dgl8Q+7R-Yd<0X+ zK{CruOjNe5|DY+)NeESMS{*b*n-W`}Z6we6&y?`z-{RBX?XBlK2953PWYP(R+B78R z22jZigJZ-<=57Re@rH$zRB&JGUtVq28Ui$+D_||0llTTvdu)eLPmZ2{B0uYG0I#{` zb-%{6tS`P;xVOHJ6f~FuyrI0pQGT>b9Z)}iXpf>HagkToeWyCMC??gTnR{fsW2>h# z9(mc!ef}6hvYW*Od^tky*^YKEY%X^5C7D^{u->*$v+eZ?_X4+X_YcJ4GvXE#K~vO| zD3y8SO)1;(Z9vgA zPoZa7&Ph|O@KPN$<@RBZ@RqRVcI$_J%F&$epkZbH6N6VDt`Tf_^-CNoaKC9CXdJs5 z<>1M^nf|#9zScZ6bPLvk-t92_DkY}pf+cnWWoL40ec-W*mka3!usaBpRZIoVPOJ_I zeR5P|d(VZkF<&oyC@R}&o9zjp&+*=e1Yyt~9;4y9pKo#i#GjV|g*h)WVB!eazGkaw z3jHQ5%*qkMgl!EALHDgpyE?Kf@c7}dYBSoS?mV4{^!a}Z%&CAJx*S2B&q|5R7hodG z7iItOpeO3+xR&EK!sW5Y4+h^~`u*(|_T!Z;?ueMFpfzvUQmdx_#fIdQO+lM97@5Oz z2)pf!sb0ztmhsz$x?8>pAIgdD@i?mIc*x_Zy?>jToZ-*40UfShbqqA{q^IdFm`R~) zZ?x>rG_)hB^87A0KNM}raTp{_?{|*d=k$3rKT#(a*1rI1Pa~U?yz(^06iH3d&Ta~F z!@IF-XQdJ4uZNk*RcDK`{JVnc>HAX79zT9(Q3;DPq_u7`T>L#UUD^ED)b~zRg%<*Z z2-Q(~u+8D-m#U5yDVPf~gLOXvX!&l5v|p8xwanl=++y=eaf!&Sb7sSkvm@8Llzc@X%@Cz5QcC(gprl zG=1lu-*v;*Ar|c1#g%-jc}B^Q0=m%;54Ju!viGkw4()9~Jrt;jTRdvLNnn39nD=lL zA*YgMmBM-!EhyVcMZt|DbKB?GQ7{B1GF5#c3TKs}JE(xBdPzJ$uCh0<@n$ImAZ}{) zh~nB#@v}f73yC@ZBq?+b-6;e!8Zs1V5S(Oz1)F5!V0Tc4&m5VO0>XPxH4Jv6Re837 zhVj7$q_>5XN1#n|x-hbYi{etjM?C0i@^dJD7F)~Kf+WZ*VEpK$%nhvO$i`%#31W;0 zZTY7H+}v|%uhjlg^a z85K_f8*BXg)sl_1>_!O=8dt}}vxT6ouFE}N}FU!Frp8$aY5=d z9>TrHbLAiROhdsET1Wb_67870XPb*2M3?0LC<{K>oz304sM7VMzv1t*DP>j(Ts}`O9%& zw|RiV7+f7aQU;2_;P3yFNaC8PXG;fdPc=ev%4%72L5e6jPzZ60OxY^HyX%TXAQ~c_ z7xtgxS9G5c_`+n6eF9x{UF3TKWiFGJHTM(0y z-_NnRIkE>7qDsjCNw$k*CdtGGu#16M-EK5YxnZH&sA2h3Gy=v~o@`reQv$F!pxm6~ z+W?W1IHaH^ke;RZU%k5>GT17DXg!1C;5QUgDXyR2))0Q1GZKoLjAWDk7P%q%Y# z&@P_T63+e%a-BwOCdCd6e1U9RP)F!D5wdzx6hl z!Bu?t4z(=ZqN)j3wIlyDSZK|hlm)FR1go0aacf$sLkji8G7Op#^0 zB(@3_oH>qFYc=xD2ZgBGOBy9kcB9l}SoVM!3`dzL@2F)lx=++(<$+0$-f1gqg%B`StYMrC z8YPJtKYVjU6;!Or;{HFaTms%-qw@~}<5>yBAnkbL8|blaRxcQlC7%{y(>+1i2EF{1 zV0I~5&?MrV;-7NQW&WXM3&vNO%;jW$!yEw>bo?BHk^CsN*1OUOSjmt~ll@?+KQbtB z(^S@H^dwji8#R1`Y0HjGBE&G3#Ls?b{&aUp3$c*+FNT zp9Bk#ZYoc;__IJ;E8TM9$J9lFBS1HtiW+qSS2j{5trsYW(zsN?8*o)9mFIN8uU^t$ zzX#uCOTVLnh{8CjjJFy@83sy!ZCNpaNaH*O_g74i4@%TWQRj*Y#U+OGa-+loX3drI zi;Dz4Is;KsO)u)fDuPu1!yjMBLrbF=qq0^J+@yJpy1kr=6cvT6n23_9kB*Le#0;r4 ziG93^fS2Cpp))|7DkuY}kJ2DUN9#RePw9^gpbAP=K;ye1!l`&twYKYoL((7j5wPMD zhsf(I$8&l`bZG#nG4HfkEdLrvkkVjH;slT&kusniPG$E%i^)OqS5S}?sokxhhG?mc zLvcI;$_1p$k;YSsVu3jMSJZ$G_gOjSIB@F`es}5BjUG|;3Qvx*jH*6joa;GQr?@fF zi-1{@PE^@^_&xEpWM2NeUoa2S}pr`v5r9T4av6Vn!p* z3Y6lKq(`4P#UBPqni~FjukikQg^DF!Oh%oqSC1a?DyrItI&SZPkbPvEGSW2e4JI{e zzPD&uElaDYDtqECc+zyqHib}hJ{bkJ7wv@68|F7hm>`KmELdczw#zgnftAs&1ZG>Z z*YIh&Wd@-^!&jLT@{dp2c0-(?0IXw&a}xb_Z4FvQdOLX|8ZeGhmAS+|zg<-B0vvao z%10_z89XwTUfhq9*dma*RdSoOpOARCCv>AymYR43=Z^CFCEnNfGM}>r!NVUUGXaC6 z6^ve5#gm`)K84rzg(;liFCGGExG~lk*oPxYK?>z-!}<=n=L&w4EHSM{-q+o0-5rY_3m%L9V$nbseGwC2+Lio!6NtPZ z_jhp&^~3t?yHE+Gjl-Z}aB_cbt*6&au85UT1xDEABITT`seXa(9uvVB(D_jh{+iV% zDLJ37nw-7cZkP#y1Daac$E*Q0OF<_IV{-ri`iH-oW;!&VGC?X101z*0jfzP1+YO3A zO47gBFHE=p!>I2Duwv%ePY7&5Ov4t^4&L(;&@?!CnZ|5ij=O;AWMYgxgr)1l>WivU zA_bDh{N%8oUazdT!`YI@O{TAL(D3>&0}zN&A}$3DVd4{isscTSybaIP1wv*#ddz=v z$a(|ELJ1d_{i=LeE3gZ*L4Vt0qc_@17ZT)ldd9`CM%ic-jfSE&{CFh0W|U`kRd=JA zhyNF`zT=U@xB3s^k7<#dUBE$`bYZlIp_*}V_f5i+rCO0z8l)lOxvNo;TAHMS2xGl~ zMZ^`DqblwCLvapD)PpMI4;{*k(~Pn~c5|M=lRWHis_It9CdV4NltcC@I|6)NeAy?{ z3+e`+mh^q2C5;un)z{KC7^K2R6j@lCpVy%A5Xzs2mQ&-xd*yhzv*joT4W0ye&)97E=* zt;%uev3P^E$g8>-b*OTS1&QO_U=!!YEFc6{U?DBqJK4ut|0|mBHDR`1`x+ z?vZq^c8A)(Dr?Nn*Zxslx3K?)HaY~vG!$~RT>Z6)wc4So#o55pMfigLRO49=6^3?)7; zarPW~y@3&OlH5?<=bU~c+~6oK&mkvX8$T3rtv$YFnMrHr-q|A!a`B|$;03WtJFq$5 zbd>d(M=!wtUwWm~zN9xx{0&gsHA_b>nS+ikkhc>|)@m=QW+9{>x{#<85XstX72O|u zLrka-H<~O2@veNcNV~bA0;HJ-1`DSUXzXa#)eF0dQb{PC;|ZM#L8~|UL}anZKOHAh zV(-;@N4kz!?TdBEU#qoE+cl=oXj=J8-9e1@kQ!NEhsMMB)82W2;(=UES7}AC=Zm&| z*e`E4C-u8KBru}vbIxCT^_4@P{w!~rruwtKD-G8yr&DA(53IN_NX#l$73Er4<`6k zbG43fZ?@3Wg2Nj^)1^cT@cc1HMVJt z;_xBrg?FWU*gqt$_!2(1UFRTpa4gp-NzZRu4d(UME()t=pu-b54Z2G~T>2r`y!%E* zzY&(iq!u;@FvIOk8_&^I^;V#E6e1{NDnixFYR)Nf#sMFay1i|-l34;PQ!|0=-7H=m z#Qj*`w-1~&NXqr_4F%i>w&331FReK3nk%Y8f9+vgrIEp@4vi=>aT(MYKY*t_qNJAe z`Mi364Rw&$m3DBk>VxW>f?Q{0R{neGHYbVvKZ;URi?5e~YBjihOZl7BaT!@kK;avet%n1YiI^q<=h)#boS-rs|O^Ddp~ zXeIlx?gR1SgJMd6=C@QA>Dk4{8H0bV+5dznoUO6KFvp0-%V9hyAF*DF%la-v5w8%Z z(0$vWY-w`5;Z`kC?JQ-dz_WEy55JO$M)R{z9{wF?u~$>0t@LsU$MvU~bkTYHA`OEx zQ5|%!7>*-Pgq5YOA8+I!^2T>QhzTysi2)|S`6!PL!+_kkAeGlN}sg_Z9fN8e{^t;6j~Hi#20c7n5}c+w@U6<xd^_qic|ci4pxP`)cZzm=Zef-MBnH_4MV} z7w4f3kB+XK=0DqcKmi$ej|KaeJZjOvYha!2oQiOxno{iZYelW*&GBi(d4I5P>W+Qe zZ_~;*jcgmoMy1_fyW-eikGe%>G!1L-i4AIOE%V_|qey!7$E!K1r&k*B)5u`)_Fz<{ z(0yr@+kgP6X?RqOP?f7Q+kQ~eOW1zzZ?WQ!bQWp21yK_%fx3w85!RXC1l}H0Z{o_O zHzn^u`TUdcYPiX`KM8cpXU^mR%vRCF%IB z!U4kx#YjLK-?GSQm?^G0ka;h56v!rIGQM73t#!2e@!tdeXD4w))MOy5(Rr0gQEOUr zW;|6uVZO+V0xRN6leR+Jt!2hDMQCqk-aeoJAmvzf^3rNqqccKEj1=*9N!I+QM+uwa zDc5I;V)mn5^&$fQhI+6Ov%i*AJ>!vqW#pAOvrZ=Q>4Y}MGK2b3qtHFiXId1qo!f=A zptV10Orp_^ym!2R$3=tBfel24VnNOJVQxK~7!0Q!$~@(gw9ibe?wY$LD69VpR>H%>;6 z2|LwOJz}gL+ZRn-3G45sX6_xyoXc9qQ``U+vO7=8^u*4^D+FuDi?@*8^4_z)aKB7H zGuGY^z@-3>#bZK!)7n#Dw zJNl%CfD^?5DO6LCh44=C&w(UAlz`witn5R1J$}O_nV=Ny#w48oR*@G-GCXAaPhk${ zyuG!Kt;9hZIU8@q1$a;ecU_ zTS|#Yauk@^exUTn`10%MG5$-*QOTN5o|oyt0oxOUsoJhhWPINd;OG}p>9`(739yAG z+m?a=O@9KAwRnkUR$-|-$Zscw3{Z#~OJ-Q39ocKL0qn`S0!6Y$Sf6n2Ebpd3w=Yb= zlRrO=l+bM88^G?6L=_t^pe{D?*g$$4RCz^GifoTqo1iMl1+=}cnA+7CmHHF}T#B;8 z0pz$(zRKyIH)`>RY!Kvv%)xx{cUxMORa7-TiaHFuyPpCb{^muaDQFpj=-grZz}G8N z*Spti_@dagUyPRN&Ptl)TNiMejmn_mRlqTeY?|r;$6+sEjlrh?l<74KwGU|M10(Et zcVzosYeQqw4u5hE=={Xjf5p%R(7!mqtF1r!a&<5`B#cEfcqc*4nlvnf>)QbU+^2}s z>2AbgN>H-_i1IBUQfHL4|nRU6b(=X-qi)}rZ$H5<uz(J@!#GzaV!hS+Pm4+`eAYKPFbdJVWdT$^2LydvJGZBR#axiS&- z5Vub+ciE(Of#SFzwz7wjJ^1vsO5@16hQJY!oJ=s&sE{5xT3U6IuIO`x@xV1`wV4}-q&8fzS5f0X=O+%VH=)%!{P}9Lz)tmb zR^Y7cxaYR(Nhte&tAev~o}3K~-`Vw+DsP?dsAwrqtAtqZf8;C@S*(i+uU&}dUD6}{U^^p!+McQ@r^7aZg6GzEXw zJ<9+Ap9&69OncYNG$`<&kN_kA3H(nIc!t!dD9w|W$Rlt6kN_kA z2|xmn03-kjKmw2eBmfCO0+0YC00}?>kN_kA2|xmn03-kjKmw4!e>;J1@fUuS#sUl= zo%8kN_kA2|xmn03-kjKmw2e zBmfCO0+7IeJ%MlW7k-q+0t_IX^Zx6tfd)VVkN_kA2|xmn03-kjKmw2eBmfCO0+0YC z00}?>kN_kA2|xmn03-kjKmw2eBmfCO0+7JQvFDehu>jW*x7GI{4@dwKfCL}`NB|Om z1Rw!O01|)%AOT1K5`Y9C0Z0H6fCL}`NB|Om1Rw!O01|)%AOT1K68Ntt@cZ1k|B?g) z>=fr*yYpXf4Kx4}fCL}`NB|Om1Rw!O01|)%AOT1K5`Y9C0Z0H6fCL}`NB|Om1Rw!O z01|)%AOT1K5`Y9+RFoD=VgcsykB(Del79M;9z_1x*r zpC{b!zQIiC!;Z}PGbFro={ETGQ^GBuCv0=A-21Y!caHv&yb=G6*nm1If&!_?-Oow9K4TgSY4Q@;U@aI9yyG za$$x;vPN&BNIpaH42M)9;~5A1k8n(yUf@@JTl(XQ%X6Oz{Ry6Xs$)@)?xTt)ai`X< zewHbJTk$*lf!otc-xb?~j2{J~Aut*OBPjcm8RGcw6B<1TGr!Lgwc#6l{20=!w- PKthZ_XbGfqz(o`QQjt1H literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/t/log_corruption1.zip b/mysql-test/suite/innodb/t/log_corruption1.zip new file mode 100644 index 0000000000000000000000000000000000000000..35a02adaa6db6c1805ea49cd1fbf974796af5f58 GIT binary patch literal 1257 zcmWIWW@Zs#U|`^2@K=;`*YZ4gw~z(MWe{NC29lXc@j3bFX_+~x25+x!@~ literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/t/log_corruption2.zip b/mysql-test/suite/innodb/t/log_corruption2.zip new file mode 100644 index 0000000000000000000000000000000000000000..4e4180ac4a31d7dd963241584c3becde4627b5fe GIT binary patch literal 1304 zcmWIWW@Zs#U|`^2Xi$}NU*Hg)wtxl5We{NC29lXc@j3bFX_+~x25+w#dNBtIG(6lm zQDdWL_GXSUxdY5kgr)^H>Al!D;qKe;ZjotbW^xCE1Z=w0H+*5K>^yiZE|T;9bsnFu z;l`HFW#Zks&+eERGhIA2>-C~FvofzvS-Hx;%S1oz^3SU&Vd9}#O=}D4e_Z+((Ia-a z+`Rqy)59NQ@5?gmU)#O6Q0C~bcgN4YOxs+?wEphnx9)G|EkC{O zoq4~#NyV-D_q!QEjvoc1Aut*OBPRqJ-fm$E@MdI^W5!*S!9rt0BZ!4mumyOtvVnvc MfzT32p9GhG04y7C1^@s6 literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/t/log_corruption3.zip b/mysql-test/suite/innodb/t/log_corruption3.zip new file mode 100644 index 0000000000000000000000000000000000000000..2337c81a80be9d91138f115b0996e0d55b3f1849 GIT binary patch literal 1304 zcmWIWW@Zs#U|`^2*rqJ!t~X=a*99y| z!;B3NS)_%n-r6>pZ`kDGR3Ln3{s!-UF`0(8W2bJ-Ybg#WWb*b`P}sQf`WnUerjvcX zh8hcA?9hLEGts83y;9$QveD`8Rq-K}TBlCy^llEU|8qfhYUIRK4>Z=S&x^0uxwSdW zWwWTf;O%_VrGKT%pReA2zVi9bcYF=^&3Z4--qG>*ZvU~biJR-0PQQHg($??Y<%FPX zvyaPX?VFSPDi7rLQ7{?;qaiSYLg0bLTZRB{MkYCC+(j8II5sqbSV#q1fHx}}NQe;# LErIk&aQO!Sz;kUU literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/t/log_corruption4.zip b/mysql-test/suite/innodb/t/log_corruption4.zip new file mode 100644 index 0000000000000000000000000000000000000000..86002d7d42a9bc013d7881798e051dfe28e734ea GIT binary patch literal 1308 zcmWIWW@Zs#U|`^2IHw}#-e0V3w1fr7We{NC29lXc@j3bFX_+~x25+w#`Y{CxG(22r zn6cp@i?p!SOIrqB)2XUbO0!?s9n!N6DqxV7*3PaL&KA~Bc*<$h8o1#T!xPC*wP*ME zd=3Asv`AF??$@$AJ?l@OHqw2yXw59ot5a64^6xg$Pn-O+#AbE3mg&K`iue6;|8;h~ zKKFj{-IEhO>(7ev98-ey23Z1EXLx1V%$(1cks2|N8;nj7)OOxQjDbXl!T%v5*S40B=?{ PkPssfS_0{_;4%;Z+WTw1 literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/t/log_corruption4a.zip b/mysql-test/suite/innodb/t/log_corruption4a.zip new file mode 100644 index 0000000000000000000000000000000000000000..6d072f3029fece328f659bfa7b1d2fe22d00a6a0 GIT binary patch literal 1310 zcmWIWW@Zs#U|`^2IF+m6K3i|!mt`zKE`tCAH;~LsiqFYUPs_|nHF$e{vTv_r?4dbMPZ-OmYh4~NgCGU^_ zd2Zhq|NESZR}O_$ZHEMm`JUzMKa+yQ!%fHXt#pv<;ZFa5fxx?S?UEj6)?0xkQRsa8d zkbQNy!dU6_1A;RShN6pV(zXb6m;5SX(pKERuiNsbwJfd&hW4UHfcQt=kx S&B_K6Vgy1h?+ literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/t/log_corruption5.zip b/mysql-test/suite/innodb/t/log_corruption5.zip new file mode 100644 index 0000000000000000000000000000000000000000..bbf0238efc993e3eae7d692c12013d3c8978b9ea GIT binary patch literal 1308 zcmWIWW@Zs#U|`^2c(GRA-Ti$5+Y%NamqCDm8%Sm*#pmRwr)B1(8oa$~=*JW&(C~1f z;jDzioMviem#P`0v$VZLnr6SSJEUhDRKOrzon0-QEo93uSNwyB+rd-J6Vgw7H~nmM zHU4aOM_5kDwA+Q|J9O8dHd)=hDa$Q1c-bmD?Mqu`^ei)P_KXc#$@%TjuIis((l17C ztCw$o%VYUJ=>LzeKVLsAnYcSy{NAp;q3_rf=2yzZ9`Ve1SNpnV_s^d!anJg{&o3;P zdTg^*zMSyjj^m OLX1FY38c@0%Rm6UUTix6 literal 0 HcmV?d00001 diff --git a/mysql-test/suite/innodb/t/log_corruption6.zip b/mysql-test/suite/innodb/t/log_corruption6.zip new file mode 100644 index 0000000000000000000000000000000000000000..04dd687e7c9324b6bcb6288deb939163ec9d3c09 GIT binary patch literal 1311 zcmWIWW@Zs#U|`^2=&sRlSI)m5vYZ9TWe{NC29lXc@j3bFX_+~x25&DL`Y{CxG(22r zIAaa3dV;5p?i(H5B@4E0PMNx5>hfy#Z0;3@?f $SEARCH_FILE 2>&1 + +--echo # Write tmp/log_file/my.cnf + +perl; +die unless open IN, "<", "$ENV{MYSQLTEST_VARDIR}/my.cnf"; +my $found; +while () { $found=$1 if /^(lc-messages-dir=.*)/ } +close IN; + +die unless defined $found; +die unless open OUT, ">", "$ENV{bugdir}/my.cnf"; +print OUT "[mysqld] +$found +innodb_data_home_dir = $ENV{bugdir} +datadir = $ENV{bugdir} +secure_file_priv= +skip_aria +#core_file # MDEV-11689 FIXME: add this back, and remove all ,134 below +innodb_data_file_path = ibdata1:10M;ibdata2:10M:autoextend +innodb_undo_logs = 20 +innodb_undo_tablespaces = 3 +innodb_log_files_in_group = 3 +"; +close(OUT); +EOF + +--echo # Start mysqld without the possibility to create innodb_undo_tablespaces +--mkdir $bugdir/undo002 +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=\[ERROR\] InnoDB: Could not create undo tablespace '.*undo002'; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +--echo # Remove undo001,undo002,ibdata1,ibdata2,ib_logfile1,ib_logfile2,ib_logfile101 +--remove_file $bugdir/undo001 +--rmdir $bugdir/undo002 +--remove_file $bugdir/ibdata1 +--remove_file $bugdir/ibdata2 +--remove_file $bugdir/ib_logfile1 +--remove_file $bugdir/ib_logfile2 +--remove_file $bugdir/ib_logfile101 +--list_files $bugdir + +--echo # Start mysqld with non existent innodb_log_group_home_dir +--error 1,134 +--exec $MYSQLD $args --innodb_log_group_home_dir=/path/to/non-existent/ +let SEARCH_PATTERN=File .path.to.non-existent.*ib_logfile101: 'create' returned OS error \d+; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +--echo # Remove ibdata1 & ibdata2 +--remove_file $bugdir/ibdata1 +--remove_file $bugdir/ibdata2 +--list_files $bugdir + +# Innodb creates system tablespaces according to my.cnf and aborts +# complaining about mysql.* tables. This is sufficient for testing +# missing tablespaces. +--echo # Start mysqld to create tablespaces according to my.cnf +--error 2,134 +--exec $MYSQLD $args --skip-grant-tables --innodb-unknown-parameter +let SEARCH_PATTERN=unknown option '--innodb-unknown-parameter'; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +--echo # Backup tmp/logfile/* +--copy_file $bugdir/ibdata1 $bugdir/bak_ibdata1 +--copy_file $bugdir/ibdata2 $bugdir/bak_ibdata2 +--copy_file $bugdir/ib_logfile0 $bugdir/bak_ib_logfile0 +--copy_file $bugdir/ib_logfile1 $bugdir/bak_ib_logfile1 +--copy_file $bugdir/ib_logfile2 $bugdir/bak_ib_logfile2 +--copy_file $bugdir/undo001 $bugdir/bak_undo001 +--copy_file $bugdir/undo002 $bugdir/bak_undo002 +--copy_file $bugdir/undo003 $bugdir/bak_undo003 + +--echo # 1. With ibdata2, Without ibdata1 +--remove_file $bugdir/ibdata1 +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 2. With ibdata1, without ibdata2 +--remove_file $bugdir/ibdata2 +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=Tablespace size stored in header is \d+ pages, but; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 3. Without ibdata1 & ibdata2 +--remove_file $bugdir/ibdata1 +--remove_file $bugdir/ibdata2 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=undo tablespace .*undo001.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 4. Without ibdata*, ib_logfile* and with undo00* +--remove_files_wildcard $bugdir ibdata* +--remove_files_wildcard $bugdir ib_logfile* +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=undo tablespace .*undo001.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + + +--echo # 5. Without ibdata*,ib_logfile* files & Without undo002 +--remove_files_wildcard $bugdir ibdata* +--remove_files_wildcard $bugdir ib_logfile* +--remove_file $bugdir/undo002 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=undo tablespace .*undo001.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 6. Without ibdata*,ib_logfile* files & Without undo001, undo002 +# and with undo003 +--remove_files_wildcard $bugdir ibdata* +--remove_files_wildcard $bugdir ib_logfile* +--remove_file $bugdir/undo001 +--remove_file $bugdir/undo002 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=undo tablespace .*undo003.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 7. With ibdata files & Without undo002 +--remove_file $bugdir/undo002 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=Expected to open 3 undo tablespaces but was able; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=to find only 1 undo tablespaces; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 8. With ibdata files & Without undo001, undo002 +--remove_file $bugdir/undo001 +--remove_file $bugdir/undo002 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=Expected to open 3 undo tablespaces but was able; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=to find only 0 undo tablespaces; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 9. Without ibdata*, without undo*, Without ib_logfile1 and with ib_logfile2 +--remove_files_wildcard $bugdir ibdata* +--remove_files_wildcard $bugdir undo00* +--remove_file $bugdir/ib_logfile1 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=redo log file .*ib_logfile0.* exists\. Creating system tablespace with existing redo log files is not recommended\. Please delete all redo log files before creating new system tablespace\.; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +# 10. With ibdata*, without ib_logfile0 +#--remove_file $bugdir/ib_logfile0 +# The below would start the server. Since we cannot start a parallel +# server, do not test the below case +#--error 1,134 +#--exec $MYSQLD $args + +# clean up & Restore +#--source ../include/log_file_cleanup.inc + +--echo # 11. With ibdata*, without ib_logfile1 +--remove_file $bugdir/ib_logfile1 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=Only one log file found; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN=\[ERROR\] Aborting; +--source include/search_pattern_in_file.inc + +# clean up & Restore +--source ../include/log_file_cleanup.inc + +--echo # 12. With ibdata*, without ib_logfile2 +--remove_file $bugdir/ib_logfile2 +--list_files $bugdir +--error 1,134 +--exec $MYSQLD $args +let SEARCH_PATTERN=Resizing redo log from \d+\*\d+ to \d+\*\d+ pages, LSN=\d+; +--source include/search_pattern_in_file.inc + +--echo # Cleanup +# Remove ibtmp* which are re-generated after each mysqld invocation +# skip auto generated auto.cnf from list_files +--remove_files_wildcard $bugdir auto.cnf +--remove_files_wildcard $bugdir ibtmp* +--list_files $bugdir +--remove_files_wildcard $bugdir +--rmdir $bugdir diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test new file mode 100644 index 00000000000..c55005c0e58 --- /dev/null +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -0,0 +1,268 @@ +# WL#7142 InnoDB: Simplify tablespace discovery during crash recovery +# Test the detection of duplicate tablespaces. + +--source include/have_innodb.inc + +# Embedded server does not support crashing +--source include/not_embedded.inc + +SET GLOBAL innodb_file_per_table=ON; + +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; + +--source include/no_checkpoint_start.inc +CREATE TABLE t3(a INT PRIMARY KEY) ENGINE=InnoDB; + +BEGIN; +INSERT INTO t3 VALUES (33101),(347); +INSERT INTO t1 VALUES (42),(9),(101); +RENAME TABLE t1 TO t2; +UPDATE t2 SET a=347 where a=42; +COMMIT; + +--let CLEANUP_IF_CHECKPOINT=DROP TABLE t2,t3; +--source include/no_checkpoint_end.inc + +--echo # Fault 0 (no real fault): Orphan file with duplicate space_id. +--copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t0.ibd + +--echo # Fault 1: Two dirty files with the same space_id. +--copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd + +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_RANGE= -50000; +let SEARCH_ABORT= NOT FOUND; +let $check_no_innodb=SELECT * FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); + +# This could fail to refuse InnoDB startup, in case there was a log +# checkpoint after the INSERT. That is what we checked above. +--source include/start_mysqld.inc +eval $check_no_innodb; +let SEARCH_PATTERN= InnoDB: Ignoring data file '.*t2.ibd' with space ID \d+. Another data file called .*t1.ibd exists with the same space ID; +--source include/search_pattern_in_file.inc + +--source include/shutdown_mysqld.inc + +--remove_file $MYSQLD_DATADIR/test/t1.ibd +--remove_file $SEARCH_FILE + +# This could fail to refuse InnoDB startup, in case there was a log +# checkpoint after the CREATE TABLE t3. That is what we checked above. +--echo # Fault 2: Wrong space_id in a dirty file, and a missing file. +--move_file $MYSQLD_DATADIR/test/t3.ibd $MYSQLD_DATADIR/test/t1.ibd + +--source include/start_mysqld.inc +eval $check_no_innodb; + +let SEARCH_PATTERN= InnoDB: Ignoring data file '.*t1.ibd' with space ID; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at.*t3.ibd; +--source include/search_pattern_in_file.inc + +--source include/shutdown_mysqld.inc + +--move_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t3.ibd + +--echo # Fault 3: Wrong space_id in a dirty file, and no missing file. +# Swap t2.ibd and t3.ibd. +--move_file $MYSQLD_DATADIR/test/t3.ibd $MYSQLD_DATADIR/test/t.ibd +--move_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t3.ibd +--move_file $MYSQLD_DATADIR/test/t.ibd $MYSQLD_DATADIR/test/t2.ibd + +--source include/start_mysqld.inc +eval $check_no_innodb; + +let SEARCH_PATTERN= InnoDB: Ignoring data file '.*t[23].ibd' with space ID; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at .*t1.ibd; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at .*t3.ibd; +--source include/search_pattern_in_file.inc +let SEARCH_PATTERN= InnoDB: Set innodb_force_recovery=1 to ignore this and to permanently lose all changes to the tablespace; +--source include/search_pattern_in_file.inc + +--source include/shutdown_mysqld.inc + +# Swap back t3.ibd, but hide t2.ibd (which the redo log also knows as t1.ibd). +--move_file $MYSQLD_DATADIR/test/t3.ibd $MYSQLD_DATADIR/test/t.ibd +--move_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t3.ibd + +--echo # Fault 4: Missing data file + +--source include/start_mysqld.inc +eval $check_no_innodb; + +let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at .*t[12].ibd. +.*InnoDB: Set innodb_force_recovery=1 to ignore this and to permanently lose all changes to the tablespace; +--source include/search_pattern_in_file.inc + +--source include/shutdown_mysqld.inc + +--echo # Fault 5: Wrong type of data file + +# TODO: Test the following as well once +# Bug#18131883 IMPROVE INNODB ERROR MESSAGES REGARDING FILES +# has been fixed: +# A file containing 16384 zero bytes. +# --mkdir $MYSQLD_DATADIR/test/t2.ibd + +# Create a short file. +--exec echo "" > $MYSQLD_DATADIR/test/t2.ibd + +--source include/start_mysqld.inc +eval $check_no_innodb; + +let SEARCH_PATTERN= \[ERROR\] InnoDB: Datafile .*t2.*\. Cannot determine the space ID from the first 64 pages; +--source include/search_pattern_in_file.inc + +--source include/shutdown_mysqld.inc + +# Restore t2.ibd +--remove_file $MYSQLD_DATADIR/test/t2.ibd +--move_file $MYSQLD_DATADIR/test/t.ibd $MYSQLD_DATADIR/test/t2.ibd + +--source include/start_mysqld.inc + +SELECT * FROM t2; +SELECT * FROM t3; +SHOW TABLES; +DROP TABLE t2,t3; + +--error ER_TABLESPACE_EXISTS +CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB; + +# Remove the orphan file from fault 0. +--remove_file $MYSQLD_DATADIR/test/t0.ibd + +CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB; +DROP TABLE t0; + +--disable_query_log +# The following are for the orphan file t0.ibd: +call mtr.add_suppression("InnoDB: Operating system error number [0-9]* in a file operation"); +call mtr.add_suppression("InnoDB: Error number [0-9]* means 'File exists'"); +call mtr.add_suppression("InnoDB: Cannot create file '.*t0.ibd'"); +call mtr.add_suppression("InnoDB: The file '.*t0\.ibd' already exists"); +# The following are for aborted startup without --innodb-force-recovery: +call mtr.add_suppression("InnoDB: Tablespace .* was not found at .*test"); +call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore this and to permanently lose all changes to the tablespace"); +call mtr.add_suppression("InnoDB: Cannot read first page of '.*test.[tu]2.ibd' I/O error"); +call mtr.add_suppression("InnoDB: Cannot read first page in datafile: .*test.*ibd"); +call mtr.add_suppression("InnoDB: Datafile './test/.*ibd' is corrupted"); +call mtr.add_suppression("InnoDB: Cannot replay file rename. Remove either file and try again"); +call mtr.add_suppression("InnoDB: Cannot rename.*because the target file exists"); +call mtr.add_suppression("InnoDB: Found corrupted log"); +# The following are for the --innodb-force-recovery=1 with broken u* tables: +call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd"); +call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified"); +call mtr.add_suppression("InnoDB: .*you must create directories"); +call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: '.*u[1-5]\.ibd'"); +call mtr.add_suppression("InnoDB: Could not find a valid tablespace file for `test/u[1-5]`"); +call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`u[1-3]` because it could not be opened."); +call mtr.add_suppression("InnoDB: Failed to find tablespace for table .* in the cache. Attempting to load the tablespace with space id"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted"); +call mtr.add_suppression("Plugin 'InnoDB' \(init function returned error\|registration as a STORAGE ENGINE failed\)"); +FLUSH TABLES; +--enable_query_log + +--source include/no_checkpoint_start.inc + +CREATE TABLE u1(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE u2(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE u3(a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE u4(a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO u4 VALUES(1); +RENAME TABLE u4 TO u5; +RENAME TABLE u5 TO u6; +INSERT INTO u6 VALUES(2); + +--let CLEANUP_IF_CHECKPOINT=DROP TABLE u1,u2,u3,u6; +--source include/no_checkpoint_end.inc + +--echo # Fault 6: All-zero data file and innodb_force_recovery + +--remove_file $MYSQLD_DATADIR/test/u1.ibd +--remove_file $MYSQLD_DATADIR/test/u2.ibd +--remove_file $MYSQLD_DATADIR/test/u3.ibd + +# InnoDB: Header page consists of zero bytes +perl; +die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/test/u1.ibd"); +print FILE "\0" x 16384; +close(FILE); +EOF + +--exec echo "" > $MYSQLD_DATADIR/test/u2.ibd + +# TODO: Test with this, once +# Bug#18131883 IMPROVE INNODB ERROR MESSAGES REGARDING FILES +# has been fixed: +#--mkdir $MYSQLD_DATADIR/test/u3.ibd + +--copy_file $MYSQLD_DATADIR/test/u6.ibd $MYSQLD_DATADIR/test/u4.ibd + +--let $restart_parameters= --innodb-force-recovery=1 +--source include/start_mysqld.inc +eval $check_no_innodb; + +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN= \[ERROR\] InnoDB: Datafile .*u1.*\. Cannot determine the space ID from the first 64 pages; +--source include/search_pattern_in_file.inc + +# TODO: These errors should state the file name (u2.ibd) and be ignored +# in innodb-force-recovery mode once +# Bug#18131883 IMPROVE INNODB ERROR MESSAGES REGARDING FILES +# has been fixed: +let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot read first page of .*u2.ibd.*; +--source include/search_pattern_in_file.inc + +--source include/shutdown_mysqld.inc + +# Allow --innodb-force-recovery to start despite the broken file. +# TODO: Remove this workaround, and make --innodb-force-recovery=1 +# ignore the broken file. +--remove_file $MYSQLD_DATADIR/test/u2.ibd + +--echo # Fault 7: Missing or wrong data file and innodb_force_recovery + +--source include/start_mysqld.inc +eval $check_no_innodb; + +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot rename '.*u5.ibd' to '.*u6.ibd' for space ID \d+ because the target file exists; +--source include/search_pattern_in_file.inc + +--remove_file $MYSQLD_DATADIR/test/u6.ibd + +--source include/restart_mysqld.inc + +let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; +--source include/search_pattern_in_file.inc + +let SEARCH_PATTERN= \[Warning\] InnoDB: Tablespace \d+ was not found at .*u[1-5].ibd, and innodb_force_recovery was set. All redo log for this tablespace will be ignored!; +--source include/search_pattern_in_file.inc + +--let $restart_parameters= +--source include/restart_mysqld.inc + +DROP TABLE u1,u2,u3,u6; + +--remove_file $MYSQLD_DATADIR/test/u1.ibd +--echo # List of files: +--list_files $MYSQLD_DATADIR/test + +SHOW TABLES; diff --git a/mysql-test/suite/innodb/t/log_file_name_debug.test b/mysql-test/suite/innodb/t/log_file_name_debug.test new file mode 100644 index 00000000000..41d7ec2e53e --- /dev/null +++ b/mysql-test/suite/innodb/t/log_file_name_debug.test @@ -0,0 +1,31 @@ +--source include/have_innodb.inc +# Embedded server does not support restarting +--source include/not_embedded.inc +--source include/have_debug.inc + +--echo # +--echo # Bug#19685095 DO NOT CARE ABOUT UNRESOLVED MLOG_FILE_NAME +--echo # IF THERE ARE NO OPERATIONS TO APPLY +--echo # + +SET GLOBAL DEBUG_DBUG='+d,fil_names_write_bogus'; +--disable_query_log +FLUSH TABLES; +--enable_query_log + +--source include/no_checkpoint_start.inc + +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; + +--let CLEANUP_IF_CHECKPOINT=DROP TABLE t1; +--source include/no_checkpoint_end.inc + +--source include/start_mysqld.inc + +DROP TABLE t1; + +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let SEARCH_PATTERN = InnoDB: Tablespace 4294967280 was not found at .*, but there were no modifications either +--let SEARCH_ABORT = NOT FOUND +--let SEARCH_RANGE = -50000 +--source include/search_pattern_in_file.inc diff --git a/mysql-test/suite/innodb/t/log_file_size_checkpoint.test b/mysql-test/suite/innodb/t/log_file_size_checkpoint.test new file mode 100644 index 00000000000..26e0bdf5e2c --- /dev/null +++ b/mysql-test/suite/innodb/t/log_file_size_checkpoint.test @@ -0,0 +1,32 @@ +--source include/have_innodb.inc +--source include/not_embedded.inc +--source include/no_valgrind_without_big.inc + +CREATE DATABASE logtest; +USE logtest; +let $n=250; +let $t=veryLongTableNameToCreateMLOG_FILE_NAMErecords; + +--disable_query_log +call mtr.add_suppression("InnoDB: Resizing redo log"); +call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files"); +call mtr.add_suppression("InnoDB: New log files created"); +FLUSH TABLES; + +let $i=$n; +while ($i) +{ +--eval CREATE TABLE $t$i(a INT PRIMARY KEY) ENGINE=InnoDB; +dec $i; +} + +# If we set above n to 500, this test case could fail easily, because +# the inndob buffer pool is too small, some of which would be occupied +# by the recv*. With n=250, this test case could sporadically fail too. +# So we have to set buffer pool size to 50M which should be enough for this +# test case. Once we fix the bug#22179133 and bug#22186325, we should use +# the default innodb buffer pool(or the smaller one). +let $restart_parameters = --innodb-log-files-in-group=2 --innodb-log-file-size=4M --innodb-buffer-pool-size=50M; +--source include/kill_and_restart_mysqld.inc + +DROP DATABASE logtest; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5ed02a92e0e..b869f2d1307 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4462,12 +4462,6 @@ innobase_change_buffering_inited_ok: } */ - if (!srv_read_only_mode) { - mysql_thread_create(thd_destructor_thread_key, - &thd_destructor_thread, - NULL, thd_destructor_proxy, NULL); - } - /* Since we in this module access directly the fields of a trx struct, and due to different headers and flags it might happen that ib_mutex_t has a different size in this module and in InnoDB @@ -4489,6 +4483,10 @@ innobase_change_buffering_inited_ok: if (err != DB_SUCCESS) { DBUG_RETURN(innobase_init_abort()); + } else if (!srv_read_only_mode) { + mysql_thread_create(thd_destructor_thread_key, + &thd_destructor_thread, + NULL, thd_destructor_proxy, NULL); } /* Adjust the innodb_undo_logs config object */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 3403534d36b..587ffc15adb 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1299,6 +1299,7 @@ srv_shutdown_all_bg_threads() @param[in] line Line number @param[in] err Reason for aborting InnoDB startup @return DB_SUCCESS or error code. */ +MY_ATTRIBUTE((warn_unused_result, nonnull)) static dberr_t srv_init_abort_low( @@ -2411,6 +2412,7 @@ files_checked: if (err != DB_SUCCESS) { return(srv_init_abort(err)); } + /* Create the doublewrite buffer to a new tablespace */ if (buf_dblwr == NULL && !buf_dblwr_create()) { return(srv_init_abort(DB_ERROR)); From 30ba31005793cdd9b596aabaf95110bb291dddcf Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 27 Jan 2017 18:05:11 +0100 Subject: [PATCH 139/167] cleanup: thd_destructor_proxy 1. wait for thd_destructor_proxy thread to start after creating it. this ensures that the thread is ready to receive a shutdown signal whenever we want to send it. 2. join it at shutdown, this guarantees that no innodb THD will exist after innobase_end(). this fixes crashes and memory leaks in main.mysqld_option_err (were innodb was started and then immediately shut down). --- storage/innobase/handler/ha_innodb.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index b869f2d1307..9707e24390d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -313,26 +313,28 @@ This THDs must be destroyed rather early in the server shutdown sequence. This service thread creates a THD and idly waits for it to get a signal to die. Then it notifies all purge workers to shutdown. */ -st_my_thread_var *thd_destructor_myvar= NULL; -mysql_cond_t thd_destructor_cond; -pthread_t thd_destructor_thread; +static volatile st_my_thread_var *thd_destructor_myvar= NULL; +static pthread_t thd_destructor_thread; pthread_handler_t thd_destructor_proxy(void *) { mysql_mutex_t thd_destructor_mutex; + mysql_cond_t thd_destructor_cond; my_thread_init(); mysql_mutex_init(PSI_NOT_INSTRUMENTED, &thd_destructor_mutex, 0); mysql_cond_init(PSI_NOT_INSTRUMENTED, &thd_destructor_cond, 0); - thd_destructor_myvar = _my_thread_var(); + st_my_thread_var *myvar= _my_thread_var(); THD *thd= create_thd(); thd_proc_info(thd, "InnoDB background thread"); + myvar->current_mutex = &thd_destructor_mutex; + myvar->current_cond = &thd_destructor_cond; + mysql_mutex_lock(&thd_destructor_mutex); - thd_destructor_myvar->current_mutex = &thd_destructor_mutex; - thd_destructor_myvar->current_cond = &thd_destructor_cond; + thd_destructor_myvar = myvar; /* wait until the server wakes the THD to abort and die */ while (!thd_destructor_myvar->abort) mysql_cond_wait(&thd_destructor_cond, &thd_destructor_mutex); @@ -4487,6 +4489,8 @@ innobase_change_buffering_inited_ok: mysql_thread_create(thd_destructor_thread_key, &thd_destructor_thread, NULL, thd_destructor_proxy, NULL); + while (!thd_destructor_myvar) + os_thread_sleep(20); } /* Adjust the innodb_undo_logs config object */ @@ -4603,6 +4607,7 @@ innobase_end( } innobase_space_shutdown(); + pthread_join(thd_destructor_thread, NULL); mysql_mutex_destroy(&innobase_share_mutex); mysql_mutex_destroy(&commit_cond_m); From 64b5e94236e7c4246863fc70b91c346ba7b66b8b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 27 Jan 2017 14:26:09 +0100 Subject: [PATCH 140/167] mysqlbinlog memory leaks that failed main.mysqlbinlog --- client/mysqlbinlog.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 39a879bc619..e2b121c27a7 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -2877,9 +2877,6 @@ int main(int argc, char** argv) DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); - (void) my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024, - MYF(0)); - my_init_time(); // for time functions tzset(); // set tzname @@ -2917,6 +2914,10 @@ int main(int argc, char** argv) my_set_max_open_files(open_files_limit); + if (opt_flashback) + my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024, + MYF(0)); + if (opt_stop_never) to_last_remote_log= TRUE; @@ -3029,8 +3030,8 @@ int main(int argc, char** argv) my_free(event_str->str); } fprintf(result_file, "COMMIT\n/*!*/;\n"); + delete_dynamic(&binlog_events); } - delete_dynamic(&binlog_events); /* Set delimiter back to semicolon */ if (!stop_event_string.is_empty()) From abfcdb8fbc4dec1ef9e6ea8fc9961344186b0209 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 28 Jan 2017 14:52:19 -0800 Subject: [PATCH 141/167] Fixed bug mdev-10773. The temporary tables created for recursive table references should be closed in close_thread_tables(), because they might be used in the statements like ANALYZE WITH r AS (...) SELECT * from r where r is defined through recursion. --- mysql-test/r/cte_recursive.result | 65 +++++++++++++++++++++++++++++++ mysql-test/t/cte_recursive.test | 12 ++++++ sql/sql_base.cc | 17 ++++++++ sql/sql_class.h | 6 +++ sql/sql_union.cc | 9 ++++- 5 files changed, 108 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index d5476aec1c4..20ca5c8f8cb 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -2343,3 +2343,68 @@ select id + 1, uuid() from data_generator where id < 150000 select * from data_generator ) as a; drop table t1; +# +# MDEV-10773: ANALYZE for query with recursive CTE +# +analyze format=json +with recursive src(counter) as +(select 1 +union +select counter+1 from src where counter<10 +) select * from src; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "", + "access_type": "ALL", + "r_loops": 1, + "rows": 2, + "r_rows": 10, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "materialized": { + "query_block": { + "recursive_union": { + "table_name": "", + "access_type": "ALL", + "r_loops": 0, + "r_rows": null, + "query_specifications": [ + { + "query_block": { + "select_id": 2, + "table": { + "message": "No tables used" + } + } + }, + { + "query_block": { + "select_id": 3, + "r_loops": 10, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "", + "access_type": "ALL", + "r_loops": 10, + "rows": 2, + "r_rows": 1, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 90, + "attached_condition": "src.counter < 10" + } + } + } + ] + } + } + } + } + } +} diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index ea0f73be259..332996d4921 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -1505,3 +1505,15 @@ select id, test_data ) as a; drop table t1; + +--echo # +--echo # MDEV-10773: ANALYZE for query with recursive CTE +--echo # + +--replace_regex /"r_total_time_ms": [0-9]*[.]?[0-9]*/"r_total_time_ms": "REPLACED"/ +analyze format=json +with recursive src(counter) as +(select 1 + union + select counter+1 from src where counter<10 +) select * from src; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ac4b8a45107..3758b3ba710 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -769,6 +769,23 @@ void close_thread_tables(THD *thd) thd->derived_tables= 0; } + if (thd->rec_tables) + { + TABLE *next; + /* + Close all temporary tables created for recursive table references. + This action was postponed because the table could be used in the + statements like ANALYZE WITH r AS (...) SELECT * from r + where r is defined through recursion. + */ + for (table= thd->rec_tables ; table ; table= next) + { + next= table->next; + free_tmp_table(thd, table); + } + thd->rec_tables= 0; + } + /* Mark all temporary tables used by this statement as free for reuse. */ diff --git a/sql/sql_class.h b/sql/sql_class.h index b6dafd939bc..295474d0d62 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1381,6 +1381,11 @@ public: */ TABLE *derived_tables; + /* + Temporary tables created for recursive table references. + */ + TABLE *rec_tables; + /* During a MySQL session, one can lock tables in two modes: automatic or manual. In automatic mode all necessary tables are locked just before @@ -1461,6 +1466,7 @@ public: open_tables= 0; temporary_tables= 0; derived_tables= 0; + rec_tables= 0; extra_lock= 0; lock= 0; locked_tables_mode= LTM_NONE; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index b30b5528741..71d0e331101 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -283,7 +283,14 @@ void select_union_recursive::cleanup() tab->file->extra(HA_EXTRA_RESET_STATE); tab->file->ha_delete_all_rows(); } - free_tmp_table(thd, tab); + /* + The table will be closed later in close_thread_tables(), + because it might be used in the statements like + ANALYZE WITH r AS (...) SELECT * from r + where r is defined through recursion. + */ + tab->next= thd->rec_tables; + thd->rec_tables= tab; } } From a7d6271cbf63d129045ba4c97333f975bf88e050 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 29 Jan 2017 13:49:23 +0100 Subject: [PATCH 142/167] skip innodb.log_corruption test if no unzip executable is found also move *.zip files from t/ to std_data/ --- mysql-test/include/have_unzip.inc | 3 +++ mysql-test/suite.pm | 2 ++ .../innodb/{t => std_data}/log_corruption.zip | Bin .../{t => std_data}/log_corruption0.zip | Bin .../{t => std_data}/log_corruption1.zip | Bin .../{t => std_data}/log_corruption2.zip | Bin .../{t => std_data}/log_corruption3.zip | Bin .../{t => std_data}/log_corruption4.zip | Bin .../{t => std_data}/log_corruption4a.zip | Bin .../{t => std_data}/log_corruption5.zip | Bin .../{t => std_data}/log_corruption6.zip | Bin mysql-test/suite/innodb/t/log_corruption.test | 19 +++++++++--------- 12 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 mysql-test/include/have_unzip.inc rename mysql-test/suite/innodb/{t => std_data}/log_corruption.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption0.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption1.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption2.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption3.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption4.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption4a.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption5.zip (100%) rename mysql-test/suite/innodb/{t => std_data}/log_corruption6.zip (100%) diff --git a/mysql-test/include/have_unzip.inc b/mysql-test/include/have_unzip.inc new file mode 100644 index 00000000000..a3308524679 --- /dev/null +++ b/mysql-test/include/have_unzip.inc @@ -0,0 +1,3 @@ +# +# empty. the real check happens in suite.pm +# diff --git a/mysql-test/suite.pm b/mysql-test/suite.pm index f501e610e53..134a0d6d438 100644 --- a/mysql-test/suite.pm +++ b/mysql-test/suite.pm @@ -68,6 +68,8 @@ sub skip_combinations { unless $::mysqld_variables{'version-ssl-library'} =~ /OpenSSL (\S+)/ and $1 ge "1.0.1d"; + $skip{'include/have_unzip.inc'} = 'no unzip executable' unless `unzip`; + %skip; } diff --git a/mysql-test/suite/innodb/t/log_corruption.zip b/mysql-test/suite/innodb/std_data/log_corruption.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption.zip rename to mysql-test/suite/innodb/std_data/log_corruption.zip diff --git a/mysql-test/suite/innodb/t/log_corruption0.zip b/mysql-test/suite/innodb/std_data/log_corruption0.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption0.zip rename to mysql-test/suite/innodb/std_data/log_corruption0.zip diff --git a/mysql-test/suite/innodb/t/log_corruption1.zip b/mysql-test/suite/innodb/std_data/log_corruption1.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption1.zip rename to mysql-test/suite/innodb/std_data/log_corruption1.zip diff --git a/mysql-test/suite/innodb/t/log_corruption2.zip b/mysql-test/suite/innodb/std_data/log_corruption2.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption2.zip rename to mysql-test/suite/innodb/std_data/log_corruption2.zip diff --git a/mysql-test/suite/innodb/t/log_corruption3.zip b/mysql-test/suite/innodb/std_data/log_corruption3.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption3.zip rename to mysql-test/suite/innodb/std_data/log_corruption3.zip diff --git a/mysql-test/suite/innodb/t/log_corruption4.zip b/mysql-test/suite/innodb/std_data/log_corruption4.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption4.zip rename to mysql-test/suite/innodb/std_data/log_corruption4.zip diff --git a/mysql-test/suite/innodb/t/log_corruption4a.zip b/mysql-test/suite/innodb/std_data/log_corruption4a.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption4a.zip rename to mysql-test/suite/innodb/std_data/log_corruption4a.zip diff --git a/mysql-test/suite/innodb/t/log_corruption5.zip b/mysql-test/suite/innodb/std_data/log_corruption5.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption5.zip rename to mysql-test/suite/innodb/std_data/log_corruption5.zip diff --git a/mysql-test/suite/innodb/t/log_corruption6.zip b/mysql-test/suite/innodb/std_data/log_corruption6.zip similarity index 100% rename from mysql-test/suite/innodb/t/log_corruption6.zip rename to mysql-test/suite/innodb/std_data/log_corruption6.zip diff --git a/mysql-test/suite/innodb/t/log_corruption.test b/mysql-test/suite/innodb/t/log_corruption.test index 725c8db6360..664894f2c41 100644 --- a/mysql-test/suite/innodb/t/log_corruption.test +++ b/mysql-test/suite/innodb/t/log_corruption.test @@ -1,3 +1,4 @@ +--source include/have_unzip.inc --source include/have_innodb.inc --source include/have_innodb_16k.inc @@ -27,7 +28,7 @@ core_file EOF --echo # redo log from before MySQL 5.7.9 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption.zip -d $bugdir > $SEARCH_FILE --error 1 --exec $MYSQLD $args let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported. This redo log was created before MySQL 5\\.7\\.9\\.; @@ -43,7 +44,7 @@ let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported. This redo log --echo # redo log from before MySQL 5.7.9, with corrupted log block --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption0.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption0.zip -d $bugdir > $SEARCH_FILE --error 1 --exec $MYSQLD $args let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported. This redo log was created before MySQL 5\\.7\\.9, and it appears corrupted; @@ -51,7 +52,7 @@ let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported. This redo log --echo # redo log from "after" MySQL 5.7.9, but with invalid header checksum --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption1.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption1.zip -d $bugdir > $SEARCH_FILE --error 1 --exec $MYSQLD $args let SEARCH_PATTERN=InnoDB: Invalid redo log header checksum; @@ -59,7 +60,7 @@ let SEARCH_PATTERN=InnoDB: Invalid redo log header checksum; --echo # distant future redo log format, with valid header checksum --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption2.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption2.zip -d $bugdir > $SEARCH_FILE --error 1 --exec $MYSQLD $args let SEARCH_PATTERN=InnoDB: Unsupported redo log format. The redo log was created with malicious intentions, or perhaps\. Please follow the instructions at http://dev.mysql.com/doc/refman/5.7/en/upgrading-downgrading.html; @@ -67,7 +68,7 @@ let SEARCH_PATTERN=InnoDB: Unsupported redo log format. The redo log was created --echo # valid header, but old-format checkpoint blocks --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption3.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption3.zip -d $bugdir > $SEARCH_FILE --error 1 --exec $MYSQLD $args let SEARCH_PATTERN=InnoDB: No valid checkpoint found .corrupted redo log; @@ -75,7 +76,7 @@ let SEARCH_PATTERN=InnoDB: No valid checkpoint found .corrupted redo log; --echo # valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2, invalid block checksum --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption4.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption4.zip -d $bugdir > $SEARCH_FILE # Anything below innodb_force_recovery=6 must find a valid redo log. # Missing tablespace files are tolerated already with innodb_force_recovery=1. --error 1 @@ -94,7 +95,7 @@ let SEARCH_PATTERN=InnoDB: Cannot create sys_virtual system tables. running in r --echo # valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2, invalid block number --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption4a.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption4a.zip -d $bugdir > $SEARCH_FILE # Anything below innodb_force_recovery=6 must find a valid redo log. # Missing tablespace files are tolerated already with innodb_force_recovery=1. --error 1 @@ -112,7 +113,7 @@ let SEARCH_PATTERN=InnoDB: Cannot create sys_virtual system tables. running in r --echo # Test a corrupted MLOG_FILE_NAME record. --echo # valid header, valid checkpoint 1, all-zero (invalid) checkpoint 2 --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption5.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption5.zip -d $bugdir > $SEARCH_FILE --error 1 --exec $MYSQLD $args let SEARCH_PATTERN=InnoDB: Log scan progressed past the checkpoint lsn 1213964; @@ -129,7 +130,7 @@ let SEARCH_PATTERN=InnoDB: Set innodb_force_recovery to ignore this error; --echo # Test a corrupted MLOG_FILE_NAME record. --echo # valid header, invalid checkpoint 1, valid checkpoint 2 --remove_file $bugdir/ib_logfile0 ---exec unzip $MYSQL_TEST_DIR/suite/innodb/t/log_corruption6.zip -d $bugdir > $SEARCH_FILE +--exec unzip $MTR_SUITE_DIR/std_data/log_corruption6.zip -d $bugdir > $SEARCH_FILE --error 1 --exec $MYSQLD $args let SEARCH_PATTERN=InnoDB: ############### CORRUPT LOG RECORD FOUND ##################; From 78712eb52fb78aab1e41241063c09814da366b1f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 3 Jan 2017 12:23:46 +0100 Subject: [PATCH 143/167] MDEV-11708 cmake -DWITH_ASAN no longer works fix the check (must be have_ not HAVE_) also remove -O1 and -Wno-error, they aren't not needed for asan --- CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f553bad5b4..be86adbf67b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,18 +183,18 @@ INCLUDE(check_compiler_flag) OPTION(WITH_ASAN "Enable address sanitizer" OFF) IF (WITH_ASAN) # gcc 4.8.1 and new versions of clang - MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=address -O1 -Wno-error -fPIC" + MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=address -fPIC" DEBUG RELWITHDEBINFO) - SET(HAVE_C_FSANITIZE ${HAVE_C__fsanitize_address__O1__Wno_error__fPIC}) - SET(HAVE_CXX_FSANITIZE ${HAVE_CXX__fsanitize_address__O1__Wno_error__fPIC}) + SET(HAVE_C_FSANITIZE ${have_C__fsanitize_address__fPIC}) + SET(HAVE_CXX_FSANITIZE ${have_CXX__fsanitize_address__fPIC}) IF(HAVE_C_FSANITIZE AND HAVE_CXX_FSANITIZE) SET(WITH_ASAN_OK 1) ELSE() # older versions of clang - MY_CHECK_AND_SET_COMPILER_FLAG("-faddress-sanitizer -O1 -fPIC" + MY_CHECK_AND_SET_COMPILER_FLAG("-faddress-sanitizer -fPIC" DEBUG RELWITHDEBINFO) - SET(HAVE_C_FADDRESS ${HAVE_C__faddress_sanitizer__O1__fPIC}) - SET(HAVE_CXX_FADDRESS ${HAVE_CXX__faddress_sanitizer__O1__fPIC}) + SET(HAVE_C_FADDRESS ${have_C__faddress_sanitizer__fPIC}) + SET(HAVE_CXX_FADDRESS ${have_CXX__faddress_sanitizer__fPIC}) IF(HAVE_C_FADDRESS AND HAVE_CXX_FADDRESS) SET(WITH_ASAN_OK 1) ENDIF() From 3d12587ca4f6aa3a91b770f652fe8ca6b70c77a1 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 24 Jan 2017 15:14:13 +0100 Subject: [PATCH 144/167] MDEV-11611 fix Ninja build ninja doesn't like when a dummy target name matches a generated file name --- dbug/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dbug/CMakeLists.txt b/dbug/CMakeLists.txt index 014efdeb9a3..84d6f1ba723 100644 --- a/dbug/CMakeLists.txt +++ b/dbug/CMakeLists.txt @@ -58,13 +58,13 @@ IF(NOT WIN32 AND NOT CMAKE_GENERATOR MATCHES Xcode) ADD_CUSTOM_COMMAND(OUTPUT user.ps DEPENDS user.r ${OUTPUT_INC} ${SOURCE_INC} COMMAND ${GROFF} -mm ${CMAKE_CURRENT_SOURCE_DIR}/user.r > user.ps || touch user.ps) - ADD_CUSTOM_TARGET(user.ps ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/user.ps) + ADD_CUSTOM_TARGET(user_ps ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/user.ps) ENDIF(GROFF) IF(NROFF) ADD_CUSTOM_COMMAND(OUTPUT user.t DEPENDS user.r ${OUTPUT_INC} ${SOURCE_INC} COMMAND ${NROFF} -mm ${CMAKE_CURRENT_SOURCE_DIR}/user.r > user.t || touch user.t) - ADD_CUSTOM_TARGET(user.t ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/user.t) + ADD_CUSTOM_TARGET(user_t ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/user.t) ENDIF(NROFF) ENDIF() From 9189284ba303cefc025b8e303619fcce2e49c6b0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 29 Jan 2017 14:12:08 +0100 Subject: [PATCH 145/167] remove a race-condition prone assertion on shutdown it might happen that 1. the server starts killing THDs 2. it sets thd->killed in srv_purge_coordinator 3. srv_purge_coordinator notices that and tells srv_workers to exit 4. srv_worker will notice that and will start exiting, ... assert here ... 5. server sets thd->killed in worker threads that is, it might happen that the assert is tested before srv_worker's THD got the kill signal. this fixes various random crashes (on this assertion) on shutdown in tests --- storage/innobase/srv/srv0srv.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index bd4dd1c80af..56fc8524945 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2720,7 +2720,6 @@ DECLARE_THREAD(srv_worker_thread)( ut_a(!purge_sys->running); ut_a(purge_sys->state == PURGE_STATE_EXIT); - ut_a(srv_shutdown_state > SRV_SHUTDOWN_NONE || thd_kill_level(thd)); rw_lock_x_unlock(&purge_sys->latch); From 2a4881800c6fa78a810d29ff2048956175fd0f6f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 30 Jan 2017 01:15:30 +0100 Subject: [PATCH 146/167] InnoDB: don't pthread_join() a thread that wasn't created this fixes the crash in innodb.101_compatibility test --- storage/innobase/handler/ha_innodb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9707e24390d..fd9702c727e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4607,7 +4607,9 @@ innobase_end( } innobase_space_shutdown(); - pthread_join(thd_destructor_thread, NULL); + if (!srv_read_only_mode) { + pthread_join(thd_destructor_thread, NULL); + } mysql_mutex_destroy(&innobase_share_mutex); mysql_mutex_destroy(&commit_cond_m); From 8ab806d2f16e1b1ea146fac59b8b7db5ecdddc34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 30 Jan 2017 11:13:10 +0200 Subject: [PATCH 147/167] Do not remove the master error log file. --- mysql-test/suite/innodb/t/log_file_name.test | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index c55005c0e58..4137f738898 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -46,7 +46,6 @@ let SEARCH_PATTERN= InnoDB: Ignoring data file '.*t2.ibd' with space ID \d+. Ano --source include/shutdown_mysqld.inc --remove_file $MYSQLD_DATADIR/test/t1.ibd ---remove_file $SEARCH_FILE # This could fail to refuse InnoDB startup, in case there was a log # checkpoint after the CREATE TABLE t3. That is what we checked above. From 31a9b3f4c8d8b7d871d6b5625e655433d99d7a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 30 Jan 2017 14:10:17 +0200 Subject: [PATCH 148/167] Fix a suppression that did not work on Windows. --- mysql-test/suite/innodb/t/log_file_name.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index 4137f738898..5c063ab124f 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -151,7 +151,7 @@ call mtr.add_suppression("InnoDB: Tablespace .* was not found at .*test"); call mtr.add_suppression("InnoDB: Set innodb_force_recovery=1 to ignore this and to permanently lose all changes to the tablespace"); call mtr.add_suppression("InnoDB: Cannot read first page of '.*test.[tu]2.ibd' I/O error"); call mtr.add_suppression("InnoDB: Cannot read first page in datafile: .*test.*ibd"); -call mtr.add_suppression("InnoDB: Datafile './test/.*ibd' is corrupted"); +call mtr.add_suppression("InnoDB: Datafile '.*test.*ibd' is corrupted"); call mtr.add_suppression("InnoDB: Cannot replay file rename. Remove either file and try again"); call mtr.add_suppression("InnoDB: Cannot rename.*because the target file exists"); call mtr.add_suppression("InnoDB: Found corrupted log"); From 9f918b9cf48989a9c1fedbd3fd8849d4d6892690 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 30 Jan 2017 10:39:35 +0100 Subject: [PATCH 149/167] take into account scientific notation of floats in regex_replace this fixes occasional main.cte_recursive failures --- mysql-test/t/cte_recursive.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index 332996d4921..aacafcb73ec 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -1510,7 +1510,7 @@ drop table t1; --echo # MDEV-10773: ANALYZE for query with recursive CTE --echo # ---replace_regex /"r_total_time_ms": [0-9]*[.]?[0-9]*/"r_total_time_ms": "REPLACED"/ +--replace_regex /"r_total_time_ms": [0-9]*[.]?[0-9]*(e[-+]?[0-9]+)?/"r_total_time_ms": "REPLACED"/ analyze format=json with recursive src(counter) as (select 1 From 1293e5e59b6b412156ef8a78f762c0b099a10b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 30 Jan 2017 17:00:51 +0200 Subject: [PATCH 150/167] Rewrite the innodb.log_file_size test with DBUG_EXECUTE_IF. Remove the debug parameter innodb_force_recovery_crash that was introduced into MySQL 5.6 by me in WL#6494 which allowed InnoDB to resize the redo log on startup. Let innodb.log_file_size actually start up the server, but ensure that the InnoDB storage engine refuses to start up in each of the scenarios. --- .../suite/innodb/r/log_file_size.result | 41 ++++- mysql-test/suite/innodb/t/log_file_size.test | 157 +++++++++++------- .../innodb_force_recovery_crash_basic.result | 33 ---- .../suite/sys_vars/r/sysvars_innodb.result | 14 -- .../t/innodb_force_recovery_crash_basic.test | 30 ---- storage/innobase/btr/btr0cur.cc | 3 +- storage/innobase/handler/ha_innodb.cc | 10 -- storage/innobase/include/srv0srv.h | 3 - storage/innobase/include/srv0start.h | 13 -- storage/innobase/include/ut0mutex.h | 2 +- storage/innobase/srv/srv0srv.cc | 5 - storage/innobase/srv/srv0start.cc | 82 +++++---- 12 files changed, 177 insertions(+), 216 deletions(-) delete mode 100644 mysql-test/suite/sys_vars/r/innodb_force_recovery_crash_basic.result delete mode 100644 mysql-test/suite/sys_vars/t/innodb_force_recovery_crash_basic.test diff --git a/mysql-test/suite/innodb/r/log_file_size.result b/mysql-test/suite/innodb/r/log_file_size.result index d83af099979..b73862af7c4 100644 --- a/mysql-test/suite/innodb/r/log_file_size.result +++ b/mysql-test/suite/innodb/r/log_file_size.result @@ -15,15 +15,38 @@ INSERT INTO t1 VALUES (123); BEGIN; DELETE FROM t1; # Kill the server ---innodb-force-recovery-crash=1 ---innodb-force-recovery-crash=3 ---innodb-force-recovery-crash=4 ---innodb-force-recovery-crash=5 ---innodb-force-recovery-crash=6 ---innodb-force-recovery-crash=7 ---innodb-force-recovery-crash=8 ---innodb-force-recovery-crash=9 ---innodb-force-recovery-crash=10 +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' +SELECT * FROM t1; +ERROR 42000: Unknown storage engine 'InnoDB' SELECT * FROM t1; a 42 diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index 371d761ba86..9d004991735 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -6,7 +6,7 @@ --source include/not_embedded.inc # Avoid CrashReporter popup on Mac --source include/not_crashrep.inc -# innodb-force-recovery-crash needs debug +# DBUG_EXECUTE_IF is needed --source include/have_debug.inc if (`SELECT @@innodb_log_file_size = 1048576`) { @@ -18,6 +18,16 @@ call mtr.add_suppression("InnoDB: Resizing redo log"); call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files"); call mtr.add_suppression("InnoDB: New log files created"); call mtr.add_suppression("InnoDB: The log sequence numbers [0-9]+ and [0-9]+ in ibdata files do not match the log sequence number [0-9]+ in the ib_logfiles"); +call mtr.add_suppression("syntax error in innodb_log_group_home_dir"); +call mtr.add_suppression("Plugin 'InnoDB' init function returned error"); +call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); +call mtr.add_suppression("InnoDB: Plugin initialization aborted"); +call mtr.add_suppression("InnoDB: innodb_read_only prevents crash recovery"); +call mtr.add_suppression("InnoDB: Are you sure you are using the right ib_logfiles"); +call mtr.add_suppression("InnoDB: Cannot create log files in read-only mode"); +call mtr.add_suppression("InnoDB: Only one log file found"); +call mtr.add_suppression("InnoDB: Log file .*ib_logfile[01].* size"); +call mtr.add_suppression("InnoDB: Unable to open .*ib_logfile0. to check native AIO read support"); FLUSH TABLES; --enable_query_log @@ -43,106 +53,122 @@ INSERT INTO t1 VALUES (123); let MYSQLD_DATADIR= `select @@datadir`; let SEARCH_ABORT = NOT FOUND; -let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; -# MDEV-11689 FIXME: add --core-file to $args, and remove all ,134 below -let $args=--innodb --unknown-option --loose-console > $SEARCH_FILE 2>&1; -let $crash=$args --innodb-force-recovery-crash; +let SEARCH_RANGE= -50000; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; BEGIN; DELETE FROM t1; --source include/kill_mysqld.inc ---error 2 ---exec $MYSQLD_CMD $args --innodb-log-group-home-dir=foo\;bar +--let $restart_parameters= --innodb-log-group-home-dir=foo\;bar +--source include/start_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= syntax error in innodb_log_group_home_dir; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=1 ---error 3,134 ---exec $MYSQLD_CMD $crash=1 +--let $restart_parameters= --debug=d,innodb_log_abort_1 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=3 ---error 3,134 ---exec $MYSQLD_CMD $crash=3 + +--let $restart_parameters= --debug=d,innodb_log_abort_3 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---error 2 ---exec $MYSQLD_CMD $args --innodb-read-only +--let $restart_parameters= --innodb-read-only +--source include/restart_mysqld.inc + +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=4 ---error 3,134 ---exec $MYSQLD_CMD $crash=4 +--let $restart_parameters= --debug=d,innodb_log_abort_4 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=5 ---error 3,134 ---exec $MYSQLD_CMD $crash=5 + +--let $restart_parameters= --debug=d,innodb_log_abort_5 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---error 2 ---exec $MYSQLD_CMD $args --innodb-read-only +--let $restart_parameters= --innodb-read-only +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=6 ---error 3,134 ---exec $MYSQLD_CMD $crash=6 +--let $restart_parameters= --debug=d,innodb_log_abort_6 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=7 ---error 3,134 ---exec $MYSQLD_CMD $crash=7 -# this crashes right after deleting all log files ---remove_file $SEARCH_FILE ---error 2 ---exec $MYSQLD_CMD $args --innodb-read-only +--let $restart_parameters= --debug=d,innodb_log_abort_7 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + +# this aborts right after deleting all log files + +--let $restart_parameters= --innodb-read-only +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + let SEARCH_PATTERN= InnoDB: Cannot create log files in read-only mode; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=8 ---error 3,134 ---exec $MYSQLD_CMD $crash=8 +--let $restart_parameters= --debug=d,innodb_log_abort_8 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE ---echo --innodb-force-recovery-crash=9 ---error 3,134 ---exec $MYSQLD_CMD $crash=9 + +--let $restart_parameters= --debug=d,innodb_log_abort_9 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE +--source include/shutdown_mysqld.inc # We should have perfectly synced files here. # Rename the log files, and trigger an error in recovery. --move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0 --move_file $MYSQLD_DATADIR/ib_logfile1 $MYSQLD_DATADIR/ib_logfile1_hidden ---error 2,134 ---exec $MYSQLD_CMD $args + +--let $restart_parameters= +--source include/start_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + let SEARCH_PATTERN= InnoDB: Only one log file found; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE --move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101 perl; @@ -150,11 +176,12 @@ die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile0"); print FILE "garbage"; close(FILE); EOF ---error 2,134 ---exec $MYSQLD_CMD $args + +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile0 size 7 is not a multiple of innodb_page_size; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE --remove_file $MYSQLD_DATADIR/ib_logfile0 --move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0 @@ -164,26 +191,28 @@ print FILE "junkfill" x 131072; close(FILE); EOF ---error 2,134 ---exec $MYSQLD_CMD $args +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile1 is of different size 1048576 bytes than other log files; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE --remove_file $MYSQLD_DATADIR/ib_logfile1 --move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101 --move_file $MYSQLD_DATADIR/ib_logfile1_hidden $MYSQLD_DATADIR/ib_logfile1 ---echo --innodb-force-recovery-crash=10 ---error 3,134 ---exec $MYSQLD_CMD $crash=10 +--let $restart_parameters= --debug=d,innodb_log_abort_10 +--source include/restart_mysqld.inc +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM t1; + let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: Renaming log file .*ib_logfile101 to .*ib_logfile0; --source include/search_pattern_in_file.inc ---remove_file $SEARCH_FILE --let $restart_parameters= ---source include/start_mysqld.inc +--source include/restart_mysqld.inc SELECT * FROM t1; DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/r/innodb_force_recovery_crash_basic.result b/mysql-test/suite/sys_vars/r/innodb_force_recovery_crash_basic.result deleted file mode 100644 index 5af00f21c74..00000000000 --- a/mysql-test/suite/sys_vars/r/innodb_force_recovery_crash_basic.result +++ /dev/null @@ -1,33 +0,0 @@ -select @@global.innodb_force_recovery_crash in (0, 1); -@@global.innodb_force_recovery_crash in (0, 1) -1 -select @@global.innodb_force_recovery_crash; -@@global.innodb_force_recovery_crash -0 -select @@session.innodb_force_recovery_crash; -ERROR HY000: Variable 'innodb_force_recovery_crash' is a GLOBAL variable -show global variables like 'innodb_force_recovery_crash'; -Variable_name Value -innodb_force_recovery_crash 0 -show session variables like 'innodb_force_recovery_crash'; -Variable_name Value -innodb_force_recovery_crash 0 -select * from information_schema.global_variables where variable_name='innodb_force_recovery_crash'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_FORCE_RECOVERY_CRASH 0 -select * from information_schema.session_variables where variable_name='innodb_force_recovery_crash'; -VARIABLE_NAME VARIABLE_VALUE -INNODB_FORCE_RECOVERY_CRASH 0 -set global innodb_force_recovery_crash=1; -ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable -set global innodb_force_recovery_crash=0; -ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable -select @@global.innodb_force_recovery_crash; -@@global.innodb_force_recovery_crash -0 -set session innodb_force_recovery_crash='some'; -ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable -set @@session.innodb_force_recovery_crash='some'; -ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable -set global innodb_force_recovery_crash='some'; -ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 5954b057d2f..4b4e10141ab 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1168,20 +1168,6 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED -VARIABLE_NAME INNODB_FORCE_RECOVERY_CRASH -SESSION_VALUE NULL -GLOBAL_VALUE 0 -GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE 0 -VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_COMMENT Kills the server during crash recovery. -NUMERIC_MIN_VALUE 0 -NUMERIC_MAX_VALUE 100 -NUMERIC_BLOCK_SIZE 0 -ENUM_VALUE_LIST NULL -READ_ONLY YES -COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME INNODB_FT_AUX_TABLE SESSION_VALUE NULL GLOBAL_VALUE diff --git a/mysql-test/suite/sys_vars/t/innodb_force_recovery_crash_basic.test b/mysql-test/suite/sys_vars/t/innodb_force_recovery_crash_basic.test deleted file mode 100644 index cfbd10c4e31..00000000000 --- a/mysql-test/suite/sys_vars/t/innodb_force_recovery_crash_basic.test +++ /dev/null @@ -1,30 +0,0 @@ ---source include/have_innodb.inc ---source include/have_debug.inc - -# -# exists as global only -# -select @@global.innodb_force_recovery_crash in (0, 1); -select @@global.innodb_force_recovery_crash; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -select @@session.innodb_force_recovery_crash; -show global variables like 'innodb_force_recovery_crash'; -show session variables like 'innodb_force_recovery_crash'; ---disable_warnings -select * from information_schema.global_variables where variable_name='innodb_force_recovery_crash'; -select * from information_schema.session_variables where variable_name='innodb_force_recovery_crash'; ---enable_warnings - -# show that it's read-only -# ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global innodb_force_recovery_crash=1; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global innodb_force_recovery_crash=0; -select @@global.innodb_force_recovery_crash; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set session innodb_force_recovery_crash='some'; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set @@session.innodb_force_recovery_crash='some'; ---error ER_INCORRECT_GLOBAL_LOCAL_VAR -set global innodb_force_recovery_crash='some'; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 8b139d58b96..9033c399ce2 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3,7 +3,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2015, 2016, MariaDB Corporation. +Copyright (c) 2015, 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -4208,7 +4208,6 @@ btr_cur_pessimistic_update( ut_ad(thr_get_trx(thr)->in_rollback); DBUG_EXECUTE_IF("ib_blob_update_rollback", DBUG_SUICIDE();); - RECOVERY_CRASH(99); btr_rec_free_updated_extern_fields( index, rec, page_zip, *offsets, update, true, mtr); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index fd9702c727e..7edc1fdd687 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -21326,13 +21326,6 @@ static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery, "Helps to save your data in case the disk image of the database becomes corrupt.", NULL, NULL, 0, 0, 6, 0); -#ifndef DBUG_OFF -static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash, - PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, - "Kills the server during crash recovery.", - NULL, NULL, 0, 0, 100, 0); -#endif /* !DBUG_OFF */ - static MYSQL_SYSVAR_ULONG(page_size, srv_page_size, PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY, "Page size to use for all InnoDB tablespaces.", @@ -21975,9 +21968,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(flush_log_at_trx_commit), MYSQL_SYSVAR(flush_method), MYSQL_SYSVAR(force_recovery), -#ifndef DBUG_OFF - MYSQL_SYSVAR(force_recovery_crash), -#endif /* !DBUG_OFF */ MYSQL_SYSVAR(fill_factor), MYSQL_SYSVAR(ft_cache_size), MYSQL_SYSVAR(ft_total_cache_size), diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index ca81ad46b8b..b22487ca1ef 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -450,9 +450,6 @@ extern double srv_adaptive_flushing_lwm; extern ulong srv_flushing_avg_loops; extern ulong srv_force_recovery; -#ifndef DBUG_OFF -extern ulong srv_force_recovery_crash; -#endif /* !DBUG_OFF */ extern ulint srv_fast_shutdown; /*!< If this is 1, do not do a purge and index buffer merge. diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index f08e6e71a78..d456806b86b 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -34,19 +34,6 @@ Created 10/10/1995 Heikki Tuuri // Forward declaration struct dict_table_t; -#ifdef DBUG_OFF -# define RECOVERY_CRASH(x) do {} while(0) -#else -# define RECOVERY_CRASH(x) do { \ - if (srv_force_recovery_crash == x) { \ - fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \ - srv_force_recovery_crash); \ - fflush(stderr); \ - exit(3); \ - } \ -} while (0) -#endif /* DBUG_OFF */ - /** If buffer pool is less than the size, only one buffer pool instance is used. */ #define BUF_POOL_SIZE_THRESHOLD (1024 * 1024 * 1024) diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h index 197a34e6122..354fd9e0a7a 100644 --- a/storage/innobase/include/ut0mutex.h +++ b/storage/innobase/include/ut0mutex.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -30,7 +31,6 @@ Created 2012-03-24 Sunny Bains. extern uint srv_spin_wait_delay; extern ulong srv_n_spin_wait_rounds; -extern ulong srv_force_recovery_crash; #include "sync0policy.h" #include "ib0mutex.h" diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 56fc8524945..8ae2193a7a0 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -359,11 +359,6 @@ starting from SRV_FORCE_IGNORE_CORRUPT, so that data can be recovered by SELECT or mysqldump. When this is nonzero, we do not allow any user modifications to the data. */ ulong srv_force_recovery; -#ifndef DBUG_OFF -/** Inject a crash at different steps of the recovery process. -This is for testing and debugging only. */ -ulong srv_force_recovery_crash; -#endif /* !DBUG_OFF */ /** Print all user-level transactions deadlocks to mysqld stderr */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 587ffc15adb..408501f6f0d 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -418,12 +418,12 @@ create_log_files( file should be recoverable. The buffer pool was clean, and we can simply create all log files from the scratch. */ - RECOVERY_CRASH(6); + DBUG_EXECUTE_IF("innodb_log_abort_6", return(DB_ERROR);); } ut_ad(!buf_pool_check_no_pending_io()); - RECOVERY_CRASH(7); + DBUG_EXECUTE_IF("innodb_log_abort_7", return(DB_ERROR);); for (unsigned i = 0; i < srv_n_log_files; i++) { sprintf(logfilename + dirnamelen, @@ -436,7 +436,7 @@ create_log_files( } } - RECOVERY_CRASH(8); + DBUG_EXECUTE_IF("innodb_log_abort_8", return(DB_ERROR);); /* We did not create the first log file initially as ib_logfile0, so that crash recovery cannot find it until it @@ -488,10 +488,16 @@ create_log_files( return(DB_SUCCESS); } -/*********************************************************************//** -Renames the first log file. */ +/** Rename the first redo log file. +@param[in,out] logfilename buffer for the log file name +@param[in] dirnamelen length of the directory path +@param[in] lsn FIL_PAGE_FILE_FLUSH_LSN value +@param[in,out] logfile0 name of the first log file +@return error code +@retval DB_SUCCESS on successful operation */ +MY_ATTRIBUTE((warn_unused_result, nonnull)) static -void +dberr_t create_log_files_rename( /*====================*/ char* logfilename, /*!< in/out: buffer for log file name */ @@ -502,6 +508,9 @@ create_log_files_rename( /* If innodb_flush_method=O_DSYNC, we need to explicitly flush the log buffers. */ fil_flush(SRV_LOG_SPACE_FIRST_ID); + + DBUG_EXECUTE_IF("innodb_log_abort_9", return(DB_ERROR);); + /* Close the log files, so that we can rename the first one. */ fil_close_log_files(false); @@ -510,26 +519,26 @@ create_log_files_rename( checkpoint has been created. */ sprintf(logfilename + dirnamelen, "ib_logfile%u", 0); - RECOVERY_CRASH(9); - ib::info() << "Renaming log file " << logfile0 << " to " << logfilename; log_mutex_enter(); ut_ad(strlen(logfile0) == 2 + strlen(logfilename)); - bool success = os_file_rename( - innodb_log_file_key, logfile0, logfilename); - ut_a(success); - - RECOVERY_CRASH(10); + dberr_t err = os_file_rename( + innodb_log_file_key, logfile0, logfilename) + ? DB_SUCCESS : DB_ERROR; /* Replace the first file with ib_logfile0. */ strcpy(logfile0, logfilename); log_mutex_exit(); + DBUG_EXECUTE_IF("innodb_log_abort_10", err = DB_ERROR;); + fil_open_log_and_system_tablespace_files(); ib::warn() << "New log files created, LSN=" << lsn; + + return(err); } /*********************************************************************//** @@ -1117,8 +1126,6 @@ srv_open_tmp_tablespace(bool create_new_db) srv_tmp_space.set_space_id(SRV_TMP_SPACE_ID); - RECOVERY_CRASH(100); - dberr_t err = srv_tmp_space.check_file_spec( &create_new_temp_space, 12 * 1024 * 1024); @@ -1347,7 +1354,7 @@ srv_prepare_to_delete_redo_log_files( /* Clean the buffer pool. */ buf_flush_sync_all_buf_pools(); - RECOVERY_CRASH(1); + DBUG_EXECUTE_IF("innodb_log_abort_1", return(0);); log_mutex_enter(); @@ -1952,14 +1959,17 @@ innobase_start_or_create_for_mysql(void) logfilename, dirnamelen, flushed_lsn, logfile0); + if (err == DB_SUCCESS) { + err = create_log_files_rename( + logfilename, + dirnamelen, + flushed_lsn, logfile0); + } + if (err != DB_SUCCESS) { return(srv_init_abort(err)); } - create_log_files_rename( - logfilename, dirnamelen, - flushed_lsn, logfile0); - /* Suppress the message about crash recovery. */ flushed_lsn = log_get_lsn(); @@ -2119,13 +2129,15 @@ files_checked: err = fil_write_flushed_lsn(flushed_lsn); + if (err == DB_SUCCESS) { + err = create_log_files_rename( + logfilename, dirnamelen, + flushed_lsn, logfile0); + } + if (err != DB_SUCCESS) { return(srv_init_abort(err)); } - - create_log_files_rename( - logfilename, dirnamelen, flushed_lsn, logfile0); - } else { /* Check if we support the max format that is stamped @@ -2348,28 +2360,32 @@ files_checked: /* Prepare to delete the old redo log files */ flushed_lsn = srv_prepare_to_delete_redo_log_files(i); + DBUG_EXECUTE_IF("innodb_log_abort_1", + return(srv_init_abort(DB_ERROR));); /* Prohibit redo log writes from any other threads until creating a log checkpoint at the end of create_log_files(). */ ut_d(recv_no_log_write = true); ut_ad(!buf_pool_check_no_pending_io()); - RECOVERY_CRASH(3); + DBUG_EXECUTE_IF("innodb_log_abort_3", + return(srv_init_abort(DB_ERROR));); /* Stamp the LSN to the data files. */ err = fil_write_flushed_lsn(flushed_lsn); + DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;); + if (err != DB_SUCCESS) { return(srv_init_abort(err)); } - RECOVERY_CRASH(4); - /* Close and free the redo log files, so that we can replace them. */ fil_close_log_files(true); - RECOVERY_CRASH(5); + DBUG_EXECUTE_IF("innodb_log_abort_5", + return(srv_init_abort(DB_ERROR));); /* Free the old log file space. */ log_group_close_all(); @@ -2383,13 +2399,15 @@ files_checked: logfilename, dirnamelen, flushed_lsn, logfile0); + if (err == DB_SUCCESS) { + err = create_log_files_rename( + logfilename, dirnamelen, flushed_lsn, + logfile0); + } + if (err != DB_SUCCESS) { return(srv_init_abort(err)); } - - create_log_files_rename( - logfilename, dirnamelen, flushed_lsn, - logfile0); } recv_recovery_rollback_active(); From 7128328d418514c6a7fd61af37d27cfdeebe099e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 30 Jan 2017 18:15:44 +0200 Subject: [PATCH 151/167] Remove a work-around for MDEV-11689. Also, work around MDEV-11948 by disabling native asynchronous I/O. --- mysql-test/suite/innodb/t/log_file.test | 33 +++++++++++++------------ 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/innodb/t/log_file.test b/mysql-test/suite/innodb/t/log_file.test index c8b06ff382a..7e52ccfc726 100644 --- a/mysql-test/suite/innodb/t/log_file.test +++ b/mysql-test/suite/innodb/t/log_file.test @@ -28,18 +28,19 @@ innodb_data_home_dir = $ENV{bugdir} datadir = $ENV{bugdir} secure_file_priv= skip_aria -#core_file # MDEV-11689 FIXME: add this back, and remove all ,134 below +core_file innodb_data_file_path = ibdata1:10M;ibdata2:10M:autoextend innodb_undo_logs = 20 innodb_undo_tablespaces = 3 innodb_log_files_in_group = 3 +skip_innodb_use_native_aio # MDEV-11948 CentOS 5 fails to write ib_logfile101 "; close(OUT); EOF --echo # Start mysqld without the possibility to create innodb_undo_tablespaces --mkdir $bugdir/undo002 ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=\[ERROR\] InnoDB: Could not create undo tablespace '.*undo002'; --source include/search_pattern_in_file.inc @@ -57,7 +58,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --list_files $bugdir --echo # Start mysqld with non existent innodb_log_group_home_dir ---error 1,134 +--error 1 --exec $MYSQLD $args --innodb_log_group_home_dir=/path/to/non-existent/ let SEARCH_PATTERN=File .path.to.non-existent.*ib_logfile101: 'create' returned OS error \d+; --source include/search_pattern_in_file.inc @@ -73,7 +74,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; # complaining about mysql.* tables. This is sufficient for testing # missing tablespaces. --echo # Start mysqld to create tablespaces according to my.cnf ---error 2,134 +--error 2 --exec $MYSQLD $args --skip-grant-tables --innodb-unknown-parameter let SEARCH_PATTERN=unknown option '--innodb-unknown-parameter'; --source include/search_pattern_in_file.inc @@ -92,7 +93,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --echo # 1. With ibdata2, Without ibdata1 --remove_file $bugdir/ibdata1 ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=The innodb_system data file 'ibdata1' was not found but one of the other data files 'ibdata2' exists; --source include/search_pattern_in_file.inc @@ -104,7 +105,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --echo # 2. With ibdata1, without ibdata2 --remove_file $bugdir/ibdata2 ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=Tablespace size stored in header is \d+ pages, but; --source include/search_pattern_in_file.inc @@ -118,7 +119,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --remove_file $bugdir/ibdata1 --remove_file $bugdir/ibdata2 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=undo tablespace .*undo001.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; --source include/search_pattern_in_file.inc @@ -132,7 +133,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --remove_files_wildcard $bugdir ibdata* --remove_files_wildcard $bugdir ib_logfile* --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=undo tablespace .*undo001.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; --source include/search_pattern_in_file.inc @@ -148,7 +149,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --remove_files_wildcard $bugdir ib_logfile* --remove_file $bugdir/undo002 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=undo tablespace .*undo001.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; --source include/search_pattern_in_file.inc @@ -165,7 +166,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --remove_file $bugdir/undo001 --remove_file $bugdir/undo002 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=undo tablespace .*undo003.* exists\. Creating system tablespace with existing undo tablespaces is not supported\. Please delete all undo tablespaces before creating new system tablespace\.; --source include/search_pattern_in_file.inc @@ -178,7 +179,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --echo # 7. With ibdata files & Without undo002 --remove_file $bugdir/undo002 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=Expected to open 3 undo tablespaces but was able; --source include/search_pattern_in_file.inc @@ -193,7 +194,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --remove_file $bugdir/undo001 --remove_file $bugdir/undo002 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=Expected to open 3 undo tablespaces but was able; --source include/search_pattern_in_file.inc @@ -210,7 +211,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --remove_files_wildcard $bugdir undo00* --remove_file $bugdir/ib_logfile1 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=redo log file .*ib_logfile0.* exists\. Creating system tablespace with existing redo log files is not recommended\. Please delete all redo log files before creating new system tablespace\.; --source include/search_pattern_in_file.inc @@ -224,7 +225,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; #--remove_file $bugdir/ib_logfile0 # The below would start the server. Since we cannot start a parallel # server, do not test the below case -#--error 1,134 +#--error 1 #--exec $MYSQLD $args # clean up & Restore @@ -233,7 +234,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --echo # 11. With ibdata*, without ib_logfile1 --remove_file $bugdir/ib_logfile1 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=Only one log file found; --source include/search_pattern_in_file.inc @@ -246,7 +247,7 @@ let SEARCH_PATTERN=\[ERROR\] Aborting; --echo # 12. With ibdata*, without ib_logfile2 --remove_file $bugdir/ib_logfile2 --list_files $bugdir ---error 1,134 +--error 1 --exec $MYSQLD $args let SEARCH_PATTERN=Resizing redo log from \d+\*\d+ to \d+\*\d+ pages, LSN=\d+; --source include/search_pattern_in_file.inc From 642077ea5a67eaa0594468df4ae0ab297d9f62f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 30 Jan 2017 17:50:54 +0200 Subject: [PATCH 152/167] srv_get_active_thread_type(): Remove a potential race condition. Call trx_purge_state() only once, to avoid a race condition if the value changes while the conditions are being evaluated. --- storage/innobase/srv/srv0srv.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 8ae2193a7a0..c2cf71a2f98 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2013,13 +2013,18 @@ srv_get_active_thread_type(void) srv_sys_mutex_exit(); - /* Check only on shutdown. */ - if (ret == SRV_NONE - && srv_shutdown_state != SRV_SHUTDOWN_NONE - && trx_purge_state() != PURGE_STATE_DISABLED - && trx_purge_state() != PURGE_STATE_EXIT) { - - ret = SRV_PURGE; + if (ret == SRV_NONE && srv_shutdown_state != SRV_SHUTDOWN_NONE) { + /* Check only on shutdown. */ + switch (trx_purge_state()) { + case PURGE_STATE_INIT: + case PURGE_STATE_RUN: + case PURGE_STATE_STOP: + ret = SRV_PURGE; + break; + case PURGE_STATE_DISABLED: + case PURGE_STATE_EXIT: + break; + } } return(ret); From 1d96b09890966a45a9c3e4e17f973ecaaefb6a8f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 31 Jan 2017 23:41:10 +0400 Subject: [PATCH 153/167] MDEV-9979 Keywords UNBOUNDED, PRECEDING, FOLLOWING, TIES, OTHERS should be non-reserved Adding keywords the following keywords into the "keyword" rules: - EXCLUDE - UNBOUNDED - PRECEDING - FOLLOWING - TIES - OTHERS They are non-reserved words in the SQL standard (checked in a SQL-2011 draft), and they don't cause any conflicts in sql_yacc.yy. --- mysql-test/r/keywords.result | 51 ++++++++++++++++++++++++++++++++++++ mysql-test/t/keywords.test | 40 ++++++++++++++++++++++++++++ sql/sql_yacc.yy | 19 +++++++++----- 3 files changed, 104 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result index f5bf600dc40..8c510b712ce 100644 --- a/mysql-test/r/keywords.result +++ b/mysql-test/r/keywords.result @@ -276,6 +276,57 @@ ERROR HY000: Unknown system variable 'option' set option option=1; ERROR HY000: Unknown system variable 'option' # +# MDEV-9979 Keywords UNBOUNDED, PRECEDING, FOLLOWING, TIES, OTHERS should be non-reserved +# +CREATE TABLE EXCLUDE (EXCLUDE INT); +SELECT EXCLUDE FROM EXCLUDE; +EXCLUDE +SELECT EXCLUDE EXCLUDE FROM EXCLUDE; +EXCLUDE +SELECT EXCLUDE AS EXCLUDE FROM EXCLUDE; +EXCLUDE +DROP TABLE EXCLUDE; +CREATE TABLE UNBOUNDED (UNBOUNDED INT); +SELECT UNBOUNDED FROM UNBOUNDED; +UNBOUNDED +SELECT UNBOUNDED UNBOUNDEX FROM UNBOUNDED; +UNBOUNDEX +SELECT UNBOUNDED AS UNBOUNDEX FROM UNBOUNDED; +UNBOUNDEX +DROP TABLE UNBOUNDED; +CREATE TABLE PRECEDING (PRECEDING INT); +SELECT PRECEDING FROM PRECEDING; +PRECEDING +SELECT PRECEDING PRECEDING FROM PRECEDING; +PRECEDING +SELECT PRECEDING AS PRECEDING FROM PRECEDING; +PRECEDING +DROP TABLE PRECEDING; +CREATE TABLE FOLLOWING (FOLLOWING INT); +SELECT FOLLOWING FROM FOLLOWING; +FOLLOWING +SELECT FOLLOWING FOLLOWING FROM FOLLOWING; +FOLLOWING +SELECT FOLLOWING AS FOLLOWING FROM FOLLOWING; +FOLLOWING +DROP TABLE FOLLOWING; +CREATE TABLE TIES (TIES INT); +SELECT TIES FROM TIES; +TIES +SELECT TIES TIES FROM TIES; +TIES +SELECT TIES AS TIES FROM TIES; +TIES +DROP TABLE TIES; +CREATE TABLE OTHERS (OTHERS INT); +SELECT OTHERS FROM OTHERS; +OTHERS +SELECT OTHERS OTHERS FROM OTHERS; +OTHERS +SELECT OTHERS AS OTHERS FROM OTHERS; +OTHERS +DROP TABLE OTHERS; +# # MDEV-10585 EXECUTE IMMEDIATE statement # CREATE TABLE immediate (immediate int); diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test index 40beee9e3c1..5c4c813ab39 100644 --- a/mysql-test/t/keywords.test +++ b/mysql-test/t/keywords.test @@ -174,6 +174,46 @@ set option=1; --error 1193 set option option=1; +--echo # +--echo # MDEV-9979 Keywords UNBOUNDED, PRECEDING, FOLLOWING, TIES, OTHERS should be non-reserved +--echo # +CREATE TABLE EXCLUDE (EXCLUDE INT); +SELECT EXCLUDE FROM EXCLUDE; +SELECT EXCLUDE EXCLUDE FROM EXCLUDE; +SELECT EXCLUDE AS EXCLUDE FROM EXCLUDE; +DROP TABLE EXCLUDE; + +CREATE TABLE UNBOUNDED (UNBOUNDED INT); +SELECT UNBOUNDED FROM UNBOUNDED; +SELECT UNBOUNDED UNBOUNDEX FROM UNBOUNDED; +SELECT UNBOUNDED AS UNBOUNDEX FROM UNBOUNDED; +DROP TABLE UNBOUNDED; + +CREATE TABLE PRECEDING (PRECEDING INT); +SELECT PRECEDING FROM PRECEDING; +SELECT PRECEDING PRECEDING FROM PRECEDING; +SELECT PRECEDING AS PRECEDING FROM PRECEDING; +DROP TABLE PRECEDING; + +CREATE TABLE FOLLOWING (FOLLOWING INT); +SELECT FOLLOWING FROM FOLLOWING; +SELECT FOLLOWING FOLLOWING FROM FOLLOWING; +SELECT FOLLOWING AS FOLLOWING FROM FOLLOWING; +DROP TABLE FOLLOWING; + +CREATE TABLE TIES (TIES INT); +SELECT TIES FROM TIES; +SELECT TIES TIES FROM TIES; +SELECT TIES AS TIES FROM TIES; +DROP TABLE TIES; + +CREATE TABLE OTHERS (OTHERS INT); +SELECT OTHERS FROM OTHERS; +SELECT OTHERS OTHERS FROM OTHERS; +SELECT OTHERS AS OTHERS FROM OTHERS; +DROP TABLE OTHERS; + + --echo # --echo # MDEV-10585 EXECUTE IMMEDIATE statement --echo # diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ff4a5e12e56..74a61425141 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1030,6 +1030,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); Comments for TOKENS. For each token, please include in the same line a comment that contains the following tags: + SQL-2011-N : Non Reserved keywird as per SQL-2011 SQL-2003-R : Reserved keyword as per SQL-2003 SQL-2003-N : Non Reserved keyword as per SQL-2003 SQL-1999-R : Reserved keyword as per SQL-1999 @@ -1219,7 +1220,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token EVERY_SYM /* SQL-2003-N */ %token EXCHANGE_SYM %token EXAMINED_SYM -%token EXCLUDE_SYM +%token EXCLUDE_SYM /* SQL-2011-N */ %token EXECUTE_SYM /* SQL-2003-R */ %token EXISTS /* SQL-2003-R */ %token EXIT_SYM @@ -1240,7 +1241,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token FLOAT_SYM /* SQL-2003-R */ %token FLUSH_SYM %token FOLLOWS_SYM /* MYSQL trigger*/ -%token FOLLOWING_SYM +%token FOLLOWING_SYM /* SQL-2011-N */ %token FORCE_SYM %token FOREIGN /* SQL-2003-R */ %token FOR_SYM /* SQL-2003-R */ @@ -1442,7 +1443,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ORDER_SYM /* SQL-2003-R */ %token OR_OR_SYM /* OPERATOR */ %token OR_SYM /* SQL-2003-R */ -%token OTHERS_SYM +%token OTHERS_SYM /* SQL-2011-N */ %token OUTER %token OUTFILE %token OUT_SYM /* SQL-2003-R */ @@ -1469,7 +1470,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token PORT_SYM %token POSITION_SYM /* SQL-2003-N */ %token PRECEDES_SYM /* MYSQL */ -%token PRECEDING_SYM +%token PRECEDING_SYM /* SQL-2011-N */ %token PRECISION /* SQL-2003-R */ %token PREPARE_SYM /* SQL-2003-R */ %token PRESERVE_SYM @@ -1630,7 +1631,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token TEXT_SYM %token THAN_SYM %token THEN_SYM /* SQL-2003-R */ -%token TIES_SYM +%token TIES_SYM /* SQL-2011-N */ %token TIMESTAMP /* SQL-2003-R */ %token TIMESTAMP_ADD %token TIMESTAMP_DIFF @@ -1651,7 +1652,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token TYPE_SYM /* SQL-2003-N */ %token UDF_RETURNS_SYM %token ULONGLONG_NUM -%token UNBOUNDED_SYM +%token UNBOUNDED_SYM /* SQL-2011-N */ %token UNCOMMITTED_SYM /* SQL-2003-N */ %token UNDEFINED_SYM %token UNDERSCORE_CHARSET @@ -14539,9 +14540,11 @@ keyword: | DO_SYM {} | END {} | EXAMINED_SYM {} + | EXCLUDE_SYM {} | EXECUTE_SYM {} | FLUSH_SYM {} | FOLLOWS_SYM {} + | FOLLOWING_SYM {} | FORMAT_SYM {} | GET_SYM {} | HANDLER_SYM {} @@ -14553,10 +14556,12 @@ keyword: | OPEN_SYM {} | OPTION {} | OPTIONS_SYM {} + | OTHERS_SYM {} | OWNER_SYM {} | PARSER_SYM {} | PORT_SYM {} | PRECEDES_SYM {} + | PRECEDING_SYM {} | PREPARE_SYM {} | REMOVE_SYM {} | REPAIR {} @@ -14575,9 +14580,11 @@ keyword: | START_SYM {} | STOP_SYM {} | STORED_SYM {} + | TIES_SYM {} | TRUNCATE_SYM {} | UNICODE_SYM {} | UNINSTALL_SYM {} + | UNBOUNDED_SYM {} | WRAPPER_SYM {} | XA_SYM {} | UPGRADE_SYM {} From 68235f2c2b29f5abadbfaedef6e9093313c86a15 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 1 Feb 2017 08:00:50 +0400 Subject: [PATCH 154/167] MDEV-11692 Comparison data type aggregation for pluggable data types --- mysql-test/r/bug13633383.result | 66 +- mysql-test/r/gis-debug.result | 47 + mysql-test/r/gis.result | 909 +++++++++++++++++- mysql-test/r/partition.result | 2 +- mysql-test/suite/innodb_gis/r/1.result | 10 +- .../innodb_gis/r/alter_spatial_index.result | 2 + .../innodb_gis/r/create_spatial_index.result | 4 +- mysql-test/suite/innodb_gis/r/gis.result | 10 +- mysql-test/suite/innodb_gis/t/1.test | 2 + .../innodb_gis/t/alter_spatial_index.test | 3 + .../innodb_gis/t/create_spatial_index.test | 2 + mysql-test/suite/innodb_gis/t/gis.test | 2 + mysql-test/t/bug13633383.test | 1 + mysql-test/t/gis-debug.test | 26 + mysql-test/t/gis.test | 69 ++ mysql-test/t/partition.test | 1 + sql/item_cmpfunc.cc | 88 +- sql/item_cmpfunc.h | 6 +- sql/sql_type.cc | 39 +- sql/sql_type.h | 9 +- 20 files changed, 1174 insertions(+), 124 deletions(-) diff --git a/mysql-test/r/bug13633383.result b/mysql-test/r/bug13633383.result index a6f5bab5260..ed94ec5b98b 100644 --- a/mysql-test/r/bug13633383.result +++ b/mysql-test/r/bug13633383.result @@ -45,70 +45,6 @@ repeat('a',10000) desc, repeat('a',10000) with rollup ; -col435 -0.00000000000000000 -0.00000000000000000 -0.00000000000000000 -Warnings: -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00k\xBF\xC0\x00\x00\x00\x00\x00j\xF8@' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x006\x0E\xFD\xB9PVh,;b\xC2\xBA\xF6$\xEE\xB0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC0\xAE\xDB\xC0' -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00j\xF8@\x00\x00\x00\x00\x00\x00\x00\x00' +ERROR HY000: Illegal parameter data types int and geometry for operation '=' set session sort_buffer_size= default; DROP TABLE t1, t2, t3; diff --git a/mysql-test/r/gis-debug.result b/mysql-test/r/gis-debug.result index 79adef34b98..0f63509bb99 100644 --- a/mysql-test/r/gis-debug.result +++ b/mysql-test/r/gis-debug.result @@ -305,3 +305,50 @@ ERROR HY000: Function or expression 'st_gis_debug()' cannot be used in the DEFAU # # End of 10.2 tests # +# +# Start of 10.3 tests +# +# +# Comparison data type aggregation for pluggable data types +# +SET SESSION debug_dbug="+d,Item_func_in"; +SET SESSION debug_dbug="+d,Predicant_to_list_comparator"; +CREATE TABLE t1 (a POINT); +INSERT INTO t1 VALUES (POINT(1,1)),(POINT(1,2)),(POINT(1,3)); +SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30)); +COUNT(*) +1 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (geometry) +Note 1105 DBUG: [1] arg=2 handler=0 (geometry) +Note 1105 DBUG: [2] arg=3 handler=0 (geometry) +Note 1105 DBUG: types_compatible=yes bisect=yes +SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30),'test'); +COUNT(*) +1 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (geometry) +Note 1105 DBUG: [1] arg=2 handler=0 (geometry) +Note 1105 DBUG: [2] arg=3 handler=0 (geometry) +Note 1105 DBUG: [3] arg=4 handler=3 (longblob) +Note 1105 DBUG: types_compatible=no bisect=no +SELECT COUNT(*) FROM t1 WHERE a IN ('test','test1'); +COUNT(*) +0 +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (longblob) +Note 1105 DBUG: [1] arg=2 handler=0 (longblob) +Note 1105 DBUG: types_compatible=yes bisect=yes +DROP TABLE t1; +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES ('test'),('test1'),('test2'); +SELECT * FROM t1 WHERE a IN ('test',POINT(1,1)); +a +test +Warnings: +Note 1105 DBUG: [0] arg=1 handler=0 (longblob) +Note 1105 DBUG: [1] arg=2 handler=0 (longblob) +Note 1105 DBUG: types_compatible=yes bisect=yes +DROP TABLE t1; +SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; +SET SESSION debug_dbug="-d,Item_func_in"; diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 601590c88c1..3da76826611 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1017,7 +1017,7 @@ GEOMFROMTEXT( 'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))')); # must not crash SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); -1 +ERROR HY000: Illegal parameter data types int and geometry for operation '<>' DROP TABLE t1; # # Bug #49250 : spatial btree index corruption and crash @@ -1645,11 +1645,7 @@ FLUSH TABLES; SELECT 1 FROM g1 FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month) ; -1 -Warnings: -Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\xF0?' -Warning 1441 Datetime function: datetime field overflow -Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\x00@' +ERROR HY000: Illegal parameter data types geometry and datetime for operation '=' DROP TABLE g1; # # Bug#13013970 MORE CRASHES IN FIELD_BLOB::GET_KEY_IMAGE @@ -2814,5 +2810,906 @@ DROP TABLE t1; DROP PROCEDURE p1; DROP PROCEDURE p2; # +# MDEV-11692 Comparison data type aggregation for pluggable data types +# +CREATE PROCEDURE p2(query TEXT) +BEGIN +DECLARE errcount INT DEFAULT 0; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +SET errcount = errcount+1; +GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT; +SELECT @p AS `ERROR: `; +END; +SELECT query AS ``; +EXECUTE IMMEDIATE query; +END; +$$ +CREATE PROCEDURE p1(query TEXT) +BEGIN +SELECT query AS `-------------------------------------`; +EXECUTE IMMEDIATE query; +CALL p2('SELECT a=b FROM t1'); +CALL p2('SELECT b=a FROM t1'); +CALL p2('SELECT a BETWEEN b AND c FROM t1'); +CALL p2('SELECT a IN (b,c) FROM t1'); +CALL p2('SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1'); +CALL p2('SELECT a=POINT(1,1) FROM t1'); +CALL p2('SELECT POINT(1,1)=a FROM t1'); +CALL p2('SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1'); +CALL p2('SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1'); +CALL p2('SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1'); +DROP TABLE t1; +END; +$$ +CALL p1('CREATE TABLE t1 (a CHAR(10), b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a CHAR(10), b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +CALL p1('CREATE TABLE t1 (a VARCHAR(10), b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a VARCHAR(10), b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +CALL p1('CREATE TABLE t1 (a TINYTEXT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a TINYTEXT, b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +CALL p1('CREATE TABLE t1 (a TEXT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a TEXT, b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +CALL p1('CREATE TABLE t1 (a MEDIUMTEXT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a MEDIUMTEXT, b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +CALL p1('CREATE TABLE t1 (a LONGTEXT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a LONGTEXT, b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +CALL p1('CREATE TABLE t1 (a ENUM("a","b"), b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a ENUM("a","b"), b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +CALL p1('CREATE TABLE t1 (a TINYINT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a TINYINT, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and tinyint for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and tinyint for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types tinyint and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a SMALLINT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a SMALLINT, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and smallint for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and smallint for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types smallint and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a MEDIUMINT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a MEDIUMINT, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and mediumint for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and mediumint for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types mediumint and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a INT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a INT, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and int for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and int for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types int and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a BIGINT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a BIGINT, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and bigint for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and bigint for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types bigint and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a FLOAT, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a FLOAT, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and float for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and float for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types float and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a DOUBLE, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a DOUBLE, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and double for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and double for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types double and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a DECIMAL(10,2), b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a DECIMAL(10,2), b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and decimal for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and decimal for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types decimal and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a BIT(8), b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a BIT(8), b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and bit for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and bit for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types bit and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a TIME, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a TIME, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and time for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and time for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types time and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a DATE, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a DATE, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and date for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and date for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types date and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a DATETIME, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a DATETIME, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and datetime for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and datetime for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types datetime and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a TIMESTAMP, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a TIMESTAMP, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and timestamp for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and timestamp for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types timestamp and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a YEAR, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a YEAR, b Point, c Point) + +SELECT a=b FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation '=' + +SELECT b=a FROM t1 +ERROR: +Illegal parameter data types geometry and year for operation '=' + +SELECT a BETWEEN b AND c FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation 'between' + +SELECT a IN (b,c) FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation 'in' + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation 'case..when' + +SELECT a=POINT(1,1) FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation '=' + +SELECT POINT(1,1)=a FROM t1 +ERROR: +Illegal parameter data types geometry and year for operation '=' + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation 'between' + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation 'in' + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +ERROR: +Illegal parameter data types year and geometry for operation 'case..when' +CALL p1('CREATE TABLE t1 (a Point, b Point, c Point)'); +------------------------------------- +CREATE TABLE t1 (a Point, b Point, c Point) + +SELECT a=b FROM t1 +a=b + +SELECT b=a FROM t1 +b=a + +SELECT a BETWEEN b AND c FROM t1 +a BETWEEN b AND c + +SELECT a IN (b,c) FROM t1 +a IN (b,c) + +SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1 +CASE a WHEN b THEN "a" WHEN c THEN "b" END + +SELECT a=POINT(1,1) FROM t1 +a=POINT(1,1) + +SELECT POINT(1,1)=a FROM t1 +POINT(1,1)=a + +SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1 +a BETWEEN POINT(1,1) AND POINT(1,2) + +SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1 +a IN (POINT(1,1),POINT(1,2)) + +SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1 +CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END +DROP PROCEDURE p1; +DROP PROCEDURE p2; +# # End of 10.3 tests # diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index a30c38ad55c..8489d03f119 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -2439,7 +2439,7 @@ SELECT 1 FROM t1 WHERE b < SOME GROUP BY b WITH ROLLUP HAVING b > geomfromtext("") ); -1 +ERROR HY000: Illegal parameter data types mediumint and geometry for operation '>' DROP TABLE t1; MDEV-612 Valgrind error in ha_maria::check_if_incompatible_data diff --git a/mysql-test/suite/innodb_gis/r/1.result b/mysql-test/suite/innodb_gis/r/1.result index 94bd5f3b2e8..ca96b6cb21f 100644 --- a/mysql-test/suite/innodb_gis/r/1.result +++ b/mysql-test/suite/innodb_gis/r/1.result @@ -996,9 +996,7 @@ ST_GEOMFROMTEXT( 'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))')); # must not crash SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); -1 -Warnings: -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x06\x00\x00\x00\x01\x00\x00\x00\x01\x03\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' +ERROR HY000: Illegal parameter data types int and geometry for operation '<>' DROP TABLE t1; # # Bug #49250 : spatial btree index corruption and crash @@ -1105,11 +1103,7 @@ FLUSH TABLES; SELECT 1 FROM g1 FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month) ; -1 -Warnings: -Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\xF0?' -Warning 1441 Datetime function: datetime field overflow -Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\x00@' +ERROR HY000: Illegal parameter data types geometry and datetime for operation '=' DROP TABLE g1; # # Bug#13013970 MORE CRASHES IN FIELD_BLOB::GET_KEY_IMAGE diff --git a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result index 78d5f79e311..dc76a004731 100644 --- a/mysql-test/suite/innodb_gis/r/alter_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/alter_spatial_index.result @@ -256,6 +256,8 @@ INSERT INTO tab SELECT * FROM tab1; ALTER TABLE tab DROP PRIMARY KEY; ALTER TABLE tab DROP INDEX idx2; CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab where c1 = c2; +ERROR HY000: Illegal parameter data types int and geometry for operation '=' +CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab; INSERT INTO temp_tab SELECT * FROM tab; CREATE SPATIAL INDEX idx2 ON temp_tab(c2); CREATE SPATIAL INDEX idx3 ON temp_tab(c3); diff --git a/mysql-test/suite/innodb_gis/r/create_spatial_index.result b/mysql-test/suite/innodb_gis/r/create_spatial_index.result index 1d47fd9688c..572e3ac0d14 100644 --- a/mysql-test/suite/innodb_gis/r/create_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/create_spatial_index.result @@ -1238,13 +1238,15 @@ Table Op Msg_type Msg_text test.tab check status OK DROP TABLE tab; CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB; +ERROR HY000: Illegal parameter data types geometry and bigint for operation '>' +CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(CAST(c1 AS BINARY) > 0) ) ENGINE=InnoDB; CREATE SPATIAL INDEX idx1 ON tab(c1) ; SHOW CREATE TABLE tab; Table Create Table tab CREATE TABLE `tab` ( `c1` point NOT NULL, SPATIAL KEY `idx1` (`c1`), - CONSTRAINT `tab_const` CHECK (`c1` > 0) + CONSTRAINT `tab_const` CHECK (cast(`c1` as char charset binary) > 0) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 SHOW INDEX FROM tab; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment diff --git a/mysql-test/suite/innodb_gis/r/gis.result b/mysql-test/suite/innodb_gis/r/gis.result index fed7592f42b..146216b71b3 100644 --- a/mysql-test/suite/innodb_gis/r/gis.result +++ b/mysql-test/suite/innodb_gis/r/gis.result @@ -992,9 +992,7 @@ ST_GEOMFROMTEXT( 'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))')); # must not crash SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); -1 -Warnings: -Warning 1292 Truncated incorrect DOUBLE value: '\x00\x00\x00\x00\x01\x06\x00\x00\x00\x01\x00\x00\x00\x01\x03\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' +ERROR HY000: Illegal parameter data types int and geometry for operation '<>' DROP TABLE t1; # # Bug #49250 : spatial btree index corruption and crash @@ -1106,11 +1104,7 @@ FLUSH TABLES; SELECT 1 FROM g1 FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month) ; -1 -Warnings: -Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\xF0?' -Warning 1441 Datetime function: datetime field overflow -Warning 1292 Incorrect datetime value: '\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xF0?\x00\x00\x00\x00\x00\x00\x00@' +ERROR HY000: Illegal parameter data types geometry and datetime for operation '=' DROP TABLE g1; # # Bug#13013970 MORE CRASHES IN FIELD_BLOB::GET_KEY_IMAGE diff --git a/mysql-test/suite/innodb_gis/t/1.test b/mysql-test/suite/innodb_gis/t/1.test index 110a8acc18f..1af035f457d 100644 --- a/mysql-test/suite/innodb_gis/t/1.test +++ b/mysql-test/suite/innodb_gis/t/1.test @@ -701,6 +701,7 @@ INSERT INTO t1 VALUES 'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))')); --echo # must not crash +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); DROP TABLE t1; @@ -886,6 +887,7 @@ INSERT INTO g1 VALUES (ST_geomfromtext('point(1 2)')); FLUSH TABLES; +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT 1 FROM g1 FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month) ; diff --git a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test index efd6cb6c867..a6cc6994c93 100644 --- a/mysql-test/suite/innodb_gis/t/alter_spatial_index.test +++ b/mysql-test/suite/innodb_gis/t/alter_spatial_index.test @@ -304,8 +304,11 @@ ALTER TABLE tab DROP INDEX idx2; # Check spatial index on temp tables +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab where c1 = c2; +CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab; + INSERT INTO temp_tab SELECT * FROM tab; CREATE SPATIAL INDEX idx2 ON temp_tab(c2); diff --git a/mysql-test/suite/innodb_gis/t/create_spatial_index.test b/mysql-test/suite/innodb_gis/t/create_spatial_index.test index d25a2e79793..f8626b3c052 100644 --- a/mysql-test/suite/innodb_gis/t/create_spatial_index.test +++ b/mysql-test/suite/innodb_gis/t/create_spatial_index.test @@ -1118,7 +1118,9 @@ DROP TABLE tab; # End of Testcase compress table with Auto_increment # Test check constraint on spatial column +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB; +CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(CAST(c1 AS BINARY) > 0) ) ENGINE=InnoDB; CREATE SPATIAL INDEX idx1 ON tab(c1) ; diff --git a/mysql-test/suite/innodb_gis/t/gis.test b/mysql-test/suite/innodb_gis/t/gis.test index f28809f393c..1e34f6e6499 100644 --- a/mysql-test/suite/innodb_gis/t/gis.test +++ b/mysql-test/suite/innodb_gis/t/gis.test @@ -695,6 +695,7 @@ INSERT INTO t1 VALUES 'multipolygon(((1 2,3 4,5 6,7 8,9 8,1 2,1 2),(7 6,5 4,3 2,1 2,3 4,7 6)))')); --echo # must not crash +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT 1 FROM t1 WHERE a <> (SELECT ST_GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); DROP TABLE t1; @@ -888,6 +889,7 @@ INSERT INTO g1 VALUES (ST_geomfromtext('point(1 2)')); FLUSH TABLES; +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT 1 FROM g1 FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month) ; diff --git a/mysql-test/t/bug13633383.test b/mysql-test/t/bug13633383.test index e31d4a8c9f6..29106d379fe 100644 --- a/mysql-test/t/bug13633383.test +++ b/mysql-test/t/bug13633383.test @@ -67,6 +67,7 @@ INSERT INTO t3 VALUES (4294967296,'2011-04-12 21:05:37',0x0000CE3238,'xwcplgaxcp --enable_query_log set session sort_buffer_size= 32768; +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION select col435 from t3 natural right outer join t1 diff --git a/mysql-test/t/gis-debug.test b/mysql-test/t/gis-debug.test index 4b36a8e20e0..a34dd622312 100644 --- a/mysql-test/t/gis-debug.test +++ b/mysql-test/t/gis-debug.test @@ -20,3 +20,29 @@ CREATE TABLE t1 (a INT DEFAULT ST_GIS_DEBUG(1)); --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # Start of 10.3 tests +--echo # + +--echo # +--echo # Comparison data type aggregation for pluggable data types +--echo # + +SET SESSION debug_dbug="+d,Item_func_in"; +SET SESSION debug_dbug="+d,Predicant_to_list_comparator"; + +CREATE TABLE t1 (a POINT); +INSERT INTO t1 VALUES (POINT(1,1)),(POINT(1,2)),(POINT(1,3)); +SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30)); +SELECT COUNT(*) FROM t1 WHERE a IN (POINT(1,1),POINT(10,20),POINT(10,30),'test'); +SELECT COUNT(*) FROM t1 WHERE a IN ('test','test1'); +DROP TABLE t1; + +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES ('test'),('test1'),('test2'); +SELECT * FROM t1 WHERE a IN ('test',POINT(1,1)); +DROP TABLE t1; + +SET SESSION debug_dbug="-d,Predicant_to_list_comparator"; +SET SESSION debug_dbug="-d,Item_func_in"; diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 282005da624..7a1ddb46b21 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -669,6 +669,7 @@ INSERT INTO t1 VALUES 'multipolygon(((1 2,3 4,5 6,7 8,9 8),(7 6,5 4,3 2,1 2,3 4)))')); --echo # must not crash +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); DROP TABLE t1; @@ -1395,6 +1396,7 @@ INSERT INTO g1 VALUES (geomfromtext('point(1 2)')); FLUSH TABLES; +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT 1 FROM g1 FORCE INDEX(i) WHERE a = date_sub(now(), interval 2808.4 year_month) ; @@ -1799,6 +1801,73 @@ DROP PROCEDURE p1; DROP PROCEDURE p2; +--echo # +--echo # MDEV-11692 Comparison data type aggregation for pluggable data types +--echo # + +DELIMITER $$; +CREATE PROCEDURE p2(query TEXT) +BEGIN + DECLARE errcount INT DEFAULT 0; + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + SET errcount = errcount+1; + GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT; + SELECT @p AS `ERROR: `; + END; + SELECT query AS ``; + EXECUTE IMMEDIATE query; +END; +$$ +CREATE PROCEDURE p1(query TEXT) +BEGIN + SELECT query AS `-------------------------------------`; + EXECUTE IMMEDIATE query; + CALL p2('SELECT a=b FROM t1'); + CALL p2('SELECT b=a FROM t1'); + CALL p2('SELECT a BETWEEN b AND c FROM t1'); + CALL p2('SELECT a IN (b,c) FROM t1'); + CALL p2('SELECT CASE a WHEN b THEN "a" WHEN c THEN "b" END FROM t1'); + CALL p2('SELECT a=POINT(1,1) FROM t1'); + CALL p2('SELECT POINT(1,1)=a FROM t1'); + CALL p2('SELECT a BETWEEN POINT(1,1) AND POINT(1,2) FROM t1'); + CALL p2('SELECT a IN (POINT(1,1),POINT(1,2)) FROM t1'); + CALL p2('SELECT CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END FROM t1'); + DROP TABLE t1; +END; +$$ +DELIMITER ;$$ + +CALL p1('CREATE TABLE t1 (a CHAR(10), b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a VARCHAR(10), b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a TINYTEXT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a TEXT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a MEDIUMTEXT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a LONGTEXT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a ENUM("a","b"), b Point, c Point)'); + +CALL p1('CREATE TABLE t1 (a TINYINT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a SMALLINT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a MEDIUMINT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a INT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a BIGINT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a FLOAT, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a DOUBLE, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a DECIMAL(10,2), b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a BIT(8), b Point, c Point)'); + +CALL p1('CREATE TABLE t1 (a TIME, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a DATE, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a DATETIME, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a TIMESTAMP, b Point, c Point)'); +CALL p1('CREATE TABLE t1 (a YEAR, b Point, c Point)'); + +CALL p1('CREATE TABLE t1 (a Point, b Point, c Point)'); + + +DROP PROCEDURE p1; +DROP PROCEDURE p2; + --echo # --echo # End of 10.3 tests --echo # diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index d3161c9338c..608c8812e01 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -2422,6 +2422,7 @@ ENGINE=myisam PARTITION BY LINEAR KEY () PARTITIONS 2; INSERT INTO t1 VALUES (1,2,'test'), (2,3,'hi'), (4,5,'bye'); +--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION SELECT 1 FROM t1 WHERE b < SOME ( SELECT 1 FROM t1 WHERE a >= 1 GROUP BY b WITH ROLLUP diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fc3f81a2826..43a0c99ea53 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -98,28 +98,26 @@ static int cmp_row_type(Item* item1, Item* item2) /** Aggregates result types from the array of items. - SYNOPSIS: - agg_cmp_type() - type [out] the aggregated type - items array of items to aggregate the type from - nitems number of items in the array + This method aggregates comparison handler from the array of items. + The result handler is used later for comparison of values of these items. - DESCRIPTION - This function aggregates result types from the array of items. Found type - supposed to be used later for comparison of values of these items. - Aggregation itself is performed by the item_cmp_type() function. - @param[out] type the aggregated type - @param items array of items to aggregate the type from - @param nitems number of items in the array + aggregate_for_comparison() + funcname the function or operator name, + for error reporting + items array of items to aggregate the type from + nitems number of items in the array + int_uint_as_dec what to do when comparing INT to UINT: + set the comparison handler to decimal or int. - @retval - 1 type incompatibility has been detected - @retval - 0 otherwise + @retval true type incompatibility has been detected + @retval false otherwise */ -bool Type_handler_hybrid_field_type::aggregate_for_comparison(Item **items, - uint nitems) +bool +Type_handler_hybrid_field_type::aggregate_for_comparison(const char *funcname, + Item **items, + uint nitems, + bool int_uint_as_dec) { uint unsigned_count= items[0]->unsigned_flag; /* @@ -132,8 +130,22 @@ bool Type_handler_hybrid_field_type::aggregate_for_comparison(Item **items, for (uint i= 1 ; i < nitems ; i++) { unsigned_count+= items[i]->unsigned_flag; - aggregate_for_comparison(items[i]->type_handler()-> - type_handler_for_comparison()); + if (aggregate_for_comparison(items[i]->type_handler()-> + type_handler_for_comparison())) + { + /* + For more precise error messages if aggregation failed on the first pair + {items[0],items[1]}, use the name of items[0]->data_handler(). + Otherwise use the name of this->type_handler(), which is already a + result of aggregation for items[0]..items[i-1]. + */ + my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0), + i == 1 ? items[0]->type_handler()->name().ptr() : + type_handler()->name().ptr(), + items[i]->type_handler()->name().ptr(), + funcname); + return true; + } /* When aggregating types of two row expressions we have to check that they have the same cardinality and that each component @@ -148,7 +160,8 @@ bool Type_handler_hybrid_field_type::aggregate_for_comparison(Item **items, If all arguments are of INT type but have different unsigned_flag values, switch to DECIMAL_RESULT. */ - if (cmp_type() == INT_RESULT && + if (int_uint_as_dec && + cmp_type() == INT_RESULT && unsigned_count != nitems && unsigned_count != 0) set_handler(&type_handler_newdecimal); return 0; @@ -471,8 +484,14 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg, set_null= set_null && owner_arg; a= a1; b= a2; - m_compare_handler= Type_handler::get_handler_by_cmp_type(item_cmp_type(*a1, - *a2)); + Item *tmp_args[2]= {*a1, *a2}; + Type_handler_hybrid_field_type tmp; + if (tmp.aggregate_for_comparison(owner_arg->func_name(), tmp_args, 2, false)) + { + DBUG_ASSERT(thd->is_error()); + return 1; + } + m_compare_handler= tmp.type_handler(); return m_compare_handler->set_comparator_func(this); } @@ -2004,8 +2023,12 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; - if (m_comparator.aggregate_for_comparison(args, 3)) + if (m_comparator.aggregate_for_comparison(Item_func_between::func_name(), + args, 3, true)) + { + DBUG_ASSERT(thd->is_error()); return; + } if (m_comparator.cmp_type() == STRING_RESULT && agg_arg_charsets_for_comparison(cmp_collation, args, 3)) @@ -3033,7 +3056,7 @@ bool Item_func_case::prepare_predicant_and_values(THD *thd, uint *found_types) add_predicant(this, (uint) first_expr_num); for (uint i= 0 ; i < ncases / 2; i++) { - if (add_value_skip_null(this, i * 2, &have_null)) + if (add_value_skip_null("case..when", this, i * 2, &have_null)) return true; } all_values_added(&tmp, &type_cnt, &m_found_types); @@ -3727,7 +3750,8 @@ bool Predicant_to_list_comparator::alloc_comparators(THD *thd, uint nargs) } -bool Predicant_to_list_comparator::add_value(Item_args *args, +bool Predicant_to_list_comparator::add_value(const char *funcname, + Item_args *args, uint value_index) { DBUG_ASSERT(m_predicant_index < args->argument_count()); @@ -3736,8 +3760,11 @@ bool Predicant_to_list_comparator::add_value(Item_args *args, Item *tmpargs[2]; tmpargs[0]= args->arguments()[m_predicant_index]; tmpargs[1]= args->arguments()[value_index]; - if (tmp.aggregate_for_comparison(tmpargs, 2)) + if (tmp.aggregate_for_comparison(funcname, tmpargs, 2, true)) + { + DBUG_ASSERT(current_thd->is_error()); return true; + } m_comparators[m_comparator_count].m_handler= tmp.type_handler(); m_comparators[m_comparator_count].m_arg_index= value_index; m_comparator_count++; @@ -3745,7 +3772,8 @@ bool Predicant_to_list_comparator::add_value(Item_args *args, } -bool Predicant_to_list_comparator::add_value_skip_null(Item_args *args, +bool Predicant_to_list_comparator::add_value_skip_null(const char *funcname, + Item_args *args, uint value_index, bool *nulls_found) { @@ -3760,7 +3788,7 @@ bool Predicant_to_list_comparator::add_value_skip_null(Item_args *args, *nulls_found= true; return false; } - return add_value(args, value_index); + return add_value(funcname, args, value_index); } @@ -4153,7 +4181,7 @@ bool Item_func_in::prepare_predicant_and_values(THD *thd, uint *found_types) add_predicant(this, 0); for (uint i= 1 ; i < arg_count; i++) { - if (add_value_skip_null(this, i, &have_null)) + if (add_value_skip_null(Item_func_in::func_name(), this, i, &have_null)) return true; } all_values_added(&m_comparator, &type_cnt, found_types); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7d15fc0a1c0..6fbbf2ac40f 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1825,19 +1825,21 @@ public: /** Add a new element into m_comparators[], using a {pred,valueN} pair. + @param funcname - the name of the operation, for error reporting @param args - the owner function's argument list @param value_index - the value position in args @retval true - could not add an element because of non-comparable arguments (e.g. ROWs with size) @retval false - a new element was successfully added. */ - bool add_value(Item_args *args, uint value_index); + bool add_value(const char *funcname, Item_args *args, uint value_index); /** Add a new element into m_comparators[], ignoring explicit NULL values. If the value appeared to be an explicit NULL, nulls_found[0] is set to true. */ - bool add_value_skip_null(Item_args *args, uint value_index, + bool add_value_skip_null(const char *funcname, + Item_args *args, uint value_index, bool *nulls_found); /** diff --git a/sql/sql_type.cc b/sql/sql_type.cc index d43dd2c2c59..c5e3408edc7 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -57,6 +57,7 @@ Type_handler_bit type_handler_bit; Type_aggregator type_aggregator_for_result; +Type_aggregator type_aggregator_for_comparison; class Static_data_initializer @@ -81,6 +82,16 @@ public: type_aggregator_for_result.add(&type_handler_geometry, &type_handler_string, &type_handler_long_blob); + + type_aggregator_for_comparison.add(&type_handler_geometry, + &type_handler_geometry, + &type_handler_geometry); + type_aggregator_for_comparison.add(&type_handler_geometry, + &type_handler_null, + &type_handler_geometry); + type_aggregator_for_comparison.add(&type_handler_geometry, + &type_handler_long_blob, + &type_handler_long_blob); #endif } }; @@ -223,6 +234,12 @@ const Name /***************************************************************************/ +const Type_handler *Type_handler_null::type_handler_for_comparison() const +{ + return &type_handler_null; +} + + const Type_handler *Type_handler_int_result::type_handler_for_comparison() const { return &type_handler_longlong; @@ -380,11 +397,23 @@ Type_handler_hybrid_field_type::aggregate_for_result(const char *funcname, is needed after this call. */ -void +bool Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h) { DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison()); DBUG_ASSERT(h == h->type_handler_for_comparison()); + + if (!m_type_handler->is_traditional_type() || + !h->is_traditional_type()) + { + h= type_aggregator_for_comparison.find_handler(m_type_handler, h); + if (!h) + return true; + m_type_handler= h; + DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison()); + return false; + } + Item_result a= cmp_type(); Item_result b= h->cmp_type(); if (a == STRING_RESULT && b == STRING_RESULT) @@ -421,6 +450,7 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h) else m_type_handler= &type_handler_double; DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison()); + return false; } @@ -900,6 +930,13 @@ Field *Type_handler_long_blob::make_conversion_table_field(TABLE *table, #ifdef HAVE_SPATIAL const Name Type_handler_geometry::m_name_geometry(C_STRING_WITH_LEN("geometry")); + +const Type_handler *Type_handler_geometry::type_handler_for_comparison() const +{ + return &type_handler_geometry; +} + + Field *Type_handler_geometry::make_conversion_table_field(TABLE *table, uint metadata, const Field *target) diff --git a/sql/sql_type.h b/sql/sql_type.h index 29e1a2946bb..4515d8c9333 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -1134,6 +1134,7 @@ public: virtual ~Type_handler_null() {} const Name name() const { return m_name_null; } enum_field_types field_type() const { return MYSQL_TYPE_NULL; } + const Type_handler *type_handler_for_comparison() const; uint32 max_display_length(const Item *item) const { return 0; } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; @@ -1220,6 +1221,7 @@ public: virtual ~Type_handler_geometry() {} const Name name() const { return m_name_geometry; } enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } + const Type_handler *type_handler_for_comparison() const; Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; bool is_traditional_type() const @@ -1316,8 +1318,10 @@ public: { return (m_type_handler= Type_handler::get_handler_by_real_type(type)); } - void aggregate_for_comparison(const Type_handler *other); - bool aggregate_for_comparison(Item **items, uint nitems); + bool aggregate_for_comparison(const Type_handler *other); + bool aggregate_for_comparison(const char *funcname, + Item **items, uint nitems, + bool treat_int_to_uint_as_decimal); bool aggregate_for_result(const Type_handler *other); bool aggregate_for_result(const char *funcname, Item **item, uint nitems, bool treat_bit_as_number); @@ -1396,5 +1400,6 @@ public: }; extern Type_aggregator type_aggregator_for_result; +extern Type_aggregator type_aggregator_for_comparison; #endif /* SQL_TYPE_H_INCLUDED */ From 81c1abe8cf3dda1fe097256a06daab3041409e14 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 30 Jan 2017 11:56:23 -0800 Subject: [PATCH 155/167] Fixed bug mdev-10875. Now, after the implementation of mdev-8646 "Re-engineer the code for post-join operations" create_sort_index() can be called for subqueries. --- mysql-test/r/win.result | 16 ++++++++++++++++ mysql-test/t/win.test | 16 ++++++++++++++++ sql/sql_select.cc | 3 --- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index c8c55b91016..1c46f43a22c 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -2382,3 +2382,19 @@ pk c CNT 10 2 0.5000 drop view v1,v2,v3,v4; drop table t0,t1; +# +# MDEV-10875: window function in subquery +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (3),(1); +CREATE TABLE t2 (c VARCHAR(8)); +INSERT INTO t2 VALUES ('foo'),('bar'),('foo'); +SELECT COUNT(*) OVER (PARTITION BY c) FROM t2; +COUNT(*) OVER (PARTITION BY c) +2 +1 +2 +SELECT * FROM t1 WHERE i IN ( SELECT COUNT(*) OVER (PARTITION BY c) FROM t2 ); +i +1 +DROP TABLE t1, t2; diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index 7052368cf9c..b9490c82039 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -1426,3 +1426,19 @@ select * from v4; drop view v1,v2,v3,v4; drop table t0,t1; + +--echo # +--echo # MDEV-10875: window function in subquery +--echo # + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (3),(1); + +CREATE TABLE t2 (c VARCHAR(8)); +INSERT INTO t2 VALUES ('foo'),('bar'),('foo'); + +SELECT COUNT(*) OVER (PARTITION BY c) FROM t2; + +SELECT * FROM t1 WHERE i IN ( SELECT COUNT(*) OVER (PARTITION BY c) FROM t2 ); + +DROP TABLE t1, t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2889e1e1549..0678955883b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -21403,9 +21403,6 @@ create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort) table= tab->table; select= fsort->select; - /* Currently ORDER BY ... LIMIT is not supported in subqueries. */ - DBUG_ASSERT(join->group_list || !join->is_in_subquery()); - table->status=0; // May be wrong if quick_select if (!tab->preread_init_done && tab->preread_init()) From 9073f9fd7da80752c4fcb7c6bed1d51b4853d3ce Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 31 Jan 2017 10:32:59 -0800 Subject: [PATCH 156/167] Fixed bug mdev-9976. This bug happens due to a conflict in the construct window_spec. (win_ref conflicts with the non-reserved key word ROWS). The standard SQL-2003 says that ROWS is a reserved key word. Made this key word reserved in our grammar and removed the conflict. --- mysql-test/r/win.result | 34 ++++++++++++++++++++++++++++++++++ mysql-test/t/win.test | 21 +++++++++++++++++++++ sql/lex.h | 2 +- sql/sql_yacc.yy | 9 ++++----- 4 files changed, 60 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index 1c46f43a22c..0a003b0fe28 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -2398,3 +2398,37 @@ SELECT * FROM t1 WHERE i IN ( SELECT COUNT(*) OVER (PARTITION BY c) FROM t2 ); i 1 DROP TABLE t1, t2; +# +# MDEV-9976: window function without PARTITION BY and ORDER BY +# +CREATE TABLE t1 (id int, a int); +INSERT INTO t1 VALUES +(1,1000), (2,1100), (3,1800), (4,1500), (5,1700), (6,1200), +(7,2000), (8,2100), (9,1600); +SELECT id, sum(a) OVER (PARTITION BY id +ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) +FROM t1; +id sum(a) OVER (PARTITION BY id +1 1000 +2 1100 +3 1800 +4 1500 +5 1700 +6 1200 +7 2000 +8 2100 +9 1600 +ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) +SELECT id, sum(a) OVER (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) +FROM t1; +id sum(a) OVER (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) +1 14000 +2 13000 +3 5900 +4 10700 +5 7600 +6 11900 +7 4100 +8 2100 +9 9200 +DROP TABLE t1; diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index b9490c82039..00fbec7d88d 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -1442,3 +1442,24 @@ SELECT COUNT(*) OVER (PARTITION BY c) FROM t2; SELECT * FROM t1 WHERE i IN ( SELECT COUNT(*) OVER (PARTITION BY c) FROM t2 ); DROP TABLE t1, t2; + +--echo # +--echo # MDEV-9976: window function without PARTITION BY and ORDER BY +--echo # + +CREATE TABLE t1 (id int, a int); +INSERT INTO t1 VALUES + (1,1000), (2,1100), (3,1800), (4,1500), (5,1700), (6,1200), + (7,2000), (8,2100), (9,1600); + +--sorted_result +SELECT id, sum(a) OVER (PARTITION BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) +FROM t1; + +--sorted_result +SELECT id, sum(a) OVER (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) +FROM t1; + +DROP TABLE t1; + diff --git a/sql/lex.h b/sql/lex.h index c40aa8f546d..baeae088234 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -517,8 +517,8 @@ static SYMBOL symbols[] = { { "ROLLUP", SYM(ROLLUP_SYM)}, { "ROUTINE", SYM(ROUTINE_SYM)}, { "ROW", SYM(ROW_SYM)}, - { "ROW_COUNT", SYM(ROW_COUNT_SYM)}, { "ROWS", SYM(ROWS_SYM)}, + { "ROW_COUNT", SYM(ROW_COUNT_SYM)}, { "ROW_FORMAT", SYM(ROW_FORMAT_SYM)}, { "RTREE", SYM(RTREE_SYM)}, { "SAVEPOINT", SYM(SAVEPOINT_SYM)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 74a61425141..0cd2c563319 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1021,10 +1021,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 103 shift/reduce conflicts. + Currently there are 102 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 103 +%expect 102 /* Comments for TOKENS. @@ -1535,10 +1535,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ROLLBACK_SYM /* SQL-2003-R */ %token ROLLUP_SYM /* SQL-2003-R */ %token ROUTINE_SYM /* SQL-2003-N */ -%token ROWS_SYM /* SQL-2003-R */ -%token ROW_FORMAT_SYM %token ROW_SYM /* SQL-2003-R */ +%token ROWS_SYM /* SQL-2003-R */ %token ROW_COUNT_SYM /* SQL-2003-N */ +%token ROW_FORMAT_SYM %token ROW_NUMBER_SYM %token RTREE_SYM %token SAVEPOINT_SYM /* SQL-2003-R */ @@ -14835,7 +14835,6 @@ keyword_sp: | ROLE_SYM {} | ROLLUP_SYM {} | ROUTINE_SYM {} - | ROWS_SYM {} | ROW_COUNT_SYM {} | ROW_FORMAT_SYM {} | ROW_SYM {} From ba8ab6a79c8a25133da194df307ce5d35db1f550 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 31 Jan 2017 16:10:15 -0800 Subject: [PATCH 157/167] Adjusted tests after the fix for bug mdev-9976. Now ROWS is a reserved key word, so cannot be used as an alias name. --- .../suite/parts/r/partition_repair_myisam.result | 12 ++++++------ .../suite/parts/t/partition_repair_myisam.test | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/parts/r/partition_repair_myisam.result b/mysql-test/suite/parts/r/partition_repair_myisam.result index 3652698f634..6e99f1d3632 100644 --- a/mysql-test/suite/parts/r/partition_repair_myisam.result +++ b/mysql-test/suite/parts/r/partition_repair_myisam.result @@ -270,8 +270,8 @@ PARTITIONS 7; SELECT COUNT(*) FROM t1_will_crash; COUNT(*) 33 -SELECT (b % 7) AS `partition`, COUNT(*) AS rows FROM t1_will_crash GROUP BY (b % 7); -partition rows +SELECT (b % 7) AS `partition`, COUNT(*) AS rows_cnt FROM t1_will_crash GROUP BY (b % 7); +partition rows_cnt 0 2 1 5 2 5 @@ -343,8 +343,8 @@ test.t1_will_crash repair status OK SELECT COUNT(*) FROM t1_will_crash; COUNT(*) 29 -SELECT (b % 7) AS `partition`, COUNT(*) AS rows FROM t1_will_crash GROUP BY (b % 7); -partition rows +SELECT (b % 7) AS `partition`, COUNT(*) AS rows_cnt FROM t1_will_crash GROUP BY (b % 7); +partition rows_cnt 1 4 2 5 3 5 @@ -483,8 +483,8 @@ test.t1_will_crash repair status OK SELECT COUNT(*) FROM t1_will_crash; COUNT(*) 29 -SELECT (b % 7) AS `partition`, COUNT(*) AS rows FROM t1_will_crash GROUP BY (b % 7); -partition rows +SELECT (b % 7) AS `partition`, COUNT(*) AS rows_cnt FROM t1_will_crash GROUP BY (b % 7); +partition rows_cnt 1 4 2 4 3 5 diff --git a/mysql-test/suite/parts/t/partition_repair_myisam.test b/mysql-test/suite/parts/t/partition_repair_myisam.test index f7c503a8544..a21493ca03d 100644 --- a/mysql-test/suite/parts/t/partition_repair_myisam.test +++ b/mysql-test/suite/parts/t/partition_repair_myisam.test @@ -190,7 +190,7 @@ eval INSERT INTO t1_will_crash VALUES ('6 row 7 (crash before completely written to datafile)', 27, '$lt$lt'); --enable_query_log SELECT COUNT(*) FROM t1_will_crash; -SELECT (b % 7) AS `partition`, COUNT(*) AS rows FROM t1_will_crash GROUP BY (b % 7); +SELECT (b % 7) AS `partition`, COUNT(*) AS rows_cnt FROM t1_will_crash GROUP BY (b % 7); SELECT (b % 7) AS `partition`, b, a, length(c) FROM t1_will_crash ORDER BY `partition`, b, a; FLUSH TABLES; # testing p0, p1, p3, p6(1) @@ -216,7 +216,7 @@ OPTIMIZE TABLE t1_will_crash; CHECK TABLE t1_will_crash; REPAIR TABLE t1_will_crash; SELECT COUNT(*) FROM t1_will_crash; -SELECT (b % 7) AS `partition`, COUNT(*) AS rows FROM t1_will_crash GROUP BY (b % 7); +SELECT (b % 7) AS `partition`, COUNT(*) AS rows_cnt FROM t1_will_crash GROUP BY (b % 7); SELECT (b % 7) AS `partition`, b, a, length(c) FROM t1_will_crash ORDER BY `partition`, b, a; FLUSH TABLES; @@ -282,7 +282,7 @@ SET @@optimizer_switch=@save_optimizer_switch; ALTER TABLE t1_will_crash CHECK PARTITION p6; ALTER TABLE t1_will_crash REPAIR PARTITION p6; SELECT COUNT(*) FROM t1_will_crash; -SELECT (b % 7) AS `partition`, COUNT(*) AS rows FROM t1_will_crash GROUP BY (b % 7); +SELECT (b % 7) AS `partition`, COUNT(*) AS rows_cnt FROM t1_will_crash GROUP BY (b % 7); SELECT (b % 7) AS `partition`, b, a, length(c) FROM t1_will_crash ORDER BY `partition`, b, a; ALTER TABLE t1_will_crash CHECK PARTITION all EXTENDED; DROP TABLE t1_will_crash; From a5d8dc1818f3d563a08d92b3a680c390ae1b55a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 31 Jan 2017 12:06:52 +0200 Subject: [PATCH 158/167] Make the innochecksum tests more robust. As noted in MDEV-11947, we should disable the InnoDB doublewrite buffer during the tests, because when rewriting page checksums, innochecksum would skip the pages that are in the doublewrite buffer area. Because the doublewrite buffer is emptied on server startup and not shutdown, we should initially start with the doublewrite buffer disabled, so that there will be no warning messages for wrong page checksums in the doublewrite buffer. Also, correct the obvious typo where restart_options should have been $restart_parameters, so that InnoDB is actually verifying that the checksums were rewritten. --- .../suite/innodb_zip/r/innochecksum.result | 3 --- .../suite/innodb_zip/r/innochecksum_3.result | 6 +----- mysql-test/suite/innodb_zip/t/innochecksum.opt | 1 + mysql-test/suite/innodb_zip/t/innochecksum.test | 13 +++++-------- mysql-test/suite/innodb_zip/t/innochecksum_2.opt | 1 + .../suite/innodb_zip/t/innochecksum_2.test | 3 +-- .../suite/innodb_zip/t/innochecksum_3.test | 16 +++++----------- 7 files changed, 14 insertions(+), 29 deletions(-) create mode 100644 mysql-test/suite/innodb_zip/t/innochecksum.opt create mode 100644 mysql-test/suite/innodb_zip/t/innochecksum_2.opt diff --git a/mysql-test/suite/innodb_zip/r/innochecksum.result b/mysql-test/suite/innodb_zip/r/innochecksum.result index d05f93bd5af..ff1bccfb60c 100644 --- a/mysql-test/suite/innodb_zip/r/innochecksum.result +++ b/mysql-test/suite/innodb_zip/r/innochecksum.result @@ -1,7 +1,6 @@ # Set the environmental variables call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); -SET GLOBAL innodb_file_per_table=on; CREATE TABLE tab1(c1 INT PRIMARY KEY,c2 VARCHAR(20)) ENGINE=InnoDB; CREATE INDEX idx1 ON tab1(c2(10)); INSERT INTO tab1 VALUES(1, 'Innochecksum InnoDB1'); @@ -89,6 +88,4 @@ c1 c2 FOUND /Error while setting value \'strict_crc32\' to \'write\'/ in my_restart.err FOUND /Error while setting value \'strict_innodb\' to \'write\'/ in my_restart.err FOUND /Error while setting value \'crc23\' to \'write\'/ in my_restart.err -# Restart the server DROP TABLE tab1; -SET GLOBAL innodb_file_per_table=default; diff --git a/mysql-test/suite/innodb_zip/r/innochecksum_3.result b/mysql-test/suite/innodb_zip/r/innochecksum_3.result index c5c2a7673b3..32e6d3f1d13 100644 --- a/mysql-test/suite/innodb_zip/r/innochecksum_3.result +++ b/mysql-test/suite/innodb_zip/r/innochecksum_3.result @@ -1,6 +1,5 @@ # Set the environmental variables call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); -SET GLOBAL innodb_file_per_table=on; [1]: Further Test are for rewrite checksum (innodb|crc32|none) for all ibd file & start the server. CREATE TABLE tab1 (pk INTEGER NOT NULL PRIMARY KEY, linestring_key GEOMETRY NOT NULL, @@ -221,7 +220,4 @@ NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_resta NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err NOT FOUND /Incorrect unsigned integer value: '18446744073709551616'/ in my_restart.err -# Restart the server -DROP TABLE tab1; -DROP TABLE tab2; -SET GLOBAL innodb_file_per_table=default; +DROP TABLE tab1,tab2; diff --git a/mysql-test/suite/innodb_zip/t/innochecksum.opt b/mysql-test/suite/innodb_zip/t/innochecksum.opt new file mode 100644 index 00000000000..ac26eca328c --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/innochecksum.opt @@ -0,0 +1 @@ +--skip-innodb-doublewrite diff --git a/mysql-test/suite/innodb_zip/t/innochecksum.test b/mysql-test/suite/innodb_zip/t/innochecksum.test index 3ef311ed154..0403251bf64 100644 --- a/mysql-test/suite/innodb_zip/t/innochecksum.test +++ b/mysql-test/suite/innodb_zip/t/innochecksum.test @@ -17,8 +17,6 @@ let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); call mtr.add_suppression("InnoDB: Warning: database page corruption or a failed"); -SET GLOBAL innodb_file_per_table=on; - CREATE TABLE tab1(c1 INT PRIMARY KEY,c2 VARCHAR(20)) ENGINE=InnoDB; CREATE INDEX idx1 ON tab1(c2(10)); INSERT INTO tab1 VALUES(1, 'Innochecksum InnoDB1'); @@ -163,7 +161,7 @@ let SEARCH_PATTERN= Error while setting value \'no\' to \'strict-check\'; --exec $INNOCHECKSUM --strict-check=innodb $MYSQLD_DATADIR/test/tab1.ibd --echo # start the server with innodb_checksum_algorithm=InnoDB ---let restart_options= : --innodb_checksum_algorithm=innodb +--let $restart_parameters= --innodb_checksum_algorithm=innodb --source include/start_mysqld.inc INSERT INTO tab1 VALUES(2, 'Innochecksum CRC32'); @@ -181,7 +179,7 @@ SELECT c1,c2 FROM tab1 order by c1,c2; --exec $INNOCHECKSUM --strict-check=none $MYSQLD_DATADIR/test/t1.ibd --echo # Start the server with checksum algorithm=none ---let restart_options= : --innodb_checksum_algorithm=none +--let $restart_parameters= --innodb_checksum_algorithm=none --source include/start_mysqld.inc INSERT INTO tab1 VALUES(3, 'Innochecksum None'); @@ -195,7 +193,7 @@ DROP TABLE t1; --exec $INNOCHECKSUM --no-check --write=crc32 $MYSQLD_DATADIR/test/tab1.ibd --echo # Restart the DB server with innodb_checksum_algorithm=crc32 ---let restart_options= : --innodb_checksum_algorithm=crc32 --innodb_file_per_table=on +--let $restart_parameters= --innodb_checksum_algorithm=crc32 --source include/start_mysqld.inc SELECT * FROM tab1; @@ -209,7 +207,7 @@ SELECT c1,c2 FROM tab1 order by c1,c2; --exec $INNOCHECKSUM --no-check --write=InnoDB $MYSQLD_DATADIR/test/tab1.ibd --echo # Restart the DB server with innodb_checksum_algorithm=InnoDB ---let restart_options= : --innodb_checksum_algorithm=innodb --innodb_file_per_table=on +--let $restart_parameters= --innodb_checksum_algorithm=innodb --source include/start_mysqld.inc DELETE FROM tab1 where c1=2; @@ -236,8 +234,7 @@ let SEARCH_PATTERN=Error while setting value \'crc23\' to \'write\'; --remove_file $SEARCH_FILE # Cleanup ---echo # Restart the server +--let $restart_parameters= --source include/start_mysqld.inc DROP TABLE tab1; -SET GLOBAL innodb_file_per_table=default; diff --git a/mysql-test/suite/innodb_zip/t/innochecksum_2.opt b/mysql-test/suite/innodb_zip/t/innochecksum_2.opt new file mode 100644 index 00000000000..ac26eca328c --- /dev/null +++ b/mysql-test/suite/innodb_zip/t/innochecksum_2.opt @@ -0,0 +1 @@ +--skip-innodb-doublewrite diff --git a/mysql-test/suite/innodb_zip/t/innochecksum_2.test b/mysql-test/suite/innodb_zip/t/innochecksum_2.test index a290a9fc449..7f4ad336805 100644 --- a/mysql-test/suite/innodb_zip/t/innochecksum_2.test +++ b/mysql-test/suite/innodb_zip/t/innochecksum_2.test @@ -4,8 +4,7 @@ --source include/have_innodb.inc --source include/have_innodb_zip.inc --source include/have_debug.inc -# Valgrind would complain about memory leaks when we crash on purpose. ---source include/not_valgrind.inc +--source include/no_valgrind_without_big.inc # Avoid CrashReporter popup on Mac. --source include/not_crashrep.inc diff --git a/mysql-test/suite/innodb_zip/t/innochecksum_3.test b/mysql-test/suite/innodb_zip/t/innochecksum_3.test index 60c4b167d9a..7895510b335 100644 --- a/mysql-test/suite/innodb_zip/t/innochecksum_3.test +++ b/mysql-test/suite/innodb_zip/t/innochecksum_3.test @@ -4,8 +4,7 @@ --source include/have_innodb.inc --source include/have_innodb_zip.inc -# Valgrind would complain about memory leaks when we crash on purpose. ---source include/not_valgrind.inc +--source include/no_valgrind_without_big.inc # Embedded server does not support crashing. --source include/not_embedded.inc @@ -19,8 +18,6 @@ let MYSQLD_DATADIR= `SELECT @@datadir`; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; call mtr.add_suppression("InnoDB: Unable to read tablespace .* page no .* into the buffer pool after 100 attempts"); -SET GLOBAL innodb_file_per_table=on; - --echo [1]: Further Test are for rewrite checksum (innodb|crc32|none) for all ibd file & start the server. CREATE TABLE tab1 (pk INTEGER NOT NULL PRIMARY KEY, @@ -78,7 +75,7 @@ foreach (glob("$ENV{MYSQLD_DATADIR}/*/*.ibd")) { EOF --echo : start the server with innodb_checksum_algorithm=strict_innodb ---let restart_options= : --innodb_checksum_algorithm=strict_innodb --default_storage_engine=InnoDB +--let $restart_parameters= --innodb_checksum_algorithm=strict_innodb --source include/start_mysqld.inc INSERT INTO tab1 (pk, linestring_key, linestring_nokey) @@ -118,7 +115,7 @@ foreach (glob("$ENV{MYSQLD_DATADIR}/*/*.ibd")) { EOF --echo # start the server with innodb_checksum_algorithm=strict_crc32 ---let restart_options= : --innodb_checksum_algorithm=strict_crc32 --default_storage_engine=InnoDB +--let $restart_parameters= --innodb_checksum_algorithm=strict_crc32 --source include/start_mysqld.inc # check the table status is GOOD with DML @@ -163,7 +160,7 @@ foreach (glob("$ENV{MYSQLD_DATADIR}/*/*.ibd")) { } EOF ---let $restart_parameters = --innodb_checksum_algorithm=strict_none --default_storage_engine=InnoDB +--let $restart_parameters= --innodb_checksum_algorithm=strict_none --source include/start_mysqld.inc --let $restart_parameters= # check the table status is GOOD with DML @@ -403,9 +400,6 @@ let SEARCH_PATTERN= Incorrect unsigned integer value: '18446744073709551616'; --remove_file $SEARCH_FILE # Cleanup ---echo # Restart the server --source include/start_mysqld.inc -DROP TABLE tab1; -DROP TABLE tab2; -SET GLOBAL innodb_file_per_table=default; +DROP TABLE tab1,tab2; From 16bc16f9bab44d9aea2dc2edce375d41b9ea519a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 31 Jan 2017 14:12:14 +0200 Subject: [PATCH 159/167] Actually invoke free() in ut_allocator::deallocate(). The necessary call was inadvertently commented out in a merge of MySQL 5.7.14 to MariaDB 10.2.1 (commit fec844aca88e1c6b9c36bb0b811e92d9d023ffb9). --- storage/innobase/include/ut0new.h | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index 6f3c06cf978..5a9022e8a77 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -389,25 +390,21 @@ public: } /** Free a memory allocated by allocate() and trace the deallocation. - @param[in,out] ptr pointer to memory to free - @param[in] n_elements number of elements allocated (unused) */ - void - deallocate( - pointer ptr, - size_type n_elements = 0) + @param[in,out] ptr pointer to memory to free */ + void deallocate(pointer ptr, size_type) { +#ifdef UNIV_PFS_MEMORY if (ptr == NULL) { return; } -#ifdef UNIV_PFS_MEMORY ut_new_pfx_t* pfx = reinterpret_cast(ptr) - 1; deallocate_trace(pfx); free(pfx); #else - // free(ptr); + free(ptr); #endif /* UNIV_PFS_MEMORY */ } From 774056c825c4e2496730eb4821170d15d54ce14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 31 Jan 2017 14:20:40 +0200 Subject: [PATCH 160/167] MDEV-11671 Duplicated message for innodb_page_size Display a NOTE, not a WARNING for non-default page size. --- storage/innobase/handler/ha_innodb.cc | 28 ++++++++++----------------- 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7edc1fdd687..d5ee8f1f82e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3965,21 +3965,15 @@ innobase_init( any functions that could possibly allocate memory. */ ut_new_boot(); - if (UNIV_PAGE_SIZE != UNIV_PAGE_SIZE_DEF) { - ib::info() << "innodb_page_size has been " - << "changed from default value " - << UNIV_PAGE_SIZE_DEF << " to " << UNIV_PAGE_SIZE; - - /* There is hang on buffer pool when trying to get a new - page if buffer pool size is too small for large page sizes */ - if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF - && innobase_buffer_pool_size < (24 * 1024 * 1024)) { - ib::info() << "innodb_page_size=" - << UNIV_PAGE_SIZE << " requires " - << "innodb_buffer_pool_size > 24M current " - << innobase_buffer_pool_size; - goto error; - } + /* The buffer pool needs to be able to accommodate enough many + pages, even for larger pages */ + if (UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF + && innobase_buffer_pool_size < (24 * 1024 * 1024)) { + ib::info() << "innodb_page_size=" + << UNIV_PAGE_SIZE << " requires " + << "innodb_buffer_pool_size > 24M current " + << innobase_buffer_pool_size; + goto error; } #ifndef HAVE_LZ4 @@ -4296,9 +4290,7 @@ innobase_change_buffering_inited_ok: srv_log_file_size = (ib_uint64_t) innobase_log_file_size; if (UNIV_PAGE_SIZE_DEF != srv_page_size) { - ib::warn() << "innodb-page-size has been changed from the" - " default value " << UNIV_PAGE_SIZE_DEF << " to " - << srv_page_size << "."; + ib::info() << "innodb_page_size=" << srv_page_size; } if (srv_log_write_ahead_size > srv_page_size) { From 81b7fe9d383bdf68a622b95384f067ed68ba342c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 31 Jan 2017 19:43:03 +0200 Subject: [PATCH 161/167] Shut down InnoDB after aborted startup. This fixes memory leaks in tests that cause InnoDB startup to fail. buf_pool_free_instance(): Also free buf_pool->flush_rbt, which would normally be freed when crash recovery finishes. fil_node_close_file(), fil_space_free_low(), fil_close_all_files(): Relax some debug assertions to tolerate !srv_was_started. innodb_shutdown(): Renamed from innobase_shutdown_for_mysql(). Changed the return type to void. Do not assume that all subsystems were started. que_init(), que_close(): Remove (empty functions). srv_init(), srv_general_init(): Remove as global functions. srv_free(): Allow srv_sys=NULL. srv_get_active_thread_type(): Only return SRV_PURGE if purge really is running. srv_shutdown_all_bg_threads(): Do not reset srv_start_state. It will be needed by innodb_shutdown(). innobase_start_or_create_for_mysql(): Always call srv_boot() so that innodb_shutdown() can assume that it was called. Make more subsystems dependent on SRV_START_STATE_STAT. srv_shutdown_bg_undo_sources(): Require SRV_START_STATE_STAT. trx_sys_close(): Do not assume purge_sys!=NULL. Do not call buf_dblwr_free(), because the doublewrite buffer can exist while the transaction system does not. logs_empty_and_mark_files_at_shutdown(): Do a faster shutdown if !srv_was_started. recv_sys_close(): Invoke dblwr.pages.clear() which would normally be invoked by buf_dblwr_process(). recv_recovery_from_checkpoint_start(): Always release log_sys->mutex. row_mysql_close(): Allow the subsystem not to exist. --- storage/innobase/buf/buf0buf.cc | 5 + storage/innobase/fil/fil0fil.cc | 8 +- storage/innobase/handler/ha_innodb.cc | 6 +- storage/innobase/include/que0que.h | 13 +-- storage/innobase/include/srv0srv.h | 11 -- storage/innobase/include/srv0start.h | 8 +- storage/innobase/log/log0log.cc | 29 +++--- storage/innobase/log/log0recv.cc | 3 + storage/innobase/que/que0que.cc | 19 +--- storage/innobase/row/row0mysql.cc | 8 +- storage/innobase/srv/srv0srv.cc | 42 +++----- storage/innobase/srv/srv0start.cc | 143 +++++++++++++++----------- storage/innobase/trx/trx0sys.cc | 13 +-- 13 files changed, 146 insertions(+), 162 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 0f1d170b172..90ddf473232 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2000,6 +2000,11 @@ buf_pool_free_instance( mutex_free(&buf_pool->zip_mutex); mutex_free(&buf_pool->flush_list_mutex); + if (buf_pool->flush_rbt) { + rbt_free(buf_pool->flush_rbt); + buf_pool->flush_rbt = NULL; + } + for (bpage = UT_LIST_GET_LAST(buf_pool->LRU); bpage != NULL; bpage = prev_bpage) { diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 18252b64a78..81ee2b5f53a 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -779,7 +779,8 @@ fil_node_close_file( ut_a(!node->being_extended); ut_a(node->modification_counter == node->flush_counter || node->space->purpose == FIL_TYPE_TEMPORARY - || srv_fast_shutdown == 2); + || srv_fast_shutdown == 2 + || !srv_was_started); ret = os_file_close(node->handle); ut_a(ret); @@ -1450,7 +1451,8 @@ fil_space_free_low( fil_space_t* space) { /* The tablespace must not be in fil_system->named_spaces. */ - ut_ad(srv_fast_shutdown == 2 || space->max_lsn == 0); + ut_ad(srv_fast_shutdown == 2 || !srv_was_started + || space->max_lsn == 0); for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain); node != NULL; ) { @@ -2059,6 +2061,7 @@ fil_close_all_files(void) /* At shutdown, we should not have any files in this list. */ ut_ad(srv_fast_shutdown == 2 + || !srv_was_started || UT_LIST_GET_LEN(fil_system->named_spaces) == 0); mutex_enter(&fil_system->mutex); @@ -2085,6 +2088,7 @@ fil_close_all_files(void) mutex_exit(&fil_system->mutex); ut_ad(srv_fast_shutdown == 2 + || !srv_was_started || UT_LIST_GET_LEN(fil_system->named_spaces) == 0); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d5ee8f1f82e..b353be635f5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4476,6 +4476,7 @@ innobase_change_buffering_inited_ok: } if (err != DB_SUCCESS) { + innodb_shutdown(); DBUG_RETURN(innobase_init_abort()); } else if (!srv_read_only_mode) { mysql_thread_create(thd_destructor_thread_key, @@ -4594,10 +4595,7 @@ innobase_end( mysql_cond_broadcast(thd_destructor_myvar->current_cond); } - if (innobase_shutdown_for_mysql() != DB_SUCCESS) { - err = 1; - } - + innodb_shutdown(); innobase_space_shutdown(); if (!srv_read_only_mode) { pthread_join(thd_destructor_thread, NULL); diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h index 3e90e0b25e3..574b7e6acee 100644 --- a/storage/innobase/include/que0que.h +++ b/storage/innobase/include/que0que.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -315,18 +316,6 @@ que_fork_scheduler_round_robin( que_fork_t* fork, /*!< in: a query fork */ que_thr_t* thr); /*!< in: current pos */ -/*********************************************************************//** -Initialise the query sub-system. */ -void -que_init(void); -/*==========*/ - -/*********************************************************************//** -Close the query sub-system. */ -void -que_close(void); -/*===========*/ - /** Query thread states */ enum que_thr_state_t { QUE_THR_RUNNING, diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index b22487ca1ef..fee6ceaca4c 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -729,22 +729,11 @@ void srv_boot(void); /*==========*/ /*********************************************************************//** -Initializes the server. */ -void -srv_init(void); -/*==========*/ -/*********************************************************************//** Frees the data structures created in srv_init(). */ void srv_free(void); /*==========*/ /*********************************************************************//** -Initializes the synchronization primitives, memory system, and the thread -local storage. */ -void -srv_general_init(void); -/*==================*/ -/*********************************************************************//** Sets the info describing an i/o thread current state. */ void srv_set_io_thread_op_info( diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index d456806b86b..8de9e3457fc 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -67,11 +67,9 @@ are not found and the user wants. dberr_t innobase_start_or_create_for_mysql(void); /*====================================*/ -/****************************************************************//** -Shuts down the Innobase database. -@return DB_SUCCESS or error code */ -dberr_t -innobase_shutdown_for_mysql(void); +/** Shut down InnoDB. */ +void +innodb_shutdown(); /****************************************************************//** Shuts down background threads that can generate undo pages. */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 95e64784718..3c92e9572df 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2097,7 +2097,6 @@ logs_empty_and_mark_files_at_shutdown(void) { lsn_t lsn; ulint count = 0; - ulint total_trx; ulint pending_io; ib::info() << "Starting shutdown..."; @@ -2120,7 +2119,11 @@ loop: os_event_set(srv_monitor_event); os_event_set(srv_buf_dump_event); os_event_set(lock_sys->timeout_event); - os_event_set(dict_stats_event); + if (dict_stats_event) { + os_event_set(dict_stats_event); + } else { + ut_ad(!srv_dict_stats_thread_active); + } } os_thread_sleep(100000); @@ -2131,9 +2134,8 @@ loop: shutdown, because the InnoDB layer may have committed or prepared transactions and we don't want to lose them. */ - total_trx = trx_sys_any_active_transactions(); - - if (total_trx > 0) { + if (ulint total_trx = srv_was_started + ? trx_sys_any_active_transactions() : 0) { if (srv_print_verbose_log && count > 600) { ib::info() << "Waiting for " << total_trx << " active" @@ -2253,8 +2255,8 @@ wait_suspend_loop: goto loop; } - if (srv_fast_shutdown == 2) { - if (!srv_read_only_mode) { + if (srv_fast_shutdown == 2 || !srv_was_started) { + if (!srv_read_only_mode && srv_was_started) { ib::info() << "MySQL has requested a very fast" " shutdown without flushing the InnoDB buffer" " pool to data files. At the next mysqld" @@ -2318,8 +2320,7 @@ wait_suspend_loop: srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE; /* Make some checks that the server really is quiet */ - srv_thread_type type = srv_get_active_thread_type(); - ut_a(type == SRV_NONE); + ut_a(srv_get_active_thread_type() == SRV_NONE); bool freed = buf_all_freed(); ut_a(freed); @@ -2327,9 +2328,8 @@ wait_suspend_loop: ut_a(lsn == log_sys->lsn); if (lsn < srv_start_lsn) { - ib::error() << "Log sequence number at shutdown " << lsn - << " is lower than at startup " << srv_start_lsn - << "!"; + ib::error() << "Shutdown LSN=" << lsn + << " is less than start LSN=" << srv_start_lsn; } srv_shutdown_lsn = lsn; @@ -2339,15 +2339,14 @@ wait_suspend_loop: if (err != DB_SUCCESS) { ib::error() << "Writing flushed lsn " << lsn - << " failed at shutdown error " << err; + << " failed; error=" << err; } } fil_close_all_files(); /* Make some checks that the server really is quiet */ - type = srv_get_active_thread_type(); - ut_a(type == SRV_NONE); + ut_a(srv_get_active_thread_type() == SRV_NONE); freed = buf_all_freed(); ut_a(freed); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index dc44ae3505d..78566d060cb 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -455,6 +455,8 @@ recv_sys_close(void) /*================*/ { if (recv_sys != NULL) { + recv_sys->dblwr.pages.clear(); + if (recv_sys->addr_hash != NULL) { hash_table_free(recv_sys->addr_hash); } @@ -3263,6 +3265,7 @@ recv_recovery_from_checkpoint_start( ut_ad(!recv_sys->found_corrupt_fs); if (srv_read_only_mode && recv_needed_recovery) { + log_mutex_exit(); return(DB_READ_ONLY); } diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc index 8d3e8cfa115..9fd12686f57 100644 --- a/storage/innobase/que/que0que.cc +++ b/storage/innobase/que/que0que.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -1248,21 +1249,3 @@ que_eval_sql( DBUG_RETURN(trx->error_state); } - -/*********************************************************************//** -Initialise the query sub-system. */ -void -que_init(void) -/*==========*/ -{ - /* No op */ -} - -/*********************************************************************//** -Close the query sub-system. */ -void -que_close(void) -/*===========*/ -{ - /* No op */ -} diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 9356f25bcb0..fbf49d8d3a0 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -5233,7 +5234,8 @@ row_mysql_close(void) { ut_a(UT_LIST_GET_LEN(row_mysql_drop_list) == 0); - mutex_free(&row_drop_list_mutex); - - row_mysql_drop_list_inited = FALSE; + if (row_mysql_drop_list_inited) { + mutex_free(&row_drop_list_mutex); + row_mysql_drop_list_inited = FALSE; + } } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index c2cf71a2f98..0fd5ff7afaf 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1007,11 +1007,10 @@ srv_free_slot( srv_sys_mutex_exit(); } -/*********************************************************************//** -Initializes the server. */ +/** Initialize the server. */ +static void -srv_init(void) -/*==========*/ +srv_init() { ulint n_sys_threads = 0; ulint srv_sys_sz = sizeof(*srv_sys); @@ -1097,6 +1096,10 @@ void srv_free(void) /*==========*/ { + if (!srv_sys) { + return; + } + mutex_free(&srv_innodb_monitor_mutex); mutex_free(&page_zip_stat_per_index_mutex); @@ -1130,22 +1133,6 @@ srv_free(void) srv_sys = 0; } -/*********************************************************************//** -Initializes the synchronization primitives, memory system, and the thread -local storage. */ -void -srv_general_init(void) -/*==================*/ -{ - sync_check_init(); - /* Reset the system variables in the recovery module. */ - recv_sys_var_init(); - os_thread_init(); - trx_pool_init(); - que_init(); - row_mysql_init(); -} - /*********************************************************************//** Normalizes init parameter values to use units we use inside InnoDB. */ static @@ -1175,10 +1162,12 @@ srv_boot(void) srv_normalize_init_values(); - /* Initialize synchronization primitives, memory management, and thread - local storage */ - - srv_general_init(); + sync_check_init(); + os_thread_init(); + /* Reset the system variables in the recovery module. */ + recv_sys_var_init(); + trx_pool_init(); + row_mysql_init(); /* Initialize this module */ @@ -2013,14 +2002,15 @@ srv_get_active_thread_type(void) srv_sys_mutex_exit(); - if (ret == SRV_NONE && srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (ret == SRV_NONE && srv_shutdown_state != SRV_SHUTDOWN_NONE + && purge_sys != NULL) { /* Check only on shutdown. */ switch (trx_purge_state()) { - case PURGE_STATE_INIT: case PURGE_STATE_RUN: case PURGE_STATE_STOP: ret = SRV_PURGE; break; + case PURGE_STATE_INIT: case PURGE_STATE_DISABLED: case PURGE_STATE_EXIT: break; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 408501f6f0d..1d17bff4782 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1281,7 +1281,6 @@ srv_shutdown_all_bg_threads() os_thread_sleep(100000); if (!active) { - srv_start_state = SRV_START_STATE_NONE; return; } } @@ -1419,7 +1418,7 @@ innobase_start_or_create_for_mysql(void) { bool create_new_db = false; lsn_t flushed_lsn; - dberr_t err; + dberr_t err = DB_SUCCESS; ulint srv_n_log_files_found = srv_n_log_files; mtr_t mtr; purge_pq_t* purge_queue; @@ -1566,7 +1565,7 @@ innobase_start_or_create_for_mysql(void) ib::error() << "Unrecognized value " << srv_file_flush_method_str << " for innodb_flush_method"; - return(srv_init_abort(DB_ERROR)); + err = DB_ERROR; } /* Note that the call srv_boot() also changes the values of @@ -1661,6 +1660,10 @@ innobase_start_or_create_for_mysql(void) srv_boot(); + if (err != DB_SUCCESS) { + return(srv_init_abort(err)); + } + ib::info() << ut_crc32_implementation; if (!srv_read_only_mode) { @@ -2589,23 +2592,6 @@ files_checked: << srv_force_recovery << " !!!"; } - if (!srv_read_only_mode) { - /* Create thread(s) that handles key rotation. This is - needed already here as log_preflush_pool_modified_pages - will flush dirty pages and that might need e.g. - fil_crypt_threads_event. */ - fil_system_enter(); - fil_crypt_threads_init(); - fil_system_exit(); - - /* - Create a checkpoint before logging anything new, so that - the current encryption key in use is definitely logged - before any log blocks encrypted with that key. - */ - log_make_checkpoint_at(LSN_MAX, TRUE); - } - if (srv_force_recovery == 0) { /* In the insert buffer we may have even bigger tablespace id's, because we may have dropped those tablespaces, but @@ -2641,6 +2627,21 @@ files_checked: } #endif /* WITH_WSREP */ + /* Create thread(s) that handles key rotation. This is + needed already here as log_preflush_pool_modified_pages + will flush dirty pages and that might need e.g. + fil_crypt_threads_event. */ + fil_system_enter(); + fil_crypt_threads_init(); + fil_system_exit(); + + /* + Create a checkpoint before logging anything new, so that + the current encryption key in use is definitely logged + before any log blocks encrypted with that key. + */ + log_make_checkpoint_at(LSN_MAX, TRUE); + /* Create the dict stats gathering thread */ dict_stats_thread_handle = os_thread_create( dict_stats_thread, NULL, NULL); @@ -2650,6 +2651,12 @@ files_checked: /* Create the thread that will optimize the FTS sub-system. */ fts_optimize_init(); + /* Init data for datafile scrub threads */ + btr_scrub_init(); + + /* Initialize online defragmentation. */ + btr_defragment_init(); + srv_start_state_set(SRV_START_STATE_STAT); } @@ -2657,12 +2664,6 @@ files_checked: srv_buf_resize_thread_active = true; os_thread_create(buf_resize_thread, NULL, NULL); - /* Init data for datafile scrub threads */ - btr_scrub_init(); - - /* Initialize online defragmentation. */ - btr_defragment_init(); - srv_was_started = TRUE; return(DB_SUCCESS); } @@ -2703,27 +2704,18 @@ void srv_shutdown_bg_undo_sources(void) /*===========================*/ { - fts_optimize_shutdown(); - dict_stats_shutdown(); + if (srv_start_state_is_set(SRV_START_STATE_STAT)) { + ut_ad(!srv_read_only_mode); + fts_optimize_shutdown(); + dict_stats_shutdown(); + } } -/****************************************************************//** -Shuts down the InnoDB database. -@return DB_SUCCESS or error code */ -dberr_t -innobase_shutdown_for_mysql(void) -/*=============================*/ +/** Shut down InnoDB. */ +void +innodb_shutdown() { - if (!srv_was_started) { - if (srv_is_being_started) { - ib::warn() << "Shutting down an improperly started," - " or created database!"; - } - - return(DB_SUCCESS); - } - - if (!srv_read_only_mode && srv_fast_shutdown) { + if (srv_fast_shutdown) { srv_shutdown_bg_undo_sources(); } @@ -2762,23 +2754,51 @@ innobase_shutdown_for_mysql(void) srv_misc_tmpfile = 0; } - if (!srv_read_only_mode) { + ut_ad(dict_stats_event || !srv_was_started || srv_read_only_mode); + ut_ad(dict_sys || !srv_was_started); + ut_ad(trx_sys || !srv_was_started); + ut_ad(buf_dblwr || !srv_was_started); + ut_ad(lock_sys || !srv_was_started); + ut_ad(btr_search_sys || !srv_was_started); + ut_ad(ibuf || !srv_was_started); + ut_ad(log_sys || !srv_was_started); + + if (dict_stats_event) { dict_stats_thread_deinit(); - fil_crypt_threads_cleanup(); } - /* Cleanup data for datafile scrubbing */ - btr_scrub_cleanup(); + if (srv_start_state_is_set(SRV_START_STATE_STAT)) { + ut_ad(!srv_read_only_mode); + /* srv_shutdown_bg_undo_sources() already invoked + fts_optimize_shutdown(); dict_stats_shutdown(); */ + + fil_crypt_threads_cleanup(); + btr_scrub_cleanup(); + /* FIXME: call btr_defragment_shutdown(); */ + } /* This must be disabled before closing the buffer pool and closing the data dictionary. */ - btr_search_disable(true); - ibuf_close(); - log_shutdown(); - trx_sys_file_format_close(); - trx_sys_close(); - lock_sys_close(); + if (dict_sys) { + btr_search_disable(true); + } + if (ibuf) { + ibuf_close(); + } + if (log_sys) { + log_shutdown(); + } + if (trx_sys) { + trx_sys_file_format_close(); + trx_sys_close(); + } + if (buf_dblwr) { + buf_dblwr_free(); + } + if (lock_sys) { + lock_sys_close(); + } trx_pool_close(); @@ -2790,13 +2810,17 @@ innobase_shutdown_for_mysql(void) mutex_free(&srv_misc_tmpfile_mutex); } - dict_close(); - btr_search_sys_free(); + if (dict_sys) { + dict_close(); + } + + if (btr_search_sys) { + btr_search_sys_free(); + } /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ os_aio_free(); - que_close(); row_mysql_close(); srv_free(); fil_close(); @@ -2817,15 +2841,14 @@ innobase_shutdown_for_mysql(void) fclose(dict_foreign_err_file); } - if (srv_print_verbose_log) { + if (srv_was_started && srv_print_verbose_log) { ib::info() << "Shutdown completed; log sequence number " << srv_shutdown_lsn; } + srv_start_state = SRV_START_STATE_NONE; srv_was_started = FALSE; srv_start_has_been_called = FALSE; - - return(DB_SUCCESS); } /******************************************************************** diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 724139461d3..bb29fb167b2 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -1086,13 +1086,14 @@ trx_sys_close(void) " shutdown: " << size << " read views open"; } - sess_close(trx_dummy_sess); - trx_dummy_sess = NULL; + if (trx_dummy_sess) { + sess_close(trx_dummy_sess); + trx_dummy_sess = NULL; + } - trx_purge_sys_close(); - - /* Free the double write data structures. */ - buf_dblwr_free(); + if (purge_sys) { + trx_purge_sys_close(); + } /* Only prepared transactions may be left in the system. Free them. */ ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx); From e1977712cce51f3d914e6598869c6f4dee2ff46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 1 Feb 2017 09:28:13 +0200 Subject: [PATCH 162/167] Clean up a test. Import and adapt the changes from MySQL 5.7. --- .../innodb/r/alter_missing_tablespace.result | 34 +++++++++++ .../innodb/r/innodb-alter-discard.result | 28 --------- .../innodb/t/alter_missing_tablespace.test | 58 +++++++++++++++++++ .../suite/innodb/t/innodb-alter-discard.test | 54 ----------------- 4 files changed, 92 insertions(+), 82 deletions(-) create mode 100644 mysql-test/suite/innodb/r/alter_missing_tablespace.result delete mode 100644 mysql-test/suite/innodb/r/innodb-alter-discard.result create mode 100644 mysql-test/suite/innodb/t/alter_missing_tablespace.test delete mode 100644 mysql-test/suite/innodb/t/innodb-alter-discard.test diff --git a/mysql-test/suite/innodb/r/alter_missing_tablespace.result b/mysql-test/suite/innodb/r/alter_missing_tablespace.result new file mode 100644 index 00000000000..1517afd1a39 --- /dev/null +++ b/mysql-test/suite/innodb/r/alter_missing_tablespace.result @@ -0,0 +1,34 @@ +# +# Bug#13955083 ALLOW IN-PLACE DDL OPERATIONS ON MISSING +# OR DISCARDED TABLESPACES +# +SET GLOBAL innodb_file_per_table=1; +CREATE TABLE t(a INT)ENGINE=InnoDB; +CREATE TABLE `x..d` (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +SELECT * FROM t; +ERROR 42S02: Table 'test.t' doesn't exist in engine +ALTER TABLE t ADD INDEX (a), ALGORITHM=INPLACE; +ERROR 42S02: Table 'test.t' doesn't exist in engine +SHOW WARNINGS; +Level Code Message +Warning 1812 Tablespace is missing for table 'test/t' +Error 1932 Table 'test.t' doesn't exist in engine +ALTER TABLE t1 ADD INDEX (a), ALGORITHM=COPY; +ERROR 42S02: Table 'test.t1' doesn't exist +SHOW WARNINGS; +Level Code Message +Error 1146 Table 'test.t1' doesn't exist +ALTER TABLE t ALGORITHM=INPLACE, DISCARD TABLESPACE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DISCARD TABLESPACE' at line 1 +ALTER TABLE t ALGORITHM=COPY, DISCARD TABLESPACE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DISCARD TABLESPACE' at line 1 +ALTER TABLE t ALGORITHM=DEFAULT, DISCARD TABLESPACE; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'DISCARD TABLESPACE' at line 1 +ALTER TABLE t DISCARD TABLESPACE; +Warnings: +Warning 1812 Tablespace is missing for table 'test/t' +Warning 1812 Tablespace is missing for table 'test/t' +DROP TABLE t; +SELECT * FROM `x..d`; +ERROR 42S02: Table 'test.x..d' doesn't exist in engine +DROP TABLE `x..d`; diff --git a/mysql-test/suite/innodb/r/innodb-alter-discard.result b/mysql-test/suite/innodb/r/innodb-alter-discard.result deleted file mode 100644 index 4f773185f3e..00000000000 --- a/mysql-test/suite/innodb/r/innodb-alter-discard.result +++ /dev/null @@ -1,28 +0,0 @@ -call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: .*"); -SET GLOBAL innodb_file_per_table=1; -CREATE TABLE t(a INT)ENGINE=InnoDB; -call mtr.add_suppression("InnoDB: Operating system error number .* in a file operation."); -call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified."); -call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself, InnoDB does not create them."); -call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: './test/t.ibd' OS error: .*"); -call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`t` because it could not be opened."); -call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .*"); -call mtr.add_suppression("InnoDB: Error: trying to open a table, but could not$"); -call mtr.add_suppression("MySQL is trying to open a table handle but the \.ibd file for$"); -call mtr.add_suppression("InnoDB: Table 'test/t'$"); -call mtr.add_suppression("Could not find a valid tablespace file for"); -call mtr.add_suppression("InnoDB: Tablespace open failed for '\"test\"\.\"t\"', ignored"); -call mtr.add_suppression("InnoDB: Failed to find tablespace for table '\"test\"\.\"t\"' in the cache"); -call mtr.add_suppression("InnoDB: Cannot delete tablespace [0-9]+.*not found"); -call mtr.add_suppression("Table .*t in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist"); -SELECT * FROM t; -ERROR 42S02: Table 'test.t' doesn't exist in engine -ALTER TABLE t ADD INDEX (a), ALGORITHM=INPLACE; -ERROR 42S02: Table 'test.t' doesn't exist in engine -ALTER TABLE t1 ADD INDEX (a), ALGORITHM=COPY; -ERROR 42S02: Table 'test.t1' doesn't exist -ALTER TABLE t DISCARD TABLESPACE; -Warnings: -Warning 1812 Tablespace is missing for table 'test/t' -Warning 1812 Tablespace is missing for table 'test/t' -DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/alter_missing_tablespace.test b/mysql-test/suite/innodb/t/alter_missing_tablespace.test new file mode 100644 index 00000000000..643b7a4833d --- /dev/null +++ b/mysql-test/suite/innodb/t/alter_missing_tablespace.test @@ -0,0 +1,58 @@ +--source include/not_embedded.inc +--source include/have_innodb.inc + +--echo # +--echo # Bug#13955083 ALLOW IN-PLACE DDL OPERATIONS ON MISSING +--echo # OR DISCARDED TABLESPACES +--echo # + +--disable_query_log +call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: "); +call mtr.add_suppression("InnoDB: Operating system error number .* in a file operation"); +call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified"); +call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself, InnoDB does not create them"); +call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`\(t\|x\.\.d\)` because it could not be opened"); +call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing"); +call mtr.add_suppression("Could not find a valid tablespace file for"); +call mtr.add_suppression("InnoDB: Failed to find tablespace for table `test`\.`\(t\|x\.\.d\)` in the cache"); +call mtr.add_suppression("InnoDB: Cannot delete tablespace [0-9]+.*not found"); +call mtr.add_suppression("Table .* in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist"); +--enable_query_log + +let $MYSQLD_DATADIR=`select @@datadir`; +SET GLOBAL innodb_file_per_table=1; +CREATE TABLE t(a INT)ENGINE=InnoDB; +CREATE TABLE `x..d` (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; + +--source include/shutdown_mysqld.inc + +# Remove the tablespace files. +--remove_file $MYSQLD_DATADIR/test/t.ibd +--remove_file $MYSQLD_DATADIR/test/x@002e@002ed.ibd + +--source include/start_mysqld.inc + +# The ER_NO_SUCH_TABLE is being thrown by ha_innobase::open(). +# The table does exist, only the tablespace does not exist. +--error ER_NO_SUCH_TABLE_IN_ENGINE +SELECT * FROM t; + +--error ER_NO_SUCH_TABLE_IN_ENGINE +ALTER TABLE t ADD INDEX (a), ALGORITHM=INPLACE; +SHOW WARNINGS; + +--error ER_NO_SUCH_TABLE +ALTER TABLE t1 ADD INDEX (a), ALGORITHM=COPY; +SHOW WARNINGS; + +--error ER_PARSE_ERROR +ALTER TABLE t ALGORITHM=INPLACE, DISCARD TABLESPACE; +--error ER_PARSE_ERROR +ALTER TABLE t ALGORITHM=COPY, DISCARD TABLESPACE; +--error ER_PARSE_ERROR +ALTER TABLE t ALGORITHM=DEFAULT, DISCARD TABLESPACE; +ALTER TABLE t DISCARD TABLESPACE; +DROP TABLE t; +--error ER_NO_SUCH_TABLE_IN_ENGINE +SELECT * FROM `x..d`; +DROP TABLE `x..d`; diff --git a/mysql-test/suite/innodb/t/innodb-alter-discard.test b/mysql-test/suite/innodb/t/innodb-alter-discard.test deleted file mode 100644 index 51faf0d9068..00000000000 --- a/mysql-test/suite/innodb/t/innodb-alter-discard.test +++ /dev/null @@ -1,54 +0,0 @@ -#Bug#13955083 ALLOW IN-PLACE DDL OPERATIONS ON MISSING OR DISCARDED TABLESPACES - ---source include/not_embedded.inc ---source include/have_innodb.inc - -call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: .*"); - -let $MYSQLD_DATADIR=`select @@datadir`; -SET GLOBAL innodb_file_per_table=1; -CREATE TABLE t(a INT)ENGINE=InnoDB; - -# Shut down the server --- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- shutdown_server --- source include/wait_until_disconnected.inc - -# Remove the tablespace file. -let IBD=$MYSQLD_DATADIR/test/t.ibd; -perl; -unlink "$ENV{IBD}" || die "Unable to unlink $ENV{IBD}\n"; -EOF - -# Restart the server. --- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --- enable_reconnect --- source include/wait_until_connected_again.inc - -call mtr.add_suppression("InnoDB: Operating system error number .* in a file operation."); -call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified."); -call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself, InnoDB does not create them."); -call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: './test/t.ibd' OS error: .*"); -call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`t` because it could not be opened."); -call mtr.add_suppression("InnoDB: Cannot calculate statistics for table .* because the .ibd file is missing. Please refer to .*"); -call mtr.add_suppression("InnoDB: Error: trying to open a table, but could not$"); -call mtr.add_suppression("MySQL is trying to open a table handle but the \.ibd file for$"); -call mtr.add_suppression("InnoDB: Table 'test/t'$"); -call mtr.add_suppression("Could not find a valid tablespace file for"); -call mtr.add_suppression("InnoDB: Tablespace open failed for '\"test\"\.\"t\"', ignored"); -call mtr.add_suppression("InnoDB: Failed to find tablespace for table '\"test\"\.\"t\"' in the cache"); -call mtr.add_suppression("InnoDB: Cannot delete tablespace [0-9]+.*not found"); -call mtr.add_suppression("Table .*t in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist"); - -# The ER_NO_SUCH_TABLE is being thrown by ha_innobase::open(). -# The table does exist, only the tablespace does not exist. ---error ER_NO_SUCH_TABLE_IN_ENGINE -SELECT * FROM t; - ---error ER_NO_SUCH_TABLE_IN_ENGINE -ALTER TABLE t ADD INDEX (a), ALGORITHM=INPLACE; ---error ER_NO_SUCH_TABLE -ALTER TABLE t1 ADD INDEX (a), ALGORITHM=COPY; - -ALTER TABLE t DISCARD TABLESPACE; -DROP TABLE t; From 23628d123bd2b0fe48e41c79207835c96e329496 Mon Sep 17 00:00:00 2001 From: Georg Richter Date: Wed, 1 Feb 2017 12:14:37 +0100 Subject: [PATCH 163/167] Fix for MDEV-11174: A GCM encrypted ciphertext must contain an authentication tag with AES_BLOCK_SIZE length, so we need to check that the length of ciphertext is at least AES_BLOCK_SIZE. --- mysys_ssl/my_crypt.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc index 49bd9af3f60..5411a908bf8 100644 --- a/mysys_ssl/my_crypt.cc +++ b/mysys_ssl/my_crypt.cc @@ -168,6 +168,9 @@ public: */ if (!ctx.encrypt) { + /* encrypted string must contain authenticaton tag (see MDEV-11174) */ + if (slen < MY_AES_BLOCK_SIZE) + return MY_AES_BAD_DATA; slen-= MY_AES_BLOCK_SIZE; if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, MY_AES_BLOCK_SIZE, (void*)(src + slen))) From 02a4bbb4128fbea05b503ebec4346c214e8e6c93 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 1 Feb 2017 15:36:22 +0400 Subject: [PATCH 164/167] MDEV-11913 Split sp_get_item_value() into methods in Type_handler This patch also fixes: MDEV-11815 SP variables of temporal data types do not replicate correctly Temporal values are now printed in temporal literal format, with the SQL-standard data type prefix: TIME'10:20:30', DATE'2001-01-01', TIMESTAMP'2001-01-01 10:20:30' Previously temporal values were printed using the text string notation, e.g. _latin1'10:20:30' COLLATE latin1_swedish_ci, hence the bug. --- .../suite/binlog/r/binlog_stm_sp.result | 86 ++++++++++++++ mysql-test/suite/binlog/t/binlog_stm_sp.test | 41 +++++++ mysql-test/suite/rpl/r/rpl_stm_sp.result | 26 +++++ mysql-test/suite/rpl/t/rpl_stm_sp.test | 30 +++++ sql/sp_head.cc | 69 +----------- sql/sql_type.cc | 105 ++++++++++++++++++ sql/sql_type.h | 35 ++++++ 7 files changed, 329 insertions(+), 63 deletions(-) create mode 100644 mysql-test/suite/binlog/r/binlog_stm_sp.result create mode 100644 mysql-test/suite/binlog/t/binlog_stm_sp.test create mode 100644 mysql-test/suite/rpl/r/rpl_stm_sp.result create mode 100644 mysql-test/suite/rpl/t/rpl_stm_sp.test diff --git a/mysql-test/suite/binlog/r/binlog_stm_sp.result b/mysql-test/suite/binlog/r/binlog_stm_sp.result new file mode 100644 index 00000000000..6c470517a93 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_stm_sp.result @@ -0,0 +1,86 @@ +# +# MDEV-11815 SP variables of temporal data types do not replicate correctly +# +CREATE TABLE t1(a INT); +CREATE PROCEDURE p1() +BEGIN +DECLARE i INT DEFAULT 123; +DECLARE b8 BIT(8) DEFAULT 0x61; +DECLARE t0 TIME DEFAULT '01:01:01'; +DECLARE t6 TIME(6) DEFAULT '01:01:01.123456'; +DECLARE d DATE DEFAULT '2001-01-01'; +DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01'; +DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456'; +DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01'; +DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456'; +INSERT INTO t1 VALUES (i=0x61); +INSERT INTO t1 VALUES (b8=0x61); +INSERT INTO t1 VALUES (t0=10101); +INSERT INTO t1 VALUES (t6=10101); +INSERT INTO t1 VALUES (d=20010101); +INSERT INTO t1 VALUES (dt0=20010101010101); +INSERT INTO t1 VALUES (dt6=20010101010101); +INSERT INTO t1 VALUES (ts0=20010101010101); +INSERT INTO t1 VALUES (ts6=20010101010101); +END; +$$ +CALL p1; +DROP TABLE t1; +DROP PROCEDURE p1; +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE TABLE t1(a INT) +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() +BEGIN +DECLARE i INT DEFAULT 123; +DECLARE b8 BIT(8) DEFAULT 0x61; +DECLARE t0 TIME DEFAULT '01:01:01'; +DECLARE t6 TIME(6) DEFAULT '01:01:01.123456'; +DECLARE d DATE DEFAULT '2001-01-01'; +DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01'; +DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456'; +DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01'; +DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456'; +INSERT INTO t1 VALUES (i=0x61); +INSERT INTO t1 VALUES (b8=0x61); +INSERT INTO t1 VALUES (t0=10101); +INSERT INTO t1 VALUES (t6=10101); +INSERT INTO t1 VALUES (d=20010101); +INSERT INTO t1 VALUES (dt0=20010101010101); +INSERT INTO t1 VALUES (dt6=20010101010101); +INSERT INTO t1 VALUES (ts0=20010101010101); +INSERT INTO t1 VALUES (ts6=20010101010101); +END +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('i',123)=0x61) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('b8',_binary'a' COLLATE 'binary')=0x61) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('t0',TIME'01:01:01')=10101) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('t6',TIME'01:01:01.123456')=10101) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('d',DATE'2001-01-01')=20010101) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('dt0',TIMESTAMP'2001-01-01 01:01:01')=20010101010101) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('dt6',TIMESTAMP'2001-01-01 01:01:01.123456')=20010101010101) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('ts0',TIMESTAMP'2001-01-01 01:01:01')=20010101010101) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # BEGIN GTID #-#-# +master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('ts6',TIMESTAMP'2001-01-01 01:01:01.123456')=20010101010101) +master-bin.000001 # Query # # COMMIT +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */ +master-bin.000001 # Gtid # # GTID #-#-# +master-bin.000001 # Query # # use `test`; DROP PROCEDURE p1 diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp.test b/mysql-test/suite/binlog/t/binlog_stm_sp.test new file mode 100644 index 00000000000..095b4c7f699 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_stm_sp.test @@ -0,0 +1,41 @@ +--source include/have_binlog_format_statement.inc + +--disable_query_log +reset master; # get rid of previous tests binlog +--enable_query_log + +--echo # +--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly +--echo # + +CREATE TABLE t1(a INT); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE i INT DEFAULT 123; + DECLARE b8 BIT(8) DEFAULT 0x61; + DECLARE t0 TIME DEFAULT '01:01:01'; + DECLARE t6 TIME(6) DEFAULT '01:01:01.123456'; + DECLARE d DATE DEFAULT '2001-01-01'; + DECLARE dt0 DATETIME DEFAULT '2001-01-01 01:01:01'; + DECLARE dt6 DATETIME(6) DEFAULT '2001-01-01 01:01:01.123456'; + DECLARE ts0 TIMESTAMP DEFAULT '2001-01-01 01:01:01'; + DECLARE ts6 TIMESTAMP(6) DEFAULT '2001-01-01 01:01:01.123456'; + INSERT INTO t1 VALUES (i=0x61); + INSERT INTO t1 VALUES (b8=0x61); + INSERT INTO t1 VALUES (t0=10101); + INSERT INTO t1 VALUES (t6=10101); + INSERT INTO t1 VALUES (d=20010101); + INSERT INTO t1 VALUES (dt0=20010101010101); + INSERT INTO t1 VALUES (dt6=20010101010101); + INSERT INTO t1 VALUES (ts0=20010101010101); + INSERT INTO t1 VALUES (ts6=20010101010101); +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP TABLE t1; +DROP PROCEDURE p1; + +--let $binlog_file = LAST +source include/show_binlog_events.inc; diff --git a/mysql-test/suite/rpl/r/rpl_stm_sp.result b/mysql-test/suite/rpl/r/rpl_stm_sp.result new file mode 100644 index 00000000000..4e2d4c80fb6 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_stm_sp.result @@ -0,0 +1,26 @@ +include/master-slave.inc +[connection master] +# +# MDEV-11815 SP variables of temporal data types do not replicate correctly +# +connection master; +CREATE TABLE t1(a INT); +CREATE PROCEDURE p1() +BEGIN +DECLARE a TIME DEFAULT '01:01:01'; +INSERT INTO t1 VALUES (a=10101); +END; +$$ +CALL p1; +SELECT * FROM t1; +a +1 +connection slave; +SELECT * FROM t1; +a +1 +connection master; +DROP TABLE t1; +DROP PROCEDURE p1; +connection slave; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_stm_sp.test b/mysql-test/suite/rpl/t/rpl_stm_sp.test new file mode 100644 index 00000000000..b99906b8d03 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_sp.test @@ -0,0 +1,30 @@ +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc + +--echo # +--echo # MDEV-11815 SP variables of temporal data types do not replicate correctly +--echo # + +connection master; +CREATE TABLE t1(a INT); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + DECLARE a TIME DEFAULT '01:01:01'; + INSERT INTO t1 VALUES (a=10101); +END; +$$ +DELIMITER ;$$ +CALL p1; +SELECT * FROM t1; + +sync_slave_with_master; +SELECT * FROM t1; + +connection master; +DROP TABLE t1; +DROP PROCEDURE p1; +sync_slave_with_master; + + +--source include/rpl_end.inc diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 441de33b776..f5a763bdda1 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -92,65 +92,6 @@ sp_map_item_type(enum enum_field_types type) } -/** - Return a string representation of the Item value. - - @param thd thread handle - @param str string buffer for representation of the value - - @note - If the item has a string result type, the string is escaped - according to its character set. - - @retval - NULL on error - @retval - non-NULL a pointer to valid a valid string on success -*/ - -static String * -sp_get_item_value(THD *thd, Item *item, String *str) -{ - switch (item->result_type()) { - case REAL_RESULT: - case INT_RESULT: - case DECIMAL_RESULT: - if (item->field_type() != MYSQL_TYPE_BIT) - return item->val_str(str); - else {/* Bit type is handled as binary string */} - case STRING_RESULT: - { - String *result= item->val_str(str); - - if (!result) - return NULL; - - { - StringBuffer buf(result->charset()); - CHARSET_INFO *cs= thd->variables.character_set_client; - - buf.append('_'); - buf.append(result->charset()->csname); - if (cs->escape_with_backslash_is_dangerous) - buf.append(' '); - append_query_string(cs, &buf, result->ptr(), result->length(), - thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES); - buf.append(" COLLATE '"); - buf.append(item->collation.collation->name); - buf.append('\''); - str->copy(buf); - - return str; - } - } - - case ROW_RESULT: - default: - return NULL; - } -} - - bool Item_splocal::append_for_log(THD *thd, String *str) { if (fix_fields(thd, NULL)) @@ -165,7 +106,9 @@ bool Item_splocal::append_for_log(THD *thd, String *str) return true; StringBuffer str_value_holder(&my_charset_latin1); - String *str_value= sp_get_item_value(thd, this_item(), &str_value_holder); + Item *item= this_item(); + String *str_value= item->type_handler()->print_item_value(thd, item, + &str_value_holder); if (str_value) return str->append(*str_value) || str->append(')'); else @@ -1758,9 +1701,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, if (arg_no) binlog_buf.append(','); - str_value= sp_get_item_value(thd, nctx->get_item(arg_no), - &str_value_holder); - + Item *item= nctx->get_item(arg_no); + str_value= item->type_handler()->print_item_value(thd, item, + &str_value_holder); if (str_value) binlog_buf.append(*str_value); else diff --git a/sql/sql_type.cc b/sql/sql_type.cc index c5e3408edc7..d165470e314 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2050,3 +2050,108 @@ bool Type_handler_temporal_result:: return func->get_date_native(ltime, fuzzydate); } +/***************************************************************************/ + +/** + Get a string representation of the Item value. + See sql_type.h for details. +*/ +String *Type_handler_row:: + print_item_value(THD *thd, Item *item, String *str) const +{ + DBUG_ASSERT(0); + return NULL; +} + + +/** + Get a string representation of the Item value, + using the character string format with its charset and collation, e.g. + latin1 'string' COLLATE latin1_german2_ci +*/ +String *Type_handler:: + print_item_value_csstr(THD *thd, Item *item, String *str) const +{ + String *result= item->val_str(str); + + if (!result) + return NULL; + + StringBuffer buf(result->charset()); + CHARSET_INFO *cs= thd->variables.character_set_client; + + buf.append('_'); + buf.append(result->charset()->csname); + if (cs->escape_with_backslash_is_dangerous) + buf.append(' '); + append_query_string(cs, &buf, result->ptr(), result->length(), + thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES); + buf.append(" COLLATE '"); + buf.append(item->collation.collation->name); + buf.append('\''); + str->copy(buf); + + return str; +} + + +String *Type_handler_numeric:: + print_item_value(THD *thd, Item *item, String *str) const +{ + return item->val_str(str); +} + + +String *Type_handler:: + print_item_value_temporal(THD *thd, Item *item, String *str, + const Name &type_name, String *buf) const +{ + String *result= item->val_str(buf); + return !result || + str->realloc(type_name.length() + result->length() + 2) || + str->copy(type_name.ptr(), type_name.length(), &my_charset_latin1) || + str->append('\'') || + str->append(result->ptr(), result->length()) || + str->append('\'') ? + NULL : + str; +} + + +String *Type_handler_time_common:: + print_item_value(THD *thd, Item *item, String *str) const +{ + StringBuffer buf; + return print_item_value_temporal(thd, item, str, + Name(C_STRING_WITH_LEN("TIME")), &buf); +} + + +String *Type_handler_date_common:: + print_item_value(THD *thd, Item *item, String *str) const +{ + StringBuffer buf; + return print_item_value_temporal(thd, item, str, + Name(C_STRING_WITH_LEN("DATE")), &buf); +} + + +String *Type_handler_datetime_common:: + print_item_value(THD *thd, Item *item, String *str) const +{ + StringBuffer buf; + return print_item_value_temporal(thd, item, str, + Name(C_STRING_WITH_LEN("TIMESTAMP")), &buf); +} + + +String *Type_handler_timestamp_common:: + print_item_value(THD *thd, Item *item, String *str) const +{ + StringBuffer buf; + return print_item_value_temporal(thd, item, str, + Name(C_STRING_WITH_LEN("TIMESTAMP")), &buf); +} + + +/***************************************************************************/ diff --git a/sql/sql_type.h b/sql/sql_type.h index 4515d8c9333..79cdba97f8e 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -259,6 +259,9 @@ public: class Type_handler { protected: + String *print_item_value_csstr(THD *thd, Item *item, String *str) const; + String *print_item_value_temporal(THD *thd, Item *item, String *str, + const Name &type_name, String *buf) const; void make_sort_key_longlong(uchar *to, bool maybe_null, bool null_value, bool unsigned_flag, @@ -347,6 +350,24 @@ public: virtual uint32 max_display_length(const Item *item) const= 0; virtual int Item_save_in_field(Item *item, Field *field, bool no_conversions) const= 0; + + /** + Return a string representation of the Item value. + + @param thd thread handle + @param str string buffer for representation of the value + + @note + If the item has a string result type, the string is escaped + according to its character set. + + @retval + NULL on error + @retval + non-NULL a pointer to a a valid string on success + */ + virtual String *print_item_value(THD *thd, Item *item, String *str) const= 0; + /** Check if WHERE expr=value AND expr=const @@ -481,6 +502,7 @@ public: DBUG_ASSERT(0); return 1; } + String *print_item_value(THD *thd, Item *item, String *str) const; bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, @@ -585,6 +607,7 @@ protected: const Type_handler *handler) const; public: + String *print_item_value(THD *thd, Item *item, String *str) const; double Item_func_min_max_val_real(Item_func_min_max *) const; longlong Item_func_min_max_val_int(Item_func_min_max *) const; my_decimal *Item_func_min_max_val_decimal(Item_func_min_max *, @@ -788,6 +811,10 @@ public: SORT_FIELD_ATTR *attr) const; uint32 max_display_length(const Item *item) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; + String *print_item_value(THD *thd, Item *item, String *str) const + { + return print_item_value_csstr(thd, item, str); + } bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, @@ -934,6 +961,10 @@ public: const Name name() const { return m_name_bit; } enum_field_types field_type() const { return MYSQL_TYPE_BIT; } uint32 max_display_length(const Item *item) const; + String *print_item_value(THD *thd, Item *item, String *str) const + { + return print_item_value_csstr(thd, item, str); + } Field *make_conversion_table_field(TABLE *, uint metadata, const Field *target) const; }; @@ -975,6 +1006,7 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_TIME; } const Type_handler *type_handler_for_comparison() const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; + String *print_item_value(THD *thd, Item *item, String *str) const; bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, Item **items, uint nitems) const; cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const; @@ -1019,6 +1051,7 @@ public: virtual ~Type_handler_date_common() {} const Name name() const { return m_name_date; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; } + String *print_item_value(THD *thd, Item *item, String *str) const; bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, Item **items, uint nitems) const; }; @@ -1048,6 +1081,7 @@ public: virtual ~Type_handler_datetime_common() {} const Name name() const { return m_name_datetime; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + String *print_item_value(THD *thd, Item *item, String *str) const; bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, Item **items, uint nitems) const; }; @@ -1079,6 +1113,7 @@ public: virtual ~Type_handler_timestamp_common() {} const Name name() const { return m_name_timestamp; } enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; } + String *print_item_value(THD *thd, Item *item, String *str) const; bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, Item **items, uint nitems) const; }; From b0ea044d12981983d196bbba243f0ebb7348cc71 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 30 Jan 2017 15:11:22 -0500 Subject: [PATCH 165/167] Update galera tests to adapt to recent changes in 10.2. --- mysql-test/suite/galera/disabled.def | 3 +++ mysql-test/suite/galera/r/create.result | 2 ++ .../suite/galera/r/galera_forced_binlog_format.result | 4 ++-- .../galera/r/galera_parallel_apply_lock_table.result | 2 +- .../galera/r/galera_parallel_autoinc_largetrx.result | 3 ++- mysql-test/suite/galera/r/galera_sbr.result | 4 ++-- mysql-test/suite/galera/r/galera_sbr_binlog.result | 4 ++-- .../suite/galera/r/galera_var_slave_threads.result | 9 ++++++--- mysql-test/suite/galera/t/galera_kill_applier.test | 2 +- .../suite/galera/t/galera_parallel_apply_lock_table.test | 2 +- .../suite/galera/t/galera_parallel_autoinc_largetrx.test | 3 ++- mysql-test/suite/galera/t/galera_var_slave_threads.test | 9 ++++++--- 12 files changed, 30 insertions(+), 17 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index f2e4077016a..a738e97271b 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -41,3 +41,6 @@ galera_sst_xtrabackup-v2-options : TODO: Fix test case galera_sst_xtrabackup-v2 : MDEV-11208 galera_sst_xtrabackup-v2_encrypt_with_key : MDEV-11208 mysql-wsrep#33 : TODO: investigate +galera_var_innodb_disallow_writes : MDEV-10949 +galera_many_tables_pk : MDEV-11927 +galera_many_tables_nopk : MDEV-11927 diff --git a/mysql-test/suite/galera/r/create.result b/mysql-test/suite/galera/r/create.result index 4d6488d324b..a445b32e8bf 100644 --- a/mysql-test/suite/galera/r/create.result +++ b/mysql-test/suite/galera/r/create.result @@ -7,6 +7,8 @@ SHOW VARIABLES LIKE '%log%bin%'; Variable_name Value log_bin OFF log_bin_basename +log_bin_compress OFF +log_bin_compress_min_len 256 log_bin_index log_bin_trust_function_creators ON sql_log_bin ON diff --git a/mysql-test/suite/galera/r/galera_forced_binlog_format.result b/mysql-test/suite/galera/r/galera_forced_binlog_format.result index 86789a1b8e9..e5bd486eadc 100644 --- a/mysql-test/suite/galera/r/galera_forced_binlog_format.result +++ b/mysql-test/suite/galera/r/galera_forced_binlog_format.result @@ -2,12 +2,12 @@ connection node_1; RESET MASTER; SET SESSION binlog_format = 'STATEMENT'; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); SET SESSION binlog_format = 'MIXED'; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: MIXED +Warning 1105 MariaDB Galera and flashback do not support binlog format: MIXED INSERT INTO t1 VALUES (2); SHOW BINLOG EVENTS IN 'mysqld-bin.000001' FROM 256; Log_name Pos Event_type Server_id End_log_pos Info diff --git a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result index bf4b056a6e4..90349f493bd 100644 --- a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result +++ b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result @@ -11,7 +11,7 @@ SET SESSION wsrep_sync_wait=0; SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%'; COUNT(*) = 1 1 -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table level lock%'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock'; COUNT(*) = 1 1 SELECT COUNT(*) = 0 FROM t1; diff --git a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result index 336f46fcd7e..dd30f5af384 100644 --- a/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result +++ b/mysql-test/suite/galera/r/galera_parallel_autoinc_largetrx.result @@ -19,7 +19,8 @@ COUNT(*) = 30000 SELECT COUNT(DISTINCT f1) = 30000 FROM t1; COUNT(DISTINCT f1) = 30000 1 -SELECT COUNT(*) = 5 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = 5 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE +USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; COUNT(*) = 5 1 connection default; diff --git a/mysql-test/suite/galera/r/galera_sbr.result b/mysql-test/suite/galera/r/galera_sbr.result index 61a58c9cb89..0bdaeef5b8a 100644 --- a/mysql-test/suite/galera/r/galera_sbr.result +++ b/mysql-test/suite/galera/r/galera_sbr.result @@ -1,12 +1,12 @@ connection node_1; SET SESSION binlog_format = 'STATEMENT'; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); SET SESSION binlog_format = 'MIXED'; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: MIXED +Warning 1105 MariaDB Galera and flashback do not support binlog format: MIXED INSERT INTO t1 VALUES (2); connection node_2; SELECT COUNT(*) = 2 FROM t1; diff --git a/mysql-test/suite/galera/r/galera_sbr_binlog.result b/mysql-test/suite/galera/r/galera_sbr_binlog.result index 61a58c9cb89..0bdaeef5b8a 100644 --- a/mysql-test/suite/galera/r/galera_sbr_binlog.result +++ b/mysql-test/suite/galera/r/galera_sbr_binlog.result @@ -1,12 +1,12 @@ connection node_1; SET SESSION binlog_format = 'STATEMENT'; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: STATEMENT +Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); SET SESSION binlog_format = 'MIXED'; Warnings: -Warning 1105 MariaDB Galera does not support binlog format: MIXED +Warning 1105 MariaDB Galera and flashback do not support binlog format: MIXED INSERT INTO t1 VALUES (2); connection node_2; SELECT COUNT(*) = 2 FROM t1; diff --git a/mysql-test/suite/galera/r/galera_var_slave_threads.result b/mysql-test/suite/galera/r/galera_var_slave_threads.result index facc083544c..0ad0e3820e0 100644 --- a/mysql-test/suite/galera/r/galera_var_slave_threads.result +++ b/mysql-test/suite/galera/r/galera_var_slave_threads.result @@ -12,7 +12,8 @@ SELECT @@wsrep_slave_threads = 1; @@wsrep_slave_threads = 1 1 SET GLOBAL wsrep_slave_threads = 1; -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; COUNT(*) = 2 1 SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; @@ -25,7 +26,8 @@ connection node_2; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 1 -SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; COUNT(*) = @@wsrep_slave_threads + 1 1 SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; @@ -101,7 +103,8 @@ connection node_2; SELECT COUNT(*) = 64 FROM t2; COUNT(*) = 64 1 -SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; COUNT(*) = @@wsrep_slave_threads + 1 1 SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; diff --git a/mysql-test/suite/galera/t/galera_kill_applier.test b/mysql-test/suite/galera/t/galera_kill_applier.test index e14a8b9af23..71a46114970 100644 --- a/mysql-test/suite/galera/t/galera_kill_applier.test +++ b/mysql-test/suite/galera/t/galera_kill_applier.test @@ -7,7 +7,7 @@ --connection node_1 ---let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE != 'wsrep aborter idle' OR STATE IS NULL LIMIT 1` +--let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND NOT STATE <=> 'wsrep aborter idle' AND NOT STATE <=> 'InnoDB background thread' LIMIT 1` --disable_query_log --error ER_KILL_DENIED_ERROR,ER_KILL_DENIED_ERROR diff --git a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test index febb91a9725..08ed3fac67e 100644 --- a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test +++ b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test @@ -33,7 +33,7 @@ INSERT INTO t2 VALUES (1); --sleep 1 SET SESSION wsrep_sync_wait=0; SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%applied write set%'; -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table level lock%'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock'; SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) = 0 FROM t2; diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test index f280e49d206..ea853f8ea01 100644 --- a/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test +++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test @@ -39,7 +39,8 @@ SET GLOBAL wsrep_slave_threads = 4; --reap SELECT COUNT(*) = 30000 FROM t1; SELECT COUNT(DISTINCT f1) = 30000 FROM t1; -SELECT COUNT(*) = 5 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = 5 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE + USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; --disable_query_log --eval SET GLOBAL wsrep_slave_threads = $wsrep_slave_threads_orig; diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.test b/mysql-test/suite/galera/t/galera_var_slave_threads.test index 50e22fbef66..23608ad32a9 100644 --- a/mysql-test/suite/galera/t/galera_var_slave_threads.test +++ b/mysql-test/suite/galera/t/galera_var_slave_threads.test @@ -22,7 +22,8 @@ SELECT @@wsrep_slave_threads = 1; SET GLOBAL wsrep_slave_threads = 1; # There is a separate wsrep_aborter thread at all times -SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; # @@ -38,7 +39,8 @@ INSERT INTO t1 VALUES (1); --connection node_2 SELECT COUNT(*) = 1 FROM t1; -SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; # @@ -60,7 +62,8 @@ while ($count) --connection node_2 SELECT COUNT(*) = 64 FROM t2; -SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user'; +SELECT COUNT(*) = @@wsrep_slave_threads + 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE USER = 'system user' AND NOT STATE <=> 'InnoDB background thread'; SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%'; From 69114862f21dadb5c660847c691cc24456c90970 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 1 Feb 2017 13:08:21 -0800 Subject: [PATCH 166/167] Adjusted more tests after the fix for mdev-9976. --- mysql-test/extra/binlog_tests/binlog_write_error.inc | 2 +- mysql-test/suite/binlog/r/binlog_write_error.result | 4 ++-- .../suite/binlog_encryption/binlog_write_error.result | 4 ++-- mysql-test/suite/rpl/r/rpl_killed_ddl.result | 10 +++++----- mysql-test/suite/rpl/t/rpl_killed_ddl.test | 10 +++++----- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/mysql-test/extra/binlog_tests/binlog_write_error.inc b/mysql-test/extra/binlog_tests/binlog_write_error.inc index da66dbf5a95..fa3ba087a7e 100644 --- a/mysql-test/extra/binlog_tests/binlog_write_error.inc +++ b/mysql-test/extra/binlog_tests/binlog_write_error.inc @@ -71,7 +71,7 @@ source include/binlog_inject_error.inc; let $query= DROP VIEW v1; source include/binlog_inject_error.inc; -let $query= CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +let $query= CREATE PROCEDURE p1(OUT rows_cnt INT) SELECT count(*) INTO rows_cnt FROM t1; source include/binlog_inject_error.inc; let $query= DROP PROCEDURE p1; diff --git a/mysql-test/suite/binlog/r/binlog_write_error.result b/mysql-test/suite/binlog/r/binlog_write_error.result index 28cffb3a8e5..2606a9f40b3 100644 --- a/mysql-test/suite/binlog/r/binlog_write_error.result +++ b/mysql-test/suite/binlog/r/binlog_write_error.result @@ -59,8 +59,8 @@ DROP VIEW v1; ERROR HY000: Error writing file 'master-bin' ((errno: #) SET GLOBAL debug_dbug=''; SET GLOBAL debug_dbug='d,injecting_fault_writing'; -CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; -CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +CREATE PROCEDURE p1(OUT rows_cnt INT) SELECT count(*) INTO rows_cnt FROM t1; +CREATE PROCEDURE p1(OUT rows_cnt INT) SELECT count(*) INTO rows_cnt FROM t1; ERROR HY000: Error writing file 'master-bin' ((errno: #) SET GLOBAL debug_dbug=''; SET GLOBAL debug_dbug='d,injecting_fault_writing'; diff --git a/mysql-test/suite/binlog_encryption/binlog_write_error.result b/mysql-test/suite/binlog_encryption/binlog_write_error.result index 28cffb3a8e5..2606a9f40b3 100644 --- a/mysql-test/suite/binlog_encryption/binlog_write_error.result +++ b/mysql-test/suite/binlog_encryption/binlog_write_error.result @@ -59,8 +59,8 @@ DROP VIEW v1; ERROR HY000: Error writing file 'master-bin' ((errno: #) SET GLOBAL debug_dbug=''; SET GLOBAL debug_dbug='d,injecting_fault_writing'; -CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; -CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +CREATE PROCEDURE p1(OUT rows_cnt INT) SELECT count(*) INTO rows_cnt FROM t1; +CREATE PROCEDURE p1(OUT rows_cnt INT) SELECT count(*) INTO rows_cnt FROM t1; ERROR HY000: Error writing file 'master-bin' ((errno: #) SET GLOBAL debug_dbug=''; SET GLOBAL debug_dbug='d,injecting_fault_writing'; diff --git a/mysql-test/suite/rpl/r/rpl_killed_ddl.result b/mysql-test/suite/rpl/r/rpl_killed_ddl.result index bb264a12af3..66309432efe 100644 --- a/mysql-test/suite/rpl/r/rpl_killed_ddl.result +++ b/mysql-test/suite/rpl/r/rpl_killed_ddl.result @@ -34,9 +34,9 @@ ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY DO INSERT INTO test.t1 VALUES (1); CREATE FUNCTION f1 () RETURNS INT DETERMINISTIC RETURN 1; -CREATE PROCEDURE p1 (OUT rows INT) +CREATE PROCEDURE p1 (OUT rows_cnt INT) BEGIN -SELECT COUNT(*) INTO rows FROM t1; +SELECT COUNT(*) INTO rows_cnt FROM t1; END; // CREATE SERVER s1 @@ -125,9 +125,9 @@ connection master; include/rpl_diff.inc connection master; connection master1; -CREATE PROCEDURE p2 (OUT rows INT) +CREATE PROCEDURE p2 (OUT rows_cnt INT) BEGIN -SELECT COUNT(*) INTO rows FROM t2; +SELECT COUNT(*) INTO rows_cnt FROM t2; END; // source include/kill_query.inc; @@ -135,7 +135,7 @@ connection master; include/rpl_diff.inc connection master; connection master1; -ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; +ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows_cnt of table t1'; source include/kill_query.inc; connection master; include/rpl_diff.inc diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test index 593051700a7..6415b3e8874 100644 --- a/mysql-test/suite/rpl/t/rpl_killed_ddl.test +++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test @@ -83,9 +83,9 @@ CREATE FUNCTION f1 () RETURNS INT DETERMINISTIC RETURN 1; DELIMITER //; -CREATE PROCEDURE p1 (OUT rows INT) +CREATE PROCEDURE p1 (OUT rows_cnt INT) BEGIN - SELECT COUNT(*) INTO rows FROM t1; + SELECT COUNT(*) INTO rows_cnt FROM t1; END; // DELIMITER ;// @@ -203,15 +203,15 @@ source include/kill_query_and_diff_master_slave.inc; --let $rpl_diff_statement= SHOW PROCEDURE STATUS LIKE \'p%\' DELIMITER //; -send CREATE PROCEDURE p2 (OUT rows INT) +send CREATE PROCEDURE p2 (OUT rows_cnt INT) BEGIN - SELECT COUNT(*) INTO rows FROM t2; + SELECT COUNT(*) INTO rows_cnt FROM t2; END; // DELIMITER ;// source include/kill_query_and_diff_master_slave.inc; -send ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows of table t1'; +send ALTER PROCEDURE p1 SQL SECURITY INVOKER COMMENT 'return rows_cnt of table t1'; source include/kill_query_and_diff_master_slave.inc; send DROP PROCEDURE p1; From 8481c70ede067b576d5b1576a9b68042e84368fb Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 1 Feb 2017 19:15:28 -0800 Subject: [PATCH 167/167] Fixed bug mdev-11867. If a window function with aggregation is over the result set of a grouping query then the argument of the aggregate function from the window function is allowed to be an aggregate function itself. --- mysql-test/r/win.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/win.test | 29 +++++++++++++++++++++++++++++ sql/item_sum.cc | 3 +++ sql/item_sum.h | 4 ++++ sql/sql_yacc.yy | 3 +++ 5 files changed, 67 insertions(+) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index 0a003b0fe28..0606737c3ef 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -2432,3 +2432,31 @@ id sum(a) OVER (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) 8 2100 9 9200 DROP TABLE t1; +# +# MDEV-11867: window function with aggregation +# over the result of grouping +# +create table t1 ( +username varchar(32), +amount int +); +insert into t1 values +('user1',1), +('user1',5), +('user1',3), +('user2',10), +('user2',20), +('user2',30); +select username, sum(amount) as s, avg(sum(amount)) over (order by s desc) +from t1 +group by username; +username s avg(sum(amount)) over (order by s desc) +user1 9 34.5000 +user2 60 60.0000 +select username, sum(amount), avg(sum(amount)) over (order by sum(amount) desc) +from t1 +group by username; +username sum(amount) avg(sum(amount)) over (order by sum(amount) desc) +user1 9 34.5000 +user2 60 60.0000 +drop table t1; diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index 00fbec7d88d..6444c4df6a4 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -1463,3 +1463,32 @@ FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-11867: window function with aggregation +--echo # over the result of grouping +--echo # + +create table t1 ( + username varchar(32), + amount int +); + +insert into t1 values +('user1',1), +('user1',5), +('user1',3), +('user2',10), +('user2',20), +('user2',30); + +select username, sum(amount) as s, avg(sum(amount)) over (order by s desc) + from t1 +group by username; + +select username, sum(amount), avg(sum(amount)) over (order by sum(amount) desc) + from t1 +group by username; + +drop table t1; + + diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 51a6c2bd3eb..23f8638b724 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -151,6 +151,8 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) curr_sel->name_visibility_map); bool invalid= FALSE; DBUG_ASSERT(curr_sel->name_visibility_map); // should be set already + if (window_func_sum_expr_flag) + return false; /* The value of max_arg_level is updated if an argument of the set function contains a column reference resolved against a subquery whose level is @@ -460,6 +462,7 @@ void Item_sum::mark_as_sum_func() const_item_cache= false; with_sum_func= 1; with_field= 0; + window_func_sum_expr_flag= false; } diff --git a/sql/item_sum.h b/sql/item_sum.h index 84049814ef9..940726b5d8e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -340,6 +340,9 @@ private: */ bool with_distinct; + /* TRUE if this is aggregate function of a window function */ + bool window_func_sum_expr_flag; + public: bool has_force_copy_fields() const { return force_copy_fields; } @@ -551,6 +554,7 @@ public: virtual void cleanup(); bool check_vcol_func_processor(void *arg); virtual void setup_window_func(THD *thd, Window_spec *window_spec) {} + void mark_as_window_func_sum_expr() { window_func_sum_expr_flag= true; } }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0cd2c563319..12423e71f1f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10464,6 +10464,9 @@ window_func: simple_window_func | sum_expr + { + ((Item_sum *) $1)->mark_as_window_func_sum_expr(); + } ; simple_window_func: