diff --git a/mysql-test/suite/versioning/r/foreign,trx_id.rdiff b/mysql-test/suite/versioning/r/foreign,trx_id.rdiff new file mode 100644 index 00000000000..c2c66ed11e1 --- /dev/null +++ b/mysql-test/suite/versioning/r/foreign,trx_id.rdiff @@ -0,0 +1,166 @@ +--- suite/versioning/r/foreign.result ++++ suite/versioning/r/foreign,trx_id.reject +@@ -6,8 +6,8 @@ + ) engine innodb; + create table child( + parent_id int, +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end), + foreign key(parent_id) references parent(id) + on delete restrict +@@ -39,8 +39,8 @@ + ) engine innodb; + create table child( + parent_id int(10) unsigned primary key, +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end), + foreign key(parent_id) references parent(id) + ) engine innodb with system versioning; +@@ -58,19 +58,39 @@ + ) engine innodb; + create table child( + parent_id int, +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end), + foreign key(parent_id) references parent(id) + on delete cascade + on update cascade + ) engine innodb with system versioning; +-ERROR HY000: CASCADE is not supported for TIMESTAMP(6) AS ROW START/END system-versioned tables ++insert into parent values(1); ++insert into child values(1); ++delete from parent where id = 1; ++delete from child where parent_id = 1; ++delete from parent where id = 1; ++select * from child; ++parent_id ++select * from child for system_time all; ++parent_id ++1 ++insert into parent values(1); ++insert into child values(1); ++update parent set id = id + 1; ++select * from child; ++parent_id ++2 ++select * from child for system_time all; ++parent_id ++1 ++2 ++drop table child; + drop table parent; + create or replace table parent ( + id int primary key, +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end) + ) with system versioning + engine innodb; +@@ -97,8 +117,8 @@ + create or replace table child ( + id int primary key, + parent_id int not null, +-row_start timestamp(6) as row start invisible, +-row_end timestamp(6) as row end invisible, ++row_start bigint(20) unsigned as row start invisible, ++row_end bigint(20) unsigned as row end invisible, + period for system_time(row_start, row_end), + constraint `parent-fk` + foreign key (parent_id) references parent (id) +@@ -106,7 +126,18 @@ + on update restrict + ) with system versioning + engine innodb; +-ERROR HY000: CASCADE is not supported for TIMESTAMP(6) AS ROW START/END system-versioned tables ++insert into parent (id) values (3); ++insert into child (id, parent_id) values (3, 3); ++## FIXME: #415 update of foreign constraints is disabled ++delete from child; ++## FIXME END ++delete from parent; ++select * from child; ++id parent_id ++select *, row_start < row_end, row_end < MAXVAL from child for system_time all; ++id parent_id row_start < row_end row_end < MAXVAL ++3 3 1 1 ++drop table child; + drop table parent; + ################# + # Test SET NULL # +@@ -116,22 +147,39 @@ + ) engine innodb; + create table child( + parent_id int, +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end), + foreign key(parent_id) references parent(id) + on delete set null + on update set null + ) engine innodb with system versioning; +-ERROR HY000: SET NULL is not supported for TIMESTAMP(6) AS ROW START/END system-versioned tables ++insert into parent values(1); ++insert into child values(1); ++delete from child; ++insert into child values(1); ++## FIXME: #415 update of foreign constraints is disabled ++delete from child where parent_id = 1; ++## FIXME END ++delete from parent where id = 1; ++select * from child; ++parent_id ++select * from child for system_time from timestamp 0 to timestamp now(6); ++parent_id ++1 ++1 ++delete from child; ++insert into parent values(1); ++insert into child values(1); ++drop table child; + drop table parent; + ########################### + # Parent table is foreign # + ########################### + create or replace table parent( + id int unique key, +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end) + ) engine innodb with system versioning; + create or replace table child( +@@ -162,16 +210,16 @@ + create or replace table a ( + cola int(10) primary key, + v_cola int(10) as (cola mod 10) virtual, +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end) + ) engine=innodb with system versioning; + create index v_cola on a (v_cola); + create or replace table b( + cola int(10), + v_cola int(10), +-sys_start timestamp(6) as row start invisible, +-sys_end timestamp(6) as row end invisible, ++sys_start bigint(20) unsigned as row start invisible, ++sys_end bigint(20) unsigned as row end invisible, + period for system_time(sys_start, sys_end) + ) engine=innodb with system versioning; + alter table b add constraint `v_cola_fk` diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result index 43b05d06ca3..bb9042fff9f 100644 --- a/mysql-test/suite/versioning/r/foreign.result +++ b/mysql-test/suite/versioning/r/foreign.result @@ -6,8 +6,8 @@ id int unique key ) engine innodb; create table child( parent_id int, -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end), foreign key(parent_id) references parent(id) on delete restrict @@ -39,8 +39,8 @@ id int(10) unsigned unique key ) engine innodb; create table child( parent_id int(10) unsigned primary key, -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end), foreign key(parent_id) references parent(id) ) engine innodb with system versioning; @@ -58,43 +58,19 @@ id int unique key ) engine innodb; create table child( parent_id int, -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end), foreign key(parent_id) references parent(id) on delete cascade on update cascade ) engine innodb with system versioning; -insert into parent values(1); -insert into child values(1); -## FIXME: #415 update of foreign constraints is disabled -call mtr.add_suppression("foreign key constraints in timestamp-based temporal table"); -delete from parent where id = 1; -ERROR 42000: Table 'parent' uses an extension that doesn't exist in this MariaDB version -delete from child where parent_id = 1; -## FIXME END -delete from parent where id = 1; -select * from child; -parent_id -select * from child for system_time all; -parent_id -1 -insert into parent values(1); -insert into child values(1); -update parent set id = id + 1; -select * from child; -parent_id -2 -select * from child for system_time all; -parent_id -1 -2 -drop table child; +ERROR HY000: CASCADE is not supported for TIMESTAMP(6) AS ROW START/END system-versioned tables drop table parent; create or replace table parent ( id int primary key, -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end) ) with system versioning engine innodb; @@ -121,8 +97,8 @@ engine innodb; create or replace table child ( id int primary key, parent_id int not null, -row_start SYS_DATATYPE as row start invisible, -row_end SYS_DATATYPE as row end invisible, +row_start timestamp(6) as row start invisible, +row_end timestamp(6) as row end invisible, period for system_time(row_start, row_end), constraint `parent-fk` foreign key (parent_id) references parent (id) @@ -130,18 +106,7 @@ on delete cascade on update restrict ) with system versioning engine innodb; -insert into parent (id) values (3); -insert into child (id, parent_id) values (3, 3); -## FIXME: #415 update of foreign constraints is disabled -delete from child; -## FIXME END -delete from parent; -select * from child; -id parent_id -select *, row_start < row_end, row_end < MAXVAL from child for system_time all; -id parent_id row_start < row_end row_end < MAXVAL -3 3 1 1 -drop table child; +ERROR HY000: CASCADE is not supported for TIMESTAMP(6) AS ROW START/END system-versioned tables drop table parent; ################# # Test SET NULL # @@ -151,39 +116,22 @@ id int unique key ) engine innodb; create table child( parent_id int, -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end), foreign key(parent_id) references parent(id) on delete set null on update set null ) engine innodb with system versioning; -insert into parent values(1); -insert into child values(1); -delete from child; -insert into child values(1); -## FIXME: #415 update of foreign constraints is disabled -delete from child where parent_id = 1; -## FIXME END -delete from parent where id = 1; -select * from child; -parent_id -select * from child for system_time from timestamp 0 to timestamp now(6); -parent_id -1 -1 -delete from child; -insert into parent values(1); -insert into child values(1); -drop table child; +ERROR HY000: SET NULL is not supported for TIMESTAMP(6) AS ROW START/END system-versioned tables drop table parent; ########################### # Parent table is foreign # ########################### create or replace table parent( id int unique key, -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end) ) engine innodb with system versioning; create or replace table child( @@ -214,16 +162,16 @@ drop table parent; create or replace table a ( cola int(10) primary key, v_cola int(10) as (cola mod 10) virtual, -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end) ) engine=innodb with system versioning; create index v_cola on a (v_cola); create or replace table b( cola int(10), v_cola int(10), -sys_start SYS_DATATYPE as row start invisible, -sys_end SYS_DATATYPE as row end invisible, +sys_start timestamp(6) as row start invisible, +sys_end timestamp(6) as row end invisible, period for system_time(sys_start, sys_end) ) engine=innodb with system versioning; alter table b add constraint `v_cola_fk` diff --git a/mysql-test/suite/versioning/r/simple.result b/mysql-test/suite/versioning/r/simple.result index f6a1ba37f53..7b42fed45c5 100644 --- a/mysql-test/suite/versioning/r/simple.result +++ b/mysql-test/suite/versioning/r/simple.result @@ -11,7 +11,7 @@ name varchar(100), salary int(10), constraint `dept-emp-fk` foreign key (dept_id) references dept (dept_id) -on delete cascade +on delete restrict on update restrict ) with system versioning; diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test index 03980c40dbf..040d7564360 100644 --- a/mysql-test/suite/versioning/t/foreign.test +++ b/mysql-test/suite/versioning/t/foreign.test @@ -8,7 +8,6 @@ create table parent( id int unique key ) engine innodb; ---replace_result $sys_datatype_expl SYS_DATATYPE eval create table child( parent_id int, sys_start $sys_datatype_expl as row start invisible, @@ -46,7 +45,6 @@ create table parent( id int(10) unsigned unique key ) engine innodb; ---replace_result $sys_datatype_expl SYS_DATATYPE eval create table child( parent_id int(10) unsigned primary key, sys_start $sys_datatype_expl as row start invisible, @@ -72,7 +70,7 @@ create table parent( id int unique key ) engine innodb; ---replace_result $sys_datatype_expl SYS_DATATYPE +--disable_abort_on_error eval create table child( parent_id int, sys_start $sys_datatype_expl as row start invisible, @@ -82,16 +80,14 @@ eval create table child( on delete cascade on update cascade ) engine innodb with system versioning; +--enable_abort_on_error +if ($MTR_COMBINATION_TRX_ID) { insert into parent values(1); insert into child values(1); ---echo ## FIXME: #415 update of foreign constraints is disabled -call mtr.add_suppression("foreign key constraints in timestamp-based temporal table"); ---error ER_UNSUPPORTED_EXTENSION delete from parent where id = 1; delete from child where parent_id = 1; ---echo ## FIXME END delete from parent where id = 1; select * from child; select * from child for system_time all; @@ -103,9 +99,8 @@ select * from child; select * from child for system_time all; drop table child; +} drop table parent; - ---replace_result $sys_datatype_expl SYS_DATATYPE eval create or replace table parent ( id int primary key, sys_start $sys_datatype_expl as row start invisible, @@ -137,7 +132,7 @@ create or replace table parent ( ) engine innodb; ---replace_result $sys_datatype_expl SYS_DATATYPE +--disable_abort_on_error eval create or replace table child ( id int primary key, parent_id int not null, @@ -150,7 +145,9 @@ eval create or replace table child ( on update restrict ) with system versioning engine innodb; +--enable_abort_on_error +if ($MTR_COMBINATION_TRX_ID) { insert into parent (id) values (3); insert into child (id, parent_id) values (3, 3); --echo ## FIXME: #415 update of foreign constraints is disabled @@ -162,6 +159,7 @@ select * from child; eval select *, row_start < row_end, row_end < $sys_datatype_max from child for system_time all; drop table child; +} drop table parent; --echo ################# @@ -172,7 +170,7 @@ create table parent( id int unique key ) engine innodb; ---replace_result $sys_datatype_expl SYS_DATATYPE +--disable_abort_on_error eval create table child( parent_id int, sys_start $sys_datatype_expl as row start invisible, @@ -182,7 +180,9 @@ eval create table child( on delete set null on update set null ) engine innodb with system versioning; +--enable_abort_on_error +if ($MTR_COMBINATION_TRX_ID) { insert into parent values(1); insert into child values(1); delete from child; @@ -208,13 +208,13 @@ select * from child for system_time from timestamp 0 to timestamp now(6); ## FIXME END drop table child; +} drop table parent; --echo ########################### --echo # Parent table is foreign # --echo ########################### ---replace_result $sys_datatype_expl SYS_DATATYPE eval create or replace table parent( id int unique key, sys_start $sys_datatype_expl as row start invisible, @@ -254,7 +254,6 @@ drop table parent; --echo # crash on DELETE # --echo ################### ---replace_result $sys_datatype_expl SYS_DATATYPE eval create or replace table a ( cola int(10) primary key, v_cola int(10) as (cola mod 10) virtual, @@ -265,7 +264,6 @@ eval create or replace table a ( create index v_cola on a (v_cola); ---replace_result $sys_datatype_expl SYS_DATATYPE eval create or replace table b( cola int(10), v_cola int(10), diff --git a/mysql-test/suite/versioning/t/simple.test b/mysql-test/suite/versioning/t/simple.test index 3790f0b8978..d61e9ffd47c 100644 --- a/mysql-test/suite/versioning/t/simple.test +++ b/mysql-test/suite/versioning/t/simple.test @@ -13,7 +13,7 @@ create or replace table emp ( salary int(10), constraint `dept-emp-fk` foreign key (dept_id) references dept (dept_id) - on delete cascade + on delete restrict on update restrict ) with system versioning; diff --git a/sql/handler.cc b/sql/handler.cc index b1f4eabef47..3d85d4d132c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7343,15 +7343,13 @@ bool Vers_parse_info::check_with_conditions(const char *table_name) const } bool Vers_parse_info::check_sys_fields(const char *table_name, - Alter_info *alter_info, - bool native) const + Alter_info *alter_info, bool native) { List_iterator it(alter_info->create_list); - vers_sys_type_t found= VERS_UNDEFINED; uint found_flag= 0; while (Create_field *f= it++) { - vers_sys_type_t check_unit= VERS_UNDEFINED; + vers_sys_type_t f_check_unit= VERS_UNDEFINED; uint sys_flag= f->flags & VERS_SYSTEM_FIELD; if (!sys_flag) @@ -7371,29 +7369,29 @@ bool Vers_parse_info::check_sys_fields(const char *table_name, f->type_handler() == &type_handler_timestamp2) && f->length == MAX_DATETIME_FULL_WIDTH) { - check_unit= VERS_TIMESTAMP; + f_check_unit= VERS_TIMESTAMP; } else if (native && f->type_handler() == &type_handler_longlong && (f->flags & UNSIGNED_FLAG) && f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1)) { - check_unit= VERS_TRX_ID; + f_check_unit= VERS_TRX_ID; } else { - if (!found) - found= VERS_TIMESTAMP; + if (!check_unit) + check_unit= VERS_TIMESTAMP; goto error; } - if (check_unit) + if (f_check_unit) { - if (found) + if (check_unit) { - if (found == check_unit) + if (check_unit == f_check_unit) { - if (found == VERS_TRX_ID && !TR_table::use_transaction_registry) + if (check_unit == VERS_TRX_ID && !TR_table::use_transaction_registry) { my_error(ER_VERS_TRT_IS_DISABLED, MYF(0)); return true; @@ -7402,13 +7400,13 @@ bool Vers_parse_info::check_sys_fields(const char *table_name, } error: my_error(ER_VERS_FIELD_WRONG_TYPE, MYF(0), f->field_name.str, - found == VERS_TIMESTAMP ? + check_unit == VERS_TIMESTAMP ? "TIMESTAMP(6)" : "BIGINT(20) UNSIGNED", table_name); return true; } - found= check_unit; + check_unit= f_check_unit; } } diff --git a/sql/handler.h b/sql/handler.h index ff7d3ffd3e2..29a837b5ea8 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1722,9 +1722,17 @@ struct Schema_specification_st class Create_field; +enum vers_sys_type_t +{ + VERS_UNDEFINED= 0, + VERS_TIMESTAMP, + VERS_TRX_ID +}; + struct Vers_parse_info { Vers_parse_info() : + check_unit(VERS_UNDEFINED), versioned_fields(false), unversioned_fields(false) {} @@ -1742,6 +1750,7 @@ struct Vers_parse_info start_end_t system_time; start_end_t as_row; + vers_sys_type_t check_unit; void set_system_time(LString start, LString end) { @@ -1773,7 +1782,7 @@ protected: bool need_check(const Alter_info *alter_info) const; bool check_with_conditions(const char *table_name) const; bool check_sys_fields(const char *table_name, Alter_info *alter_info, - bool native) const; + bool native); public: static const LString default_start; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index d1af8d590da..0201a904058 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4469,6 +4469,19 @@ static bool vers_prepare_keys(THD *thd, HA_CREATE_INFO *create_info, Key *key= NULL; while ((key=key_it++)) { + if (key->type == Key::FOREIGN_KEY && + create_info->vers_info.check_unit == VERS_TIMESTAMP) + { + Foreign_key *fk_key= (Foreign_key*) key; + enum enum_fk_option op; + if (fk_modifies_child(op=fk_key->update_opt) || + fk_modifies_child(op=fk_key->delete_opt)) + { + my_error(ER_VERS_NOT_SUPPORTED, MYF(0), fk_option_name(op)->str, + "TIMESTAMP(6) AS ROW START/END"); + return true; + } + } if (key->type != Key::PRIMARY && key->type != Key::UNIQUE) continue; diff --git a/sql/table.h b/sql/table.h index 731021bcaae..a180903d499 100644 --- a/sql/table.h +++ b/sql/table.h @@ -575,13 +575,6 @@ struct TABLE_STATISTICS_CB bool histograms_are_read; }; -enum vers_sys_type_t -{ - VERS_UNDEFINED= 0, - VERS_TIMESTAMP, - VERS_TRX_ID -}; - /** This structure is shared between different table objects. There is one instance of table share per one table in the database. diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index efe5f763263..835ca2ec2d1 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2199,14 +2199,6 @@ row_update_cascade_for_mysql( && (node->is_delete == PLAIN_DELETE || node->update->affects_versioned()); - if (vers_set_fields && !thr->prebuilt->versioned_write) - { - // FIXME: timestamp-based update of row_end in run_again - trx->error_state = DB_UNSUPPORTED; - thr->fk_cascade_depth = 0; - return trx->error_state; - } - for (;;) { if (vers_set_fields) { // FIXME: code duplication with row_update_for_mysql()