diff --git a/client/mysqlslap.c b/client/mysqlslap.c index ed5e20ca18c..c44bf8446f9 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -1177,9 +1177,6 @@ get_options(int *argc,char ***argv) if (debug_check_flag) my_end_arg= MY_CHECK_ERROR; - if (!user) - user= (char *)"root"; - /* If something is created and --no-drop is not specified, we drop the schema. diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 45d0d0e1111..e16a9ec69a0 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -6020,12 +6020,9 @@ static bool xtrabackup_prepare_func(char** argv) srv_shutdown_bg_undo_sources(); srv_purge_shutdown(); buf_flush_sync_all_buf_pools(); - innodb_shutdown(); - innobase_space_shutdown(); } - else - innodb_shutdown(); + innodb_shutdown(); innodb_free_param(); /* output to metadata file */ diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result index ab726a0e22f..6ded4f687a6 100644 --- a/mysql-test/suite/plugins/r/server_audit.result +++ b/mysql-test/suite/plugins/r/server_audit.result @@ -452,8 +452,8 @@ TIME,HOSTNAME,plug,localhost,ID,0,DISCONNECT,,,0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv, TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT PROXY ON plug_dest TO plug',0 -TIME,HOSTNAME,plug,localhost,ID,0,PROXY_CONNECT,test,`plug_dest`@`%`,0 TIME,HOSTNAME,plug,localhost,ID,0,CONNECT,test,,0 +TIME,HOSTNAME,plug,localhost,ID,0,PROXY_CONNECT,test,`plug_dest`@`%`,0 TIME,HOSTNAME,plug,localhost,ID,0,DISCONNECT,test,,0 TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, diff --git a/mysql-test/suite/sql_sequence/create.result b/mysql-test/suite/sql_sequence/create.result index 14464c60e99..5a53a66c9a8 100644 --- a/mysql-test/suite/sql_sequence/create.result +++ b/mysql-test/suite/sql_sequence/create.result @@ -666,7 +666,7 @@ create temporary sequence s; drop temporary table s; create temporary table s (i int); drop temporary sequence s; -ERROR 42S02: Unknown SEQUENCE: 'test.s' +ERROR 42S02: 'test.s' is not a SEQUENCE drop table s; # # MDEV-15115 Assertion failure in CREATE SEQUENCE...ROW_FORMAT=REDUNDANT diff --git a/mysql-test/suite/sql_sequence/create.test b/mysql-test/suite/sql_sequence/create.test index 2c41fb3658b..ac3aae845cd 100644 --- a/mysql-test/suite/sql_sequence/create.test +++ b/mysql-test/suite/sql_sequence/create.test @@ -489,7 +489,7 @@ drop table s; create temporary sequence s; drop temporary table s; create temporary table s (i int); ---error ER_UNKNOWN_SEQUENCES +--error ER_NOT_SEQUENCE2 drop temporary sequence s; drop table s; diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result index abc101b3c00..643233149d2 100644 --- a/mysql-test/suite/sql_sequence/other.result +++ b/mysql-test/suite/sql_sequence/other.result @@ -300,4 +300,63 @@ update t1 set p_first_name='Yunxi' where p_id=1; drop view v2; drop table t1,t2; drop sequence s1; +# +# MDEV-19273:Server crash in MDL_ticket::has_stronger_or_equal_type or +# Assertion `thd->mdl_context.is_lock_owner(MDL_key::TABLE, +# table->db.str, table->table_name.str, MDL_SHARED)' failed +# in mysql_rm_table_no_locks +# +CREATE TABLE t1 (a INT); +CREATE TEMPORARY TABLE tmp (b INT); +LOCK TABLE t1 READ; +DROP SEQUENCE tmp; +ERROR 42S02: 'test.tmp' is not a SEQUENCE +DROP TEMPORARY SEQUENCE tmp; +ERROR 42S02: 'test.tmp' is not a SEQUENCE +DROP SEQUENCE t1; +ERROR HY000: Table 't1' was locked with a READ lock and can't be updated +DROP TEMPORARY SEQUENCE t1; +ERROR 42S02: Unknown SEQUENCE: 'test.t1' +UNLOCK TABLES; +DROP SEQUENCE t1; +ERROR 42S02: 'test.t1' is not a SEQUENCE +DROP TEMPORARY SEQUENCE t1; +ERROR 42S02: Unknown SEQUENCE: 'test.t1' +DROP TABLE t1; +CREATE TABLE t (a INT); +CREATE TEMPORARY TABLE s (f INT); +CREATE SEQUENCE s; +LOCK TABLE t WRITE; +DROP SEQUENCE s; +ERROR 42S02: 'test.s' is not a SEQUENCE +DROP TEMPORARY SEQUENCE s; +ERROR 42S02: 'test.s' is not a SEQUENCE +UNLOCK TABLES; +CREATE TEMPORARY SEQUENCE s; +LOCK TABLE t WRITE; +DROP TEMPORARY SEQUENCE s; +UNLOCK TABLES; +DROP TEMPORARY TABLE s; +DROP SEQUENCE s; +create table s(a INT); +CREATE TEMPORARY TABLE s (f INT); +LOCK TABLE t WRITE; +DROP TEMPORARY TABLE s; +CREATE TEMPORARY TABLE s (f INT); +DROP TABLE s; +DROP TABLE s; +ERROR HY000: Table 's' was not locked with LOCK TABLES +UNLOCK TABLES; +DROP TABLE s; +CREATE VIEW v1 as SELECT * FROM t; +CREATE SEQUENCE s; +DROP SEQUENCE IF EXISTS v1; +Warnings: +Note 4091 Unknown SEQUENCE: 'test.v1' +DROP VIEW IF EXISTS s; +Warnings: +Note 4092 Unknown VIEW: 'test.s' +DROP VIEW v1; +DROP SEQUENCE s; +DROP TABLE t; # End of 10.3 tests diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test index 70c4efa40e5..0fbb2d0e2f9 100644 --- a/mysql-test/suite/sql_sequence/other.test +++ b/mysql-test/suite/sql_sequence/other.test @@ -315,4 +315,68 @@ drop view v2; drop table t1,t2; drop sequence s1; +--echo # +--echo # MDEV-19273:Server crash in MDL_ticket::has_stronger_or_equal_type or +--echo # Assertion `thd->mdl_context.is_lock_owner(MDL_key::TABLE, +--echo # table->db.str, table->table_name.str, MDL_SHARED)' failed +--echo # in mysql_rm_table_no_locks +--echo # + +CREATE TABLE t1 (a INT); +CREATE TEMPORARY TABLE tmp (b INT); +LOCK TABLE t1 READ; +--error ER_NOT_SEQUENCE2 +DROP SEQUENCE tmp; +--error ER_NOT_SEQUENCE2 +DROP TEMPORARY SEQUENCE tmp; +--error ER_TABLE_NOT_LOCKED_FOR_WRITE +DROP SEQUENCE t1; +--error ER_UNKNOWN_SEQUENCES +DROP TEMPORARY SEQUENCE t1; +UNLOCK TABLES; +--error ER_NOT_SEQUENCE2 +DROP SEQUENCE t1; +--error ER_UNKNOWN_SEQUENCES +DROP TEMPORARY SEQUENCE t1; + +# Cleanup +DROP TABLE t1; + + +CREATE TABLE t (a INT); +CREATE TEMPORARY TABLE s (f INT); +CREATE SEQUENCE s; +LOCK TABLE t WRITE; +--error ER_NOT_SEQUENCE2 +DROP SEQUENCE s; +--error ER_NOT_SEQUENCE2 +DROP TEMPORARY SEQUENCE s; +UNLOCK TABLES; +CREATE TEMPORARY SEQUENCE s; +LOCK TABLE t WRITE; +DROP TEMPORARY SEQUENCE s; +UNLOCK TABLES; +DROP TEMPORARY TABLE s; +DROP SEQUENCE s; + +create table s(a INT); +CREATE TEMPORARY TABLE s (f INT); +LOCK TABLE t WRITE; +DROP TEMPORARY TABLE s; +CREATE TEMPORARY TABLE s (f INT); +DROP TABLE s; +--error ER_TABLE_NOT_LOCKED +DROP TABLE s; +UNLOCK TABLES; +DROP TABLE s; + +CREATE VIEW v1 as SELECT * FROM t; +CREATE SEQUENCE s; + +DROP SEQUENCE IF EXISTS v1; +DROP VIEW IF EXISTS s; + +DROP VIEW v1; +DROP SEQUENCE s; +DROP TABLE t; --echo # End of 10.3 tests diff --git a/mysql-test/suite/versioning/common.inc b/mysql-test/suite/versioning/common.inc index efb081a02e4..25adf15dd50 100644 --- a/mysql-test/suite/versioning/common.inc +++ b/mysql-test/suite/versioning/common.inc @@ -70,6 +70,11 @@ returns int deterministic return sys_trx_end = $sys_datatype_max; +eval create or replace function current_row_ts(sys_trx_end timestamp(6)) +returns int +deterministic + return convert_tz(sys_trx_end, '+00:00', @@time_zone) = TIMESTAMP'2038-01-19 03:14:07.999999'; + delimiter ~~; eval create or replace function check_row(row_start $sys_datatype_expl, row_end $sys_datatype_expl) returns varchar(255) @@ -86,4 +91,20 @@ begin end~~ delimiter ;~~ +delimiter ~~; +eval create or replace function check_row_ts(row_start timestamp(6), row_end timestamp(6)) +returns varchar(255) +deterministic +begin + if row_end < row_start then + return "ERROR: row_end < row_start"; + elseif row_end = row_start then + return "ERROR: row_end == row_start"; + elseif current_row_ts(row_end) then + return "CURRENT ROW"; + end if; + return "HISTORICAL ROW"; +end~~ +delimiter ;~~ + --enable_query_log diff --git a/mysql-test/suite/versioning/common_finish.inc b/mysql-test/suite/versioning/common_finish.inc index 61641c6c5ce..3c4e7b66ff3 100644 --- a/mysql-test/suite/versioning/common_finish.inc +++ b/mysql-test/suite/versioning/common_finish.inc @@ -4,5 +4,7 @@ drop procedure if exists verify_trt; drop procedure if exists verify_trt_dummy; drop function if exists current_row; drop function if exists check_row; +drop function if exists current_row_ts; +drop function if exists check_row_ts; --enable_warnings --enable_query_log diff --git a/mysql-test/suite/versioning/r/delete.result b/mysql-test/suite/versioning/r/delete.result index 5aa239b9cb8..0f9e2c22130 100644 --- a/mysql-test/suite/versioning/r/delete.result +++ b/mysql-test/suite/versioning/r/delete.result @@ -130,3 +130,22 @@ ERROR 42S02: Table 'test.xx' doesn't exist drop procedure pr; drop trigger tr; drop table t1; +# +# MDEV-21138 Assertion `col->ord_part' or `f.col->ord_part' failed in row_build_index_entry_low +# +create table t1 ( +f1 int, f2 text, f3 int, fulltext (f2), key(f1), key(f3), +foreign key r (f3) references t1 (f1) on delete set null) +with system versioning engine innodb; +insert into t1 values (1, repeat('a', 8193), 1), (1, repeat('b', 8193), 1); +select f1, f3, check_row_ts(row_start, row_end) from t1; +f1 f3 check_row_ts(row_start, row_end) +1 1 CURRENT ROW +1 1 CURRENT ROW +delete from t1; +select f1, f3, check_row_ts(row_start, row_end) from t1 for system_time all; +f1 f3 check_row_ts(row_start, row_end) +1 1 HISTORICAL ROW +1 NULL ERROR: row_end == row_start +1 1 HISTORICAL ROW +drop table t1; diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result index 1b9925b1e62..288909bbc37 100644 --- a/mysql-test/suite/versioning/r/foreign.result +++ b/mysql-test/suite/versioning/r/foreign.result @@ -400,6 +400,8 @@ Warning 1265 Data truncated for column 'f12' at row 7 SET timestamp = 9; REPLACE INTO t2 SELECT * FROM t2; DROP TABLE t1, t2; +set timestamp= default; +set time_zone='+00:00'; # # MDEV-16210 FK constraints on versioned tables use historical rows, which may cause constraint violation # @@ -429,3 +431,17 @@ insert into t2 values (1), (1); # DELETE from foreign table is allowed delete from t2; drop tables t2, t1; +# +# MDEV-23644 Assertion on evaluating foreign referential action for self-reference in system versioned table +# +create table t1 (pk int primary key, f1 int,f2 int, f3 text, +key(f1), fulltext(f3), key(f3(10)), +foreign key (f2) references t1 (f1) on delete set null +) engine=innodb with system versioning; +insert into t1 values (1, 8, 8, 'SHORT'), (2, 8, 8, repeat('LONG', 8071)); +delete from t1; +select pk, f1, f2, left(f3, 4), check_row_ts(row_start, row_end) from t1 for system_time all order by pk; +pk f1 f2 left(f3, 4) check_row_ts(row_start, row_end) +1 8 8 SHOR HISTORICAL ROW +2 8 8 LONG HISTORICAL ROW +drop table t1; diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index 9e25dc6910b..ca6d026df30 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -691,6 +691,13 @@ create table t1 (a int) with system versioning partition by system_time alter table t1 add partition (partition p2); ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME` drop table t1; +# +# MDEV-22178 Assertion `info->alias.str' failed in partition_info::check_partition_info instead of ER_VERS_WRONG_PARTS +# +create or replace table t1 (a int) with system versioning; +alter table t1 partition by system_time (partition pn current); +ERROR HY000: Wrong partitions for `t1`: must have at least one HISTORY and exactly one last CURRENT +drop table t1; # End of 10.3 tests # # MDEV-22283 Server crashes in key_copy or unexpected error 156: The table already existed in the storage engine diff --git a/mysql-test/suite/versioning/r/trx_id.result b/mysql-test/suite/versioning/r/trx_id.result index 8475fc88258..03ef20a6a9e 100644 --- a/mysql-test/suite/versioning/r/trx_id.result +++ b/mysql-test/suite/versioning/r/trx_id.result @@ -5,7 +5,15 @@ sys_trx_start bigint(20) unsigned as row start invisible, sys_trx_end bigint(20) unsigned as row end invisible, period for system_time (sys_trx_start, sys_trx_end) ) with system versioning; +# No history inside the transaction +start transaction; insert into t1 (x) values (1); +update t1 set x= x + 1; +update t1 set x= x + 1; +commit; +select *, sys_trx_start > 1, sys_trx_end from t1 for system_time all; +x sys_trx_start > 1 sys_trx_end +3 1 18446744073709551615 # ALTER ADD SYSTEM VERSIONING should write to mysql.transaction_registry set @@system_versioning_alter_history=keep; create or replace table t1 (x int); diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result index cd26c341113..fbb9f541b06 100644 --- a/mysql-test/suite/versioning/r/update.result +++ b/mysql-test/suite/versioning/r/update.result @@ -241,6 +241,26 @@ B2 salary 1 2500 drop table t1; drop table t2; +# Ensure FTS retains correct history +create table t1 ( +x int, y text, fulltext (y), +row_start SYS_DATATYPE as row start invisible, +row_end SYS_DATATYPE as row end invisible, +period for system_time (row_start, row_end)) +with system versioning engine innodb; +insert into t1 values (1, repeat('LONG', 2048)); +update t1 set x= x + 1; +select x, left(y, 4), length(y), check_row(row_start, row_end) from t1 for system_time all order by x, y; +x left(y, 4) length(y) check_row(row_start, row_end) +1 LONG 8192 HISTORICAL ROW +2 LONG 8192 CURRENT ROW +update t1 set y= 'SHORT'; +select x, left(y, 4), length(y), check_row(row_start, row_end) from t1 for system_time all order by x, y; +x left(y, 4) length(y) check_row(row_start, row_end) +1 LONG 8192 HISTORICAL ROW +2 LONG 8192 HISTORICAL ROW +2 SHOR 5 CURRENT ROW +drop tables t1; ### Issue tempesta-tech/mariadb#365, bug 7 (duplicate of historical row) create or replace table t1 (a int primary key, b int) with system versioning engine myisam; @@ -350,3 +370,32 @@ insert into t1 (a) values (1), (2); update ignore t1 set a= 3; delete history from t1; drop table t1; +# +# MDEV-23446 UPDATE does not insert history row if the row is not changed +# +create table t1 ( +a int, +row_start SYS_DATATYPE as row start invisible, +row_end SYS_DATATYPE as row end invisible, +period for system_time (row_start, row_end)) with system versioning; +insert into t1 values (1); +update t1 set a= 1; +select *, check_row(row_start, row_end) from t1 for system_time all order by row_end; +a check_row(row_start, row_end) +1 HISTORICAL ROW +1 CURRENT ROW +# multi-update +create or replace table t2 like t1; +create or replace table t3 like t1; +insert into t2 values (1); +insert into t3 values (1); +update t2, t3 set t2.a= 1, t3.a= 1 where t2.a = t3.a; +select *, check_row(row_start, row_end) from t2 for system_time all order by row_end; +a check_row(row_start, row_end) +1 HISTORICAL ROW +1 CURRENT ROW +select *, check_row(row_start, row_end) from t2 for system_time all order by row_end; +a check_row(row_start, row_end) +1 HISTORICAL ROW +1 CURRENT ROW +drop tables t1, t2, t3; diff --git a/mysql-test/suite/versioning/t/delete.test b/mysql-test/suite/versioning/t/delete.test index 492463f9395..a5a0497fef2 100644 --- a/mysql-test/suite/versioning/t/delete.test +++ b/mysql-test/suite/versioning/t/delete.test @@ -94,4 +94,19 @@ drop procedure pr; drop trigger tr; drop table t1; +--echo # +--echo # MDEV-21138 Assertion `col->ord_part' or `f.col->ord_part' failed in row_build_index_entry_low +--echo # +create table t1 ( + f1 int, f2 text, f3 int, fulltext (f2), key(f1), key(f3), + foreign key r (f3) references t1 (f1) on delete set null) +with system versioning engine innodb; +insert into t1 values (1, repeat('a', 8193), 1), (1, repeat('b', 8193), 1); +select f1, f3, check_row_ts(row_start, row_end) from t1; +delete from t1; +select f1, f3, check_row_ts(row_start, row_end) from t1 for system_time all; + +# cleanup +drop table t1; + --source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test index 453ddd34034..4143cd59048 100644 --- a/mysql-test/suite/versioning/t/foreign.test +++ b/mysql-test/suite/versioning/t/foreign.test @@ -421,6 +421,8 @@ REPLACE INTO t2 SELECT * FROM t2; # Cleanup DROP TABLE t1, t2; +set timestamp= default; +set time_zone='+00:00'; --let $datadir= `select @@datadir` --remove_file $datadir/test/t1.data --remove_file $datadir/test/t1.data.2 @@ -458,4 +460,20 @@ insert into t2 values (1), (1); delete from t2; drop tables t2, t1; +--echo # +--echo # MDEV-23644 Assertion on evaluating foreign referential action for self-reference in system versioned table +--echo # +create table t1 (pk int primary key, f1 int,f2 int, f3 text, + key(f1), fulltext(f3), key(f3(10)), + foreign key (f2) references t1 (f1) on delete set null +) engine=innodb with system versioning; + +insert into t1 values (1, 8, 8, 'SHORT'), (2, 8, 8, repeat('LONG', 8071)); + +delete from t1; +select pk, f1, f2, left(f3, 4), check_row_ts(row_start, row_end) from t1 for system_time all order by pk; + +# cleanup +drop table t1; + --source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index 03d396b5e6c..f9163b09517 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -643,6 +643,15 @@ alter table t1 add partition (partition p2); # Cleanup drop table t1; +--echo # +--echo # MDEV-22178 Assertion `info->alias.str' failed in partition_info::check_partition_info instead of ER_VERS_WRONG_PARTS +--echo # +create or replace table t1 (a int) with system versioning; +--error ER_VERS_WRONG_PARTS +alter table t1 partition by system_time (partition pn current); +# Cleanup +drop table t1; + --echo # End of 10.3 tests --echo # diff --git a/mysql-test/suite/versioning/t/trx_id.test b/mysql-test/suite/versioning/t/trx_id.test index 38724a47fd1..7dfc8acb080 100644 --- a/mysql-test/suite/versioning/t/trx_id.test +++ b/mysql-test/suite/versioning/t/trx_id.test @@ -14,7 +14,13 @@ create or replace table t1 ( period for system_time (sys_trx_start, sys_trx_end) ) with system versioning; +--echo # No history inside the transaction +start transaction; insert into t1 (x) values (1); +update t1 set x= x + 1; +update t1 set x= x + 1; +commit; +select *, sys_trx_start > 1, sys_trx_end from t1 for system_time all; --echo # ALTER ADD SYSTEM VERSIONING should write to mysql.transaction_registry set @@system_versioning_alter_history=keep; diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test index 06f81ea9064..7f99e307942 100644 --- a/mysql-test/suite/versioning/t/update.test +++ b/mysql-test/suite/versioning/t/update.test @@ -147,6 +147,21 @@ select @tmp2 = sys_trx_start as B2, salary from t2; drop table t1; drop table t2; +--echo # Ensure FTS retains correct history +replace_result $sys_datatype_expl SYS_DATATYPE; +eval create table t1 ( + x int, y text, fulltext (y), + row_start $sys_datatype_expl as row start invisible, + row_end $sys_datatype_expl as row end invisible, + period for system_time (row_start, row_end)) +with system versioning engine innodb; +insert into t1 values (1, repeat('LONG', 2048)); +update t1 set x= x + 1; +select x, left(y, 4), length(y), check_row(row_start, row_end) from t1 for system_time all order by x, y; +update t1 set y= 'SHORT'; +select x, left(y, 4), length(y), check_row(row_start, row_end) from t1 for system_time all order by x, y; +drop tables t1; + --echo ### Issue tempesta-tech/mariadb#365, bug 7 (duplicate of historical row) create or replace table t1 (a int primary key, b int) with system versioning engine myisam; @@ -286,4 +301,29 @@ delete history from t1; # cleanup drop table t1; +--echo # +--echo # MDEV-23446 UPDATE does not insert history row if the row is not changed +--echo # +replace_result $sys_datatype_expl SYS_DATATYPE; +eval create table t1 ( + a int, + row_start $sys_datatype_expl as row start invisible, + row_end $sys_datatype_expl as row end invisible, + period for system_time (row_start, row_end)) with system versioning; +insert into t1 values (1); +update t1 set a= 1; +select *, check_row(row_start, row_end) from t1 for system_time all order by row_end; + +--echo # multi-update +create or replace table t2 like t1; +create or replace table t3 like t1; +insert into t2 values (1); +insert into t3 values (1); +update t2, t3 set t2.a= 1, t3.a= 1 where t2.a = t3.a; +select *, check_row(row_start, row_end) from t2 for system_time all order by row_end; +select *, check_row(row_start, row_end) from t2 for system_time all order by row_end; + +# cleanup +drop tables t1, t2, t3; + source suite/versioning/common_finish.inc; diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 171440c41ad..490fa92d312 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -115,6 +115,7 @@ static int prepare_for_fill(TABLE_LIST *tables) tables->init_one_table(&INFORMATION_SCHEMA_NAME, &tbl_name, 0, TL_READ); tables->schema_table= i_s_feedback; + tables->schema_table_reformed= 1; tables->select_lex= thd->lex->first_select_lex(); DBUG_ASSERT(tables->select_lex); tables->table= create_schema_table(thd, tables); diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 64fc319aa22..d3f75dae927 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -2070,13 +2070,9 @@ static void update_connection_info(struct connection_info *cn, { case MYSQL_AUDIT_CONNECTION_CONNECT: setup_connection_connect(cn, event); - if (event->status == 0 && event->proxy_user && event->proxy_user[0]) - log_proxy(cn, event); break; case MYSQL_AUDIT_CONNECTION_CHANGE_USER: *after_action= AA_CHANGE_USER; - if (event->proxy_user && event->proxy_user[0]) - log_proxy(cn, event); break; default:; } @@ -2194,6 +2190,8 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) { case MYSQL_AUDIT_CONNECTION_CONNECT: log_connection(cn, event, event->status ? "FAILED_CONNECT": "CONNECT"); + if (event->status == 0 && event->proxy_user && event->proxy_user[0]) + log_proxy(cn, event); break; case MYSQL_AUDIT_CONNECTION_DISCONNECT: if (use_event_data_for_disconnect) @@ -2203,6 +2201,8 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev) break; case MYSQL_AUDIT_CONNECTION_CHANGE_USER: log_connection(cn, event, "CHANGEUSER"); + if (event->proxy_user && event->proxy_user[0]) + log_proxy(cn, event); break; default:; } diff --git a/sql/opt_split.cc b/sql/opt_split.cc index 6807a623b73..fd7836f55cc 100644 --- a/sql/opt_split.cc +++ b/sql/opt_split.cc @@ -1149,7 +1149,7 @@ bool JOIN_TAB::fix_splitting(SplM_plan_info *spl_plan, bool JOIN::fix_all_splittings_in_plan() { table_map prev_tables= 0; - table_map all_tables= (1 << table_count) - 1; + table_map all_tables= (table_map(1) << table_count) - 1; for (uint tablenr= 0; tablenr < table_count; tablenr++) { POSITION *cur_pos= &best_positions[tablenr]; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 5d006a7518c..be8767af111 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -293,7 +293,15 @@ int TABLE::delete_row() store_record(this, record[1]); vers_update_end(); - return file->ha_update_row(record[1], record[0]); + int err= file->ha_update_row(record[1], record[0]); + /* + MDEV-23644: we get HA_ERR_FOREIGN_DUPLICATE_KEY iff we already got history + row with same trx_id which is the result of foreign key action, so we + don't need one more history row. + */ + if (err == HA_ERR_FOREIGN_DUPLICATE_KEY) + return file->ha_delete_row(record[0]); + return err; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 01e5752def7..8c0e5f0c0ee 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2701,7 +2701,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, delayed_row *row= 0; Delayed_insert *di=thd->di; const Discrete_interval *forced_auto_inc; - size_t user_len, host_len, ip_len; + size_t user_len, host_len, ip_length; DBUG_ENTER("write_delayed"); DBUG_PRINT("enter", ("query = '%s' length %lu", query.str, (ulong) query.length)); @@ -2735,7 +2735,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, goto err; } - user_len= host_len= ip_len= 0; + user_len= host_len= ip_length= 0; row->user= row->host= row->ip= NULL; if (thd->security_ctx) { @@ -2744,11 +2744,11 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, if (thd->security_ctx->host) host_len= strlen(thd->security_ctx->host) + 1; if (thd->security_ctx->ip) - ip_len= strlen(thd->security_ctx->ip) + 1; + ip_length= strlen(thd->security_ctx->ip) + 1; } /* This can't be THREAD_SPECIFIC as it's freed in delayed thread */ if (!(row->record= (char*) my_malloc(table->s->reclength + - user_len + host_len + ip_len, + user_len + host_len + ip_length, MYF(MY_WME)))) goto err; memcpy(row->record, table->record[0], table->s->reclength); @@ -2768,7 +2768,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, if (thd->security_ctx->ip) { row->ip= row->record + table->s->reclength + user_len + host_len; - memcpy(row->ip, thd->security_ctx->ip, ip_len); + memcpy(row->ip, thd->security_ctx->ip, ip_length); } } row->query_id= thd->query_id; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6a52b7d418e..4ddfcabf6c8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2304,8 +2304,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, { bool is_trans= 0; bool table_creation_was_logged= 0; + bool real_table= FALSE; LEX_CSTRING db= table->db; handlerton *table_type= 0; + // reset error state for this table + error= 0; DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p", table->db.str, table->table_name.str, table->table, @@ -2321,9 +2324,35 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, thd->find_temporary_table(table) && table->mdl_request.ticket != NULL)); - if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) || - (drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE)) + if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table)) + real_table= TRUE; + else if (drop_sequence && + table->table->s->table_type != TABLE_TYPE_SEQUENCE) + { + was_table= (table->table->s->table_type == TABLE_TYPE_NORMAL); + was_view= (table->table->s->table_type == TABLE_TYPE_VIEW); + if (if_exists) + { + char buff[FN_REFLEN]; + String tbl_name(buff, sizeof(buff), system_charset_info); + tbl_name.length(0); + tbl_name.append(&db); + tbl_name.append('.'); + tbl_name.append(&table->table_name); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + ER_NOT_SEQUENCE2, ER_THD(thd, ER_NOT_SEQUENCE2), + tbl_name.c_ptr_safe()); + + /* + Our job is done here. This statement was added to avoid executing + unnecessary code farther below which in some strange corner cases + caused the server to crash (see MDEV-17896). + */ + goto log_query; + } error= 1; + goto non_critical_err; + } else { table_creation_was_logged= table->table->s->table_creation_was_logged; @@ -2332,29 +2361,28 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, error= 1; goto err; } - error= 0; table->table= 0; } - if ((drop_temporary && if_exists) || !error) + if ((drop_temporary && if_exists) || !real_table) { /* This handles the case of temporary tables. We have the following cases: . "DROP TEMPORARY" was executed and a temporary table was affected - (i.e. drop_temporary && !error) or the if_exists was specified (i.e. - drop_temporary && if_exists). + (i.e. drop_temporary && !real_table) or the + if_exists was specified (i.e. drop_temporary && if_exists). . "DROP" was executed but a temporary table was affected (.i.e - !error). + !real_table). */ if (!dont_log_query && table_creation_was_logged) { /* - If there is an error, we don't know the type of the engine + If there is an real_table, we don't know the type of the engine at this point. So, we keep it in the trx-cache. */ - is_trans= error ? TRUE : is_trans; + is_trans= real_table ? TRUE : is_trans; if (is_trans) trans_tmp_table_deleted= TRUE; else @@ -2381,7 +2409,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, is no need to proceed with the code that tries to drop a regular table. */ - if (!error) continue; + if (!real_table) continue; } else if (!drop_temporary) { @@ -2397,7 +2425,6 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, reg_ext, 0); } DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); - error= 0; if (drop_temporary || (ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 && table_type == 0) || @@ -2437,6 +2464,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, { non_tmp_error = (drop_temporary ? non_tmp_error : TRUE); error= 1; + /* + non critical error (only for this table), so we continue. + Next we write it to wrong_tables and continue this loop + The same as "goto non_critical_err". + */ } } else @@ -2530,7 +2562,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, } non_tmp_error|= MY_TEST(error); } - +non_critical_err: if (error) { if (wrong_tables.length()) @@ -10031,6 +10063,7 @@ do_continue:; tmp_disable_binlog(thd); create_info->options|=HA_CREATE_TMP_ALTER; + create_info->alias= alter_ctx.table_name; error= create_table_impl(thd, alter_ctx.db, alter_ctx.table_name, alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.get_tmp_path(), diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 36f128a3a0b..7dea9cdea4a 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -8633,11 +8633,18 @@ LEX_CSTRING Charset::collation_specific_name() const for character sets and collations, so a collation name not necessarily starts with the character set name. */ + LEX_CSTRING retval; size_t csname_length= strlen(m_charset->csname); if (strncmp(m_charset->name, m_charset->csname, csname_length)) - return {NULL, 0}; + { + retval.str= NULL; + retval.length= 0; + return retval; + } const char *ptr= m_charset->name + csname_length; - return {ptr, strlen(ptr) }; + retval.str= ptr; + retval.length= strlen(ptr); + return retval; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 9514b193407..367682c74e9 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -52,8 +52,9 @@ compare_record(TABLE*). */ bool records_are_comparable(const TABLE *table) { - return ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) == 0) || - bitmap_is_subset(table->write_set, table->read_set); + return !table->versioned(VERS_TRX_ID) && + (((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) == 0) || + bitmap_is_subset(table->write_set, table->read_set)); } @@ -1081,20 +1082,9 @@ update_begin: } else if (likely(!error)) { - if (has_vers_fields && table->versioned()) - { - if (table->versioned(VERS_TIMESTAMP)) - { - store_record(table, record[2]); - table->mark_columns_per_binlog_row_image(); - error= vers_insert_history_row(table); - restore_record(table, record[2]); - } - if (likely(!error)) - rows_inserted++; - } - if (likely(!error)) - updated++; + if (has_vers_fields && table->versioned(VERS_TRX_ID)) + rows_inserted++; + updated++; } if (likely(!error) && !record_was_same && table_list->has_period()) @@ -1110,6 +1100,19 @@ update_begin: if (unlikely(error) && (!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL))) { + goto error; + } + } + + if (likely(!error) && has_vers_fields && table->versioned(VERS_TIMESTAMP)) + { + store_record(table, record[2]); + table->mark_columns_per_binlog_row_image(); + error= vers_insert_history_row(table); + restore_record(table, record[2]); + if (unlikely(error)) + { +error: /* If (ignore && error is ignorable) we don't have to do anything; otherwise... @@ -1120,10 +1123,11 @@ update_begin: flags|= ME_FATAL; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); - table->file->print_error(error,MYF(flags)); - error= 1; - break; - } + table->file->print_error(error,MYF(flags)); + error= 1; + break; + } + rows_inserted++; } if (table->triggers && @@ -2548,6 +2552,7 @@ int multi_update::send_data(List ¬_used_values) if (!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL)) { +error: /* If (ignore && error == is ignorable) we don't have to do anything; otherwise... @@ -2569,19 +2574,8 @@ int multi_update::send_data(List ¬_used_values) error= 0; updated--; } - else if (has_vers_fields && table->versioned()) + else if (has_vers_fields && table->versioned(VERS_TRX_ID)) { - if (table->versioned(VERS_TIMESTAMP)) - { - store_record(table, record[2]); - if (vers_insert_history_row(table)) - { - restore_record(table, record[2]); - error= 1; - break; - } - restore_record(table, record[2]); - } updated_sys_ver++; } /* non-transactional or transactional table got modified */ @@ -2595,6 +2589,17 @@ int multi_update::send_data(List ¬_used_values) } } } + if (has_vers_fields && table->versioned(VERS_TIMESTAMP)) + { + store_record(table, record[2]); + if (vers_insert_history_row(table)) + { + restore_record(table, record[2]); + goto error; + } + restore_record(table, record[2]); + updated_sys_ver++; + } if (table->triggers && unlikely(table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE))) diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index 03c471c35fb..36fc484b82f 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -767,7 +767,7 @@ void dtuple_convert_back_big_rec( /*========================*/ dict_index_t* index MY_ATTRIBUTE((unused)), /*!< in: index */ - dtuple_t* entry, /*!< in: entry whose data was put to vector */ + dtuple_t* entry, /*!< in/out: entry whose data was put to vector */ big_rec_t* vector) /*!< in, own: big rec vector; it is freed in this function */ { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 345f2a37d5d..d5f58827e3b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3473,10 +3473,12 @@ ha_innobase::init_table_handle_for_HANDLER(void) reset_template(); } -/** Free tablespace resources allocated. */ -void innobase_space_shutdown() +/*********************************************************************//** +Free any resources that were allocated and return failure. +@return always return 1 */ +static int innodb_init_abort() { - DBUG_ENTER("innobase_space_shutdown"); + DBUG_ENTER("innodb_init_abort"); if (fil_system.temp_space) { fil_system.temp_space->close(); @@ -3491,16 +3493,6 @@ void innobase_space_shutdown() #ifdef WITH_INNODB_DISALLOW_WRITES os_event_destroy(srv_allow_writes_event); #endif /* WITH_INNODB_DISALLOW_WRITES */ - - DBUG_VOID_RETURN; -} - -/** Free any resources that were allocated and return failure. -@return always return 1 */ -static int innodb_init_abort() -{ - DBUG_ENTER("innodb_init_abort"); - innobase_space_shutdown(); DBUG_RETURN(1); } @@ -4309,7 +4301,6 @@ innobase_end(handlerton*, ha_panic_function) } innodb_shutdown(); - innobase_space_shutdown(); mysql_mutex_destroy(&commit_cond_m); mysql_cond_destroy(&commit_cond); @@ -8779,6 +8770,20 @@ ha_innobase::update_row( MySQL that the row is not really updated and it should not increase the count of updated rows. This is fix for http://bugs.mysql.com/29157 */ + if (m_prebuilt->versioned_write + && thd_sql_command(m_user_thd) != SQLCOM_ALTER_TABLE + /* Multiple UPDATE of same rows in single transaction create + historical rows only once. */ + && trx->id != table->vers_start_id()) { + error = row_insert_for_mysql((byte*) old_row, + m_prebuilt, + ROW_INS_HISTORICAL); + if (error != DB_SUCCESS) { + goto func_exit; + } + innobase_srv_conc_exit_innodb(m_prebuilt); + innobase_active_small(); + } DBUG_RETURN(HA_ERR_RECORD_IS_THE_SAME); } else { const bool vers_set_fields = m_prebuilt->versioned_write diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index eb2afb93595..b0f6789cde2 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -968,6 +968,3 @@ which is in the prepared state @return 0 or error number */ int innobase_rollback_by_xid(handlerton* hton, XID* xid); - -/** Free tablespace resources allocated. */ -void innobase_space_shutdown(); diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index 04ddf5b0a42..fc774b6ee60 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -544,6 +544,17 @@ struct dtuple_t { @param[in] index index possibly with instantly added columns */ void trim(const dict_index_t& index); + bool vers_history_row() const + { + for (ulint i = 0; i < n_fields; i++) { + const dfield_t* field = &fields[i]; + if (field->type.vers_sys_end()) { + return field->vers_history_row(); + } + } + return false; + } + /** @param info_bits the info_bits of a data tuple @return whether this is a hidden metadata record diff --git a/storage/innobase/include/row0ins.h b/storage/innobase/include/row0ins.h index 34427dc6dc7..9a16394a052 100644 --- a/storage/innobase/include/row0ins.h +++ b/storage/innobase/include/row0ins.h @@ -206,6 +206,7 @@ struct ins_node_t if this is NULL, entry list should be created and buffers for sys fields in row allocated */ void vers_update_end(row_prebuilt_t *prebuilt, bool history_row); + bool vers_history_row() const; /* true if 'row' is historical */ }; /** Create an insert object. diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 8f3024c2d48..616158167bd 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2374,6 +2374,18 @@ row_ins_duplicate_error_in_clust( duplicate: trx->error_info = cursor->index; err = DB_DUPLICATE_KEY; + if (cursor->index->table->versioned() + && entry->vers_history_row()) + { + ulint trx_id_len; + byte *trx_id = rec_get_nth_field( + rec, offsets, n_unique, + &trx_id_len); + ut_ad(trx_id_len == DATA_TRX_ID_LEN); + if (trx->id == trx_read_trx_id(trx_id)) { + err = DB_FOREIGN_DUPLICATE_KEY; + } + } goto func_exit; } } @@ -3588,6 +3600,16 @@ row_ins_get_row_from_select( } } +inline +bool ins_node_t::vers_history_row() const +{ + if (!table->versioned()) + return false; + dfield_t* row_end = dtuple_get_nth_field(row, table->vers_end); + return row_end->vers_history_row(); +} + + /***********************************************************//** Inserts a row to a table. @return DB_SUCCESS if operation successfully completed, else error @@ -3626,12 +3648,31 @@ row_ins( ut_ad(node->state == INS_NODE_INSERT_ENTRIES); while (node->index != NULL) { - if (node->index->type != DICT_FTS) { + dict_index_t *index = node->index; + /* + We do not insert history rows into FTS_DOC_ID_INDEX because + it is unique by FTS_DOC_ID only and we do not want to add + row_end to unique key. Fulltext field works the way new + FTS_DOC_ID is created on every fulltext UPDATE, so holding only + FTS_DOC_ID for history is enough. + */ + const unsigned type = index->type; + if (index->type & DICT_FTS) { + } else if (!(type & DICT_UNIQUE) || index->n_uniq > 1 + || !node->vers_history_row()) { + dberr_t err = row_ins_index_entry_step(node, thr); if (err != DB_SUCCESS) { DBUG_RETURN(err); } + } else { + /* Unique indexes with system versioning must contain + the version end column. The only exception is a hidden + FTS_DOC_ID_INDEX that InnoDB may create on a hidden or + user-created FTS_DOC_ID column. */ + ut_ad(!strcmp(index->name, FTS_DOC_ID_INDEX_NAME)); + ut_ad(!strcmp(index->fields[0].name, FTS_DOC_ID_COL_NAME)); } node->index = dict_table_get_next_index(node->index); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index ea0719a3fc8..5721bc7a64a 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2105,10 +2105,18 @@ row_mysql_unfreeze_data_dictionary( @param buf Buffer to hold start time data */ void thd_get_query_start_data(THD *thd, char *buf); -/** Function restores btr_pcur_t, creates dtuple_t from rec_t, -sets row_end = CURRENT_TIMESTAMP/trx->id, inserts it to a table and updates -table statistics. -This is used in UPDATE CASCADE/SET NULL of a system versioning table. +/** Insert history row when evaluating foreign key referential action. + +1. Create new dtuple_t 'row' from node->historical_row; +2. Update its row_end to current timestamp; +3. Insert it to a table; +4. Update table statistics. + +This is used in UPDATE CASCADE/SET NULL of a system versioned referenced table. + +node->historical_row: dtuple_t containing pointers of row changed by refertial +action. + @param[in] thr current query thread @param[in] node a node which just updated a row in a foreign table @return DB_SUCCESS or some error */ @@ -2118,11 +2126,19 @@ static dberr_t row_update_vers_insert(que_thr_t* thr, upd_node_t* node) dfield_t* row_end; char row_end_data[8]; dict_table_t* table = node->table; + const unsigned zip_size = table->space->zip_size(); ut_ad(table->versioned()); - dtuple_t* row = node->historical_row; - ut_ad(row); - node->historical_row = NULL; + dtuple_t* row; + const ulint n_cols = dict_table_get_n_cols(table); + const ulint n_v_cols = dict_table_get_n_v_cols(table); + + ut_ad(n_cols == dtuple_get_n_fields(node->historical_row)); + ut_ad(n_v_cols == dtuple_get_n_v_fields(node->historical_row)); + + row = dtuple_create_with_vcol(node->historical_heap, n_cols, n_v_cols); + + dict_table_copy_types(row, table); ins_node_t* insert_node = ins_node_create(INS_DIRECT, table, node->historical_heap); @@ -2135,6 +2151,40 @@ static dberr_t row_update_vers_insert(que_thr_t* thr, upd_node_t* node) insert_node->common.parent = thr; ins_node_set_new_row(insert_node, row); + ut_ad(n_cols > DATA_N_SYS_COLS); + // Exclude DB_ROW_ID, DB_TRX_ID, DB_ROLL_PTR + for (ulint i = 0; i < n_cols - DATA_N_SYS_COLS; i++) { + dfield_t *src= dtuple_get_nth_field(node->historical_row, i); + dfield_t *dst= dtuple_get_nth_field(row, i); + dfield_copy(dst, src); + if (dfield_is_ext(src)) { + byte *field_data + = static_cast(dfield_get_data(src)); + ulint ext_len; + ulint field_len = dfield_get_len(src); + + ut_a(field_len >= BTR_EXTERN_FIELD_REF_SIZE); + + ut_a(memcmp(field_data + field_len + - BTR_EXTERN_FIELD_REF_SIZE, + field_ref_zero, + BTR_EXTERN_FIELD_REF_SIZE)); + + byte *data = btr_copy_externally_stored_field( + &ext_len, field_data, zip_size, field_len, + node->historical_heap); + dfield_set_data(dst, data, ext_len); + } + } + + for (ulint i = 0; i < n_v_cols; i++) { + dfield_t *dst= dtuple_get_nth_v_field(row, i); + dfield_t *src= dtuple_get_nth_v_field(node->historical_row, i); + dfield_copy(dst, src); + } + + node->historical_row = NULL; + row_end = dtuple_get_nth_field(row, table->vers_end); if (dict_table_get_nth_col(table, table->vers_end)->vers_native()) { mach_write_to_8(row_end_data, trx->id); diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index f37b810b7eb..2f7eb57bfd3 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -295,12 +295,14 @@ row_build_index_entry_low( continue; } + ut_ad(!(index->type & DICT_FTS)); + ulint len = dfield_get_len(dfield); if (f.prefix_len == 0 && (!dfield_is_ext(dfield) || dict_index_is_clust(index))) { - /* The dfield_copy() above suffices for + /* The *dfield = *dfield2 above suffices for columns that are stored in-page, or for clustered index record columns that are not part of a column prefix in the PRIMARY KEY. */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 746935f5794..6a47751e891 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2546,6 +2546,17 @@ void innodb_shutdown() sync_check_close(); + srv_sys_space.shutdown(); + if (srv_tmp_space.get_sanity_check_status()) { + fil_system.temp_space->close(); + srv_tmp_space.delete_files(); + } + srv_tmp_space.shutdown(); + +#ifdef WITH_INNODB_DISALLOW_WRITES + os_event_destroy(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ + if (srv_was_started && srv_print_verbose_log) { ib::info() << "Shutdown completed; log sequence number " << srv_shutdown_lsn