Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2020-12-23 14:52:59 +02:00
commit 0aa02567dd
36 changed files with 593 additions and 94 deletions

View File

@ -1177,9 +1177,6 @@ get_options(int *argc,char ***argv)
if (debug_check_flag) if (debug_check_flag)
my_end_arg= MY_CHECK_ERROR; my_end_arg= MY_CHECK_ERROR;
if (!user)
user= (char *)"root";
/* /*
If something is created and --no-drop is not specified, we drop the If something is created and --no-drop is not specified, we drop the
schema. schema.

View File

@ -6020,12 +6020,9 @@ static bool xtrabackup_prepare_func(char** argv)
srv_shutdown_bg_undo_sources(); srv_shutdown_bg_undo_sources();
srv_purge_shutdown(); srv_purge_shutdown();
buf_flush_sync_all_buf_pools(); buf_flush_sync_all_buf_pools();
innodb_shutdown();
innobase_space_shutdown();
} }
else
innodb_shutdown();
innodb_shutdown();
innodb_free_param(); innodb_free_param();
/* output to metadata file */ /* output to metadata file */

View File

@ -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,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_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,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,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,plug,localhost,ID,0,DISCONNECT,test,,0
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv, TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,

View File

@ -666,7 +666,7 @@ create temporary sequence s;
drop temporary table s; drop temporary table s;
create temporary table s (i int); create temporary table s (i int);
drop temporary sequence s; drop temporary sequence s;
ERROR 42S02: Unknown SEQUENCE: 'test.s' ERROR 42S02: 'test.s' is not a SEQUENCE
drop table s; drop table s;
# #
# MDEV-15115 Assertion failure in CREATE SEQUENCE...ROW_FORMAT=REDUNDANT # MDEV-15115 Assertion failure in CREATE SEQUENCE...ROW_FORMAT=REDUNDANT

View File

@ -489,7 +489,7 @@ drop table s;
create temporary sequence s; create temporary sequence s;
drop temporary table s; drop temporary table s;
create temporary table s (i int); create temporary table s (i int);
--error ER_UNKNOWN_SEQUENCES --error ER_NOT_SEQUENCE2
drop temporary sequence s; drop temporary sequence s;
drop table s; drop table s;

View File

@ -300,4 +300,63 @@ update t1 set p_first_name='Yunxi' where p_id=1;
drop view v2; drop view v2;
drop table t1,t2; drop table t1,t2;
drop sequence s1; 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 # End of 10.3 tests

View File

@ -315,4 +315,68 @@ drop view v2;
drop table t1,t2; drop table t1,t2;
drop sequence s1; 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 --echo # End of 10.3 tests

View File

@ -70,6 +70,11 @@ returns int
deterministic deterministic
return sys_trx_end = $sys_datatype_max; 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 ~~; delimiter ~~;
eval create or replace function check_row(row_start $sys_datatype_expl, row_end $sys_datatype_expl) eval create or replace function check_row(row_start $sys_datatype_expl, row_end $sys_datatype_expl)
returns varchar(255) returns varchar(255)
@ -86,4 +91,20 @@ begin
end~~ end~~
delimiter ;~~ 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 --enable_query_log

View File

@ -4,5 +4,7 @@ drop procedure if exists verify_trt;
drop procedure if exists verify_trt_dummy; drop procedure if exists verify_trt_dummy;
drop function if exists current_row; drop function if exists current_row;
drop function if exists check_row; drop function if exists check_row;
drop function if exists current_row_ts;
drop function if exists check_row_ts;
--enable_warnings --enable_warnings
--enable_query_log --enable_query_log

View File

@ -130,3 +130,22 @@ ERROR 42S02: Table 'test.xx' doesn't exist
drop procedure pr; drop procedure pr;
drop trigger tr; drop trigger tr;
drop table t1; 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;

View File

@ -400,6 +400,8 @@ Warning 1265 Data truncated for column 'f12' at row 7
SET timestamp = 9; SET timestamp = 9;
REPLACE INTO t2 SELECT * FROM t2; REPLACE INTO t2 SELECT * FROM t2;
DROP TABLE t1, 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 # 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 foreign table is allowed
delete from t2; delete from t2;
drop tables t2, t1; 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;

View File

@ -691,6 +691,13 @@ create table t1 (a int) with system versioning partition by system_time
alter table t1 add partition (partition p2); alter table t1 add partition (partition p2);
ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME` ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME`
drop table t1; 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 # End of 10.3 tests
# #
# MDEV-22283 Server crashes in key_copy or unexpected error 156: The table already existed in the storage engine # MDEV-22283 Server crashes in key_copy or unexpected error 156: The table already existed in the storage engine

View File

@ -5,7 +5,15 @@ sys_trx_start bigint(20) unsigned as row start invisible,
sys_trx_end bigint(20) unsigned as row end invisible, sys_trx_end bigint(20) unsigned as row end invisible,
period for system_time (sys_trx_start, sys_trx_end) period for system_time (sys_trx_start, sys_trx_end)
) with system versioning; ) with system versioning;
# No history inside the transaction
start transaction;
insert into t1 (x) values (1); 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 # ALTER ADD SYSTEM VERSIONING should write to mysql.transaction_registry
set @@system_versioning_alter_history=keep; set @@system_versioning_alter_history=keep;
create or replace table t1 (x int); create or replace table t1 (x int);

View File

@ -241,6 +241,26 @@ B2 salary
1 2500 1 2500
drop table t1; drop table t1;
drop table t2; 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) ### Issue tempesta-tech/mariadb#365, bug 7 (duplicate of historical row)
create or replace table t1 (a int primary key, b int) create or replace table t1 (a int primary key, b int)
with system versioning engine myisam; with system versioning engine myisam;
@ -350,3 +370,32 @@ insert into t1 (a) values (1), (2);
update ignore t1 set a= 3; update ignore t1 set a= 3;
delete history from t1; delete history from t1;
drop table 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;

View File

@ -94,4 +94,19 @@ drop procedure pr;
drop trigger tr; drop trigger tr;
drop table t1; 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 --source suite/versioning/common_finish.inc

View File

@ -421,6 +421,8 @@ REPLACE INTO t2 SELECT * FROM t2;
# Cleanup # Cleanup
DROP TABLE t1, t2; DROP TABLE t1, t2;
set timestamp= default;
set time_zone='+00:00';
--let $datadir= `select @@datadir` --let $datadir= `select @@datadir`
--remove_file $datadir/test/t1.data --remove_file $datadir/test/t1.data
--remove_file $datadir/test/t1.data.2 --remove_file $datadir/test/t1.data.2
@ -458,4 +460,20 @@ insert into t2 values (1), (1);
delete from t2; delete from t2;
drop tables t2, t1; 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 --source suite/versioning/common_finish.inc

View File

@ -643,6 +643,15 @@ alter table t1 add partition (partition p2);
# Cleanup # Cleanup
drop table t1; 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 # End of 10.3 tests
--echo # --echo #

View File

@ -14,7 +14,13 @@ create or replace table t1 (
period for system_time (sys_trx_start, sys_trx_end) period for system_time (sys_trx_start, sys_trx_end)
) with system versioning; ) with system versioning;
--echo # No history inside the transaction
start transaction;
insert into t1 (x) values (1); 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 --echo # ALTER ADD SYSTEM VERSIONING should write to mysql.transaction_registry
set @@system_versioning_alter_history=keep; set @@system_versioning_alter_history=keep;

View File

@ -147,6 +147,21 @@ select @tmp2 = sys_trx_start as B2, salary from t2;
drop table t1; drop table t1;
drop table t2; 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) --echo ### Issue tempesta-tech/mariadb#365, bug 7 (duplicate of historical row)
create or replace table t1 (a int primary key, b int) create or replace table t1 (a int primary key, b int)
with system versioning engine myisam; with system versioning engine myisam;
@ -286,4 +301,29 @@ delete history from t1;
# cleanup # cleanup
drop table t1; 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; source suite/versioning/common_finish.inc;

View File

@ -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->init_one_table(&INFORMATION_SCHEMA_NAME, &tbl_name, 0, TL_READ);
tables->schema_table= i_s_feedback; tables->schema_table= i_s_feedback;
tables->schema_table_reformed= 1;
tables->select_lex= thd->lex->first_select_lex(); tables->select_lex= thd->lex->first_select_lex();
DBUG_ASSERT(tables->select_lex); DBUG_ASSERT(tables->select_lex);
tables->table= create_schema_table(thd, tables); tables->table= create_schema_table(thd, tables);

View File

@ -2070,13 +2070,9 @@ static void update_connection_info(struct connection_info *cn,
{ {
case MYSQL_AUDIT_CONNECTION_CONNECT: case MYSQL_AUDIT_CONNECTION_CONNECT:
setup_connection_connect(cn, event); setup_connection_connect(cn, event);
if (event->status == 0 && event->proxy_user && event->proxy_user[0])
log_proxy(cn, event);
break; break;
case MYSQL_AUDIT_CONNECTION_CHANGE_USER: case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
*after_action= AA_CHANGE_USER; *after_action= AA_CHANGE_USER;
if (event->proxy_user && event->proxy_user[0])
log_proxy(cn, event);
break; break;
default:; default:;
} }
@ -2194,6 +2190,8 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
{ {
case MYSQL_AUDIT_CONNECTION_CONNECT: case MYSQL_AUDIT_CONNECTION_CONNECT:
log_connection(cn, event, event->status ? "FAILED_CONNECT": "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; break;
case MYSQL_AUDIT_CONNECTION_DISCONNECT: case MYSQL_AUDIT_CONNECTION_DISCONNECT:
if (use_event_data_for_disconnect) if (use_event_data_for_disconnect)
@ -2203,6 +2201,8 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
break; break;
case MYSQL_AUDIT_CONNECTION_CHANGE_USER: case MYSQL_AUDIT_CONNECTION_CHANGE_USER:
log_connection(cn, event, "CHANGEUSER"); log_connection(cn, event, "CHANGEUSER");
if (event->proxy_user && event->proxy_user[0])
log_proxy(cn, event);
break; break;
default:; default:;
} }

View File

@ -1149,7 +1149,7 @@ bool JOIN_TAB::fix_splitting(SplM_plan_info *spl_plan,
bool JOIN::fix_all_splittings_in_plan() bool JOIN::fix_all_splittings_in_plan()
{ {
table_map prev_tables= 0; 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++) for (uint tablenr= 0; tablenr < table_count; tablenr++)
{ {
POSITION *cur_pos= &best_positions[tablenr]; POSITION *cur_pos= &best_positions[tablenr];

View File

@ -293,7 +293,15 @@ int TABLE::delete_row()
store_record(this, record[1]); store_record(this, record[1]);
vers_update_end(); 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;
} }

View File

@ -2701,7 +2701,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
delayed_row *row= 0; delayed_row *row= 0;
Delayed_insert *di=thd->di; Delayed_insert *di=thd->di;
const Discrete_interval *forced_auto_inc; 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_ENTER("write_delayed");
DBUG_PRINT("enter", ("query = '%s' length %lu", query.str, DBUG_PRINT("enter", ("query = '%s' length %lu", query.str,
(ulong) query.length)); (ulong) query.length));
@ -2735,7 +2735,7 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
goto err; goto err;
} }
user_len= host_len= ip_len= 0; user_len= host_len= ip_length= 0;
row->user= row->host= row->ip= NULL; row->user= row->host= row->ip= NULL;
if (thd->security_ctx) if (thd->security_ctx)
{ {
@ -2744,11 +2744,11 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic,
if (thd->security_ctx->host) if (thd->security_ctx->host)
host_len= strlen(thd->security_ctx->host) + 1; host_len= strlen(thd->security_ctx->host) + 1;
if (thd->security_ctx->ip) 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 */ /* This can't be THREAD_SPECIFIC as it's freed in delayed thread */
if (!(row->record= (char*) my_malloc(table->s->reclength + if (!(row->record= (char*) my_malloc(table->s->reclength +
user_len + host_len + ip_len, user_len + host_len + ip_length,
MYF(MY_WME)))) MYF(MY_WME))))
goto err; goto err;
memcpy(row->record, table->record[0], table->s->reclength); 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) if (thd->security_ctx->ip)
{ {
row->ip= row->record + table->s->reclength + user_len + host_len; 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; row->query_id= thd->query_id;

View File

@ -2304,8 +2304,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
{ {
bool is_trans= 0; bool is_trans= 0;
bool table_creation_was_logged= 0; bool table_creation_was_logged= 0;
bool real_table= FALSE;
LEX_CSTRING db= table->db; LEX_CSTRING db= table->db;
handlerton *table_type= 0; handlerton *table_type= 0;
// reset error state for this table
error= 0;
DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p", DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p",
table->db.str, table->table_name.str, table->table, 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) && thd->find_temporary_table(table) &&
table->mdl_request.ticket != NULL)); table->mdl_request.ticket != NULL));
if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) || if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table))
(drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE)) 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; error= 1;
goto non_critical_err;
}
else else
{ {
table_creation_was_logged= table->table->s->table_creation_was_logged; 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; error= 1;
goto err; goto err;
} }
error= 0;
table->table= 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: This handles the case of temporary tables. We have the following cases:
. "DROP TEMPORARY" was executed and a temporary table was affected . "DROP TEMPORARY" was executed and a temporary table was affected
(i.e. drop_temporary && !error) or the if_exists was specified (i.e. (i.e. drop_temporary && !real_table) or the
drop_temporary && if_exists). if_exists was specified (i.e. drop_temporary && if_exists).
. "DROP" was executed but a temporary table was affected (.i.e . "DROP" was executed but a temporary table was affected (.i.e
!error). !real_table).
*/ */
if (!dont_log_query && table_creation_was_logged) 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. 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) if (is_trans)
trans_tmp_table_deleted= TRUE; trans_tmp_table_deleted= TRUE;
else 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 is no need to proceed with the code that tries to drop a regular
table. table.
*/ */
if (!error) continue; if (!real_table) continue;
} }
else if (!drop_temporary) 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); reg_ext, 0);
} }
DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
error= 0;
if (drop_temporary || if (drop_temporary ||
(ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 && (ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 &&
table_type == 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); non_tmp_error = (drop_temporary ? non_tmp_error : TRUE);
error= 1; 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 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_tmp_error|= MY_TEST(error);
} }
non_critical_err:
if (error) if (error)
{ {
if (wrong_tables.length()) if (wrong_tables.length())
@ -10031,6 +10063,7 @@ do_continue:;
tmp_disable_binlog(thd); tmp_disable_binlog(thd);
create_info->options|=HA_CREATE_TMP_ALTER; 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, error= create_table_impl(thd, alter_ctx.db, alter_ctx.table_name,
alter_ctx.new_db, alter_ctx.tmp_name, alter_ctx.new_db, alter_ctx.tmp_name,
alter_ctx.get_tmp_path(), alter_ctx.get_tmp_path(),

View File

@ -8633,11 +8633,18 @@ LEX_CSTRING Charset::collation_specific_name() const
for character sets and collations, so a collation for character sets and collations, so a collation
name not necessarily starts with the character set name. name not necessarily starts with the character set name.
*/ */
LEX_CSTRING retval;
size_t csname_length= strlen(m_charset->csname); size_t csname_length= strlen(m_charset->csname);
if (strncmp(m_charset->name, m_charset->csname, csname_length)) 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; const char *ptr= m_charset->name + csname_length;
return {ptr, strlen(ptr) }; retval.str= ptr;
retval.length= strlen(ptr);
return retval;
} }

View File

@ -52,8 +52,9 @@
compare_record(TABLE*). compare_record(TABLE*).
*/ */
bool records_are_comparable(const TABLE *table) { bool records_are_comparable(const TABLE *table) {
return ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ) == 0) || return !table->versioned(VERS_TRX_ID) &&
bitmap_is_subset(table->write_set, table->read_set); (((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)) else if (likely(!error))
{ {
if (has_vers_fields && table->versioned()) if (has_vers_fields && table->versioned(VERS_TRX_ID))
{ rows_inserted++;
if (table->versioned(VERS_TIMESTAMP)) updated++;
{
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 (likely(!error) && !record_was_same && table_list->has_period()) if (likely(!error) && !record_was_same && table_list->has_period())
@ -1110,6 +1100,19 @@ update_begin:
if (unlikely(error) && if (unlikely(error) &&
(!ignore || table->file->is_fatal_error(error, HA_CHECK_ALL))) (!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 If (ignore && error is ignorable) we don't have to
do anything; otherwise... do anything; otherwise...
@ -1120,10 +1123,11 @@ update_begin:
flags|= ME_FATAL; /* Other handler errors are fatal */ flags|= ME_FATAL; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table); prepare_record_for_error_message(error, table);
table->file->print_error(error,MYF(flags)); table->file->print_error(error,MYF(flags));
error= 1; error= 1;
break; break;
} }
rows_inserted++;
} }
if (table->triggers && if (table->triggers &&
@ -2548,6 +2552,7 @@ int multi_update::send_data(List<Item> &not_used_values)
if (!ignore || if (!ignore ||
table->file->is_fatal_error(error, HA_CHECK_ALL)) table->file->is_fatal_error(error, HA_CHECK_ALL))
{ {
error:
/* /*
If (ignore && error == is ignorable) we don't have to If (ignore && error == is ignorable) we don't have to
do anything; otherwise... do anything; otherwise...
@ -2569,19 +2574,8 @@ int multi_update::send_data(List<Item> &not_used_values)
error= 0; error= 0;
updated--; 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++; updated_sys_ver++;
} }
/* non-transactional or transactional table got modified */ /* non-transactional or transactional table got modified */
@ -2595,6 +2589,17 @@ int multi_update::send_data(List<Item> &not_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 && if (table->triggers &&
unlikely(table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, unlikely(table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
TRG_ACTION_AFTER, TRUE))) TRG_ACTION_AFTER, TRUE)))

View File

@ -767,7 +767,7 @@ void
dtuple_convert_back_big_rec( dtuple_convert_back_big_rec(
/*========================*/ /*========================*/
dict_index_t* index MY_ATTRIBUTE((unused)), /*!< in: index */ 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 big_rec_t* vector) /*!< in, own: big rec vector; it is
freed in this function */ freed in this function */
{ {

View File

@ -3473,10 +3473,12 @@ ha_innobase::init_table_handle_for_HANDLER(void)
reset_template(); 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) { if (fil_system.temp_space) {
fil_system.temp_space->close(); fil_system.temp_space->close();
@ -3491,16 +3493,6 @@ void innobase_space_shutdown()
#ifdef WITH_INNODB_DISALLOW_WRITES #ifdef WITH_INNODB_DISALLOW_WRITES
os_event_destroy(srv_allow_writes_event); os_event_destroy(srv_allow_writes_event);
#endif /* WITH_INNODB_DISALLOW_WRITES */ #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); DBUG_RETURN(1);
} }
@ -4309,7 +4301,6 @@ innobase_end(handlerton*, ha_panic_function)
} }
innodb_shutdown(); innodb_shutdown();
innobase_space_shutdown();
mysql_mutex_destroy(&commit_cond_m); mysql_mutex_destroy(&commit_cond_m);
mysql_cond_destroy(&commit_cond); mysql_cond_destroy(&commit_cond);
@ -8779,6 +8770,20 @@ ha_innobase::update_row(
MySQL that the row is not really updated and it MySQL that the row is not really updated and it
should not increase the count of updated rows. should not increase the count of updated rows.
This is fix for http://bugs.mysql.com/29157 */ 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); DBUG_RETURN(HA_ERR_RECORD_IS_THE_SAME);
} else { } else {
const bool vers_set_fields = m_prebuilt->versioned_write const bool vers_set_fields = m_prebuilt->versioned_write

View File

@ -968,6 +968,3 @@ which is in the prepared state
@return 0 or error number */ @return 0 or error number */
int innobase_rollback_by_xid(handlerton* hton, XID* xid); int innobase_rollback_by_xid(handlerton* hton, XID* xid);
/** Free tablespace resources allocated. */
void innobase_space_shutdown();

View File

@ -544,6 +544,17 @@ struct dtuple_t {
@param[in] index index possibly with instantly added columns */ @param[in] index index possibly with instantly added columns */
void trim(const dict_index_t& index); 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 @param info_bits the info_bits of a data tuple
@return whether this is a hidden metadata record @return whether this is a hidden metadata record

View File

@ -206,6 +206,7 @@ struct ins_node_t
if this is NULL, entry list should be created if this is NULL, entry list should be created
and buffers for sys fields in row allocated */ and buffers for sys fields in row allocated */
void vers_update_end(row_prebuilt_t *prebuilt, bool history_row); 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. /** Create an insert object.

View File

@ -2374,6 +2374,18 @@ row_ins_duplicate_error_in_clust(
duplicate: duplicate:
trx->error_info = cursor->index; trx->error_info = cursor->index;
err = DB_DUPLICATE_KEY; 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; 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. Inserts a row to a table.
@return DB_SUCCESS if operation successfully completed, else error @return DB_SUCCESS if operation successfully completed, else error
@ -3626,12 +3648,31 @@ row_ins(
ut_ad(node->state == INS_NODE_INSERT_ENTRIES); ut_ad(node->state == INS_NODE_INSERT_ENTRIES);
while (node->index != NULL) { 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); dberr_t err = row_ins_index_entry_step(node, thr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
DBUG_RETURN(err); 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); node->index = dict_table_get_next_index(node->index);

View File

@ -2105,10 +2105,18 @@ row_mysql_unfreeze_data_dictionary(
@param buf Buffer to hold start time data */ @param buf Buffer to hold start time data */
void thd_get_query_start_data(THD *thd, char *buf); void thd_get_query_start_data(THD *thd, char *buf);
/** Function restores btr_pcur_t, creates dtuple_t from rec_t, /** Insert history row when evaluating foreign key referential action.
sets row_end = CURRENT_TIMESTAMP/trx->id, inserts it to a table and updates
table statistics. 1. Create new dtuple_t 'row' from node->historical_row;
This is used in UPDATE CASCADE/SET NULL of a system versioning table. 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] thr current query thread
@param[in] node a node which just updated a row in a foreign table @param[in] node a node which just updated a row in a foreign table
@return DB_SUCCESS or some error */ @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; dfield_t* row_end;
char row_end_data[8]; char row_end_data[8];
dict_table_t* table = node->table; dict_table_t* table = node->table;
const unsigned zip_size = table->space->zip_size();
ut_ad(table->versioned()); ut_ad(table->versioned());
dtuple_t* row = node->historical_row; dtuple_t* row;
ut_ad(row); const ulint n_cols = dict_table_get_n_cols(table);
node->historical_row = NULL; 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_t* insert_node =
ins_node_create(INS_DIRECT, table, node->historical_heap); 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; insert_node->common.parent = thr;
ins_node_set_new_row(insert_node, row); 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<byte*>(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); row_end = dtuple_get_nth_field(row, table->vers_end);
if (dict_table_get_nth_col(table, table->vers_end)->vers_native()) { if (dict_table_get_nth_col(table, table->vers_end)->vers_native()) {
mach_write_to_8(row_end_data, trx->id); mach_write_to_8(row_end_data, trx->id);

View File

@ -295,12 +295,14 @@ row_build_index_entry_low(
continue; continue;
} }
ut_ad(!(index->type & DICT_FTS));
ulint len = dfield_get_len(dfield); ulint len = dfield_get_len(dfield);
if (f.prefix_len == 0 if (f.prefix_len == 0
&& (!dfield_is_ext(dfield) && (!dfield_is_ext(dfield)
|| dict_index_is_clust(index))) { || 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 columns that are stored in-page, or for
clustered index record columns that are not clustered index record columns that are not
part of a column prefix in the PRIMARY KEY. */ part of a column prefix in the PRIMARY KEY. */

View File

@ -2546,6 +2546,17 @@ void innodb_shutdown()
sync_check_close(); 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) { if (srv_was_started && srv_print_verbose_log) {
ib::info() << "Shutdown completed; log sequence number " ib::info() << "Shutdown completed; log sequence number "
<< srv_shutdown_lsn << srv_shutdown_lsn