diff options
-rw-r--r-- | mysql-test/suite/versioning/r/partition.result | 146 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/partition.combinations | 3 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/partition.test | 58 | ||||
-rw-r--r-- | sql/partition_info.cc | 1 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 8 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 5 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innopart.h | 40 |
7 files changed, 236 insertions, 25 deletions
diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index f4c8ce3b286..ff9f583042a 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -1,3 +1,65 @@ +set @@session.time_zone='+00:00'; +select ifnull(max(trx_id), 0) into @start_trx_id from information_schema.innodb_vtq; +create procedure if not exists verify_vtq() +begin +set @i= 0; +select +@i:= @i + 1 as No, +trx_id > 0 as A, +commit_id >= trx_id as B, +begin_ts > '1-1-1 0:0:0' as C, +commit_ts > begin_ts as D +from information_schema.innodb_vtq +where trx_id > @start_trx_id; +select ifnull(max(trx_id), 0) +into @start_trx_id +from information_schema.innodb_vtq; +end~~ +create function if not exists default_engine() +returns varchar(255) +deterministic +begin +declare e varchar(255); +select lower(engine) from information_schema.engines where support='DEFAULT' into e; +return e; +end~~ +create function if not exists sys_datatype() +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return 'bigint unsigned'; +elseif default_engine() = 'myisam' then +return 'timestamp(6)'; +end if; +return NULL; +end~~ +create function if not exists sys_commit_ts(sys_field varchar(255)) +returns varchar(255) +deterministic +begin +if default_engine() = 'innodb' then +return concat('vtq_commit_ts(', sys_field, ')'); +elseif default_engine() = 'myisam' then +return sys_field; +end if; +return NULL; +end~~ +create procedure if not exists innodb_verify_vtq(recs int) +begin +declare i int default 1; +if default_engine() = 'innodb' then +call verify_vtq; +elseif default_engine() = 'myisam' then +create temporary table tmp (No int, A bool, B bool, C bool, D bool); +while i <= recs do +insert into tmp values (i, 1, 1, 1, 1); +set i= i + 1; +end while; +select * from tmp; +drop table tmp; +end if; +end~~ create table t1 (x int) with system versioning partition by range columns (x) ( @@ -90,21 +152,78 @@ ERROR HY000: Wrong parameters for `BY SYSTEM_TIME`: `AS OF NOW` partition can no alter table t1 drop partition p1; alter table t1 drop partition p0; ERROR HY000: Wrong parameters for `BY SYSTEM_TIME`: one `AS OF NOW` and at least one `VERSIONING` partition required +set @now= now(6); insert into t1 values (1); -select * from t1; -x +set @ts_start= sys_commit_ts('sys_trx_start'); +set @ts_end= sys_commit_ts('sys_trx_end'); +set @str= concat('select x, ', @ts_start, ' < @now as A, ', @ts_end, ' > @now as B from t1 partition (p0) for system_time all'); +prepare select_p0 from @str; +set @str= concat('select x, ', @ts_start, ' > @now as C, ', @ts_end, ' = timestamp\'2038-01-19 03:14:07\' as D from t1 partition (pn) for system_time all'); +prepare select_pn from @str; +execute select_p0; +x A B +execute select_pn; +x C D +1 1 1 +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @now= now(6); +delete from t1; +execute select_p0; +x A B +1 1 1 +execute select_pn; +x C D +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all into @ts1'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +select @ts0 = @ts1; +@ts0 = @ts1 1 -select * from t1 partition (p0); -x -select * from t1 partition (pn); -x +set @now= now(6); +insert into t1 values (2); +execute select_p0; +x A B +1 1 0 +execute select_pn; +x C D +2 1 1 +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @now= now(6); +update t1 set x = x + 1; +execute select_p0; +x A B +1 1 0 +2 1 1 +execute select_pn; +x C D +3 1 1 +drop prepare select_p0; +drop prepare select_pn; +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all where x = 2 into @ts1'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @str= concat('select ', @ts_end, ' from t1 partition (p0) for system_time all where x = 2 into @ts2'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts3'); +prepare stmt from @str; +execute stmt; +drop prepare stmt; +select @ts0 = @ts1; +@ts0 = @ts1 1 -delete from t1; -select * from t1 partition (p0) for system_time all; -x +select @ts2 = @ts3; +@ts2 = @ts3 1 -select * from t1 partition (pn) for system_time all; -x create or replace table t1 (x int) with system versioning partition by system_time limit 1 ( @@ -190,3 +309,8 @@ select * from t1 partition (p1sp1) for system_time all; x 2 drop table t1; +drop procedure verify_vtq; +drop procedure innodb_verify_vtq; +drop function default_engine; +drop function sys_commit_ts; +drop function sys_datatype; diff --git a/mysql-test/suite/versioning/t/partition.combinations b/mysql-test/suite/versioning/t/partition.combinations index 4c1c009e7be..d79429f34f7 100644 --- a/mysql-test/suite/versioning/t/partition.combinations +++ b/mysql-test/suite/versioning/t/partition.combinations @@ -1,10 +1,7 @@ [innodb] -innodb partition default-storage-engine=innodb [myisam] -skip-innodb partition default-storage-engine=myisam - diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index e0500284a6f..6dc7f56923b 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -1,3 +1,5 @@ +-- source suite/versioning/common.inc + ### check System Versioning and conventional partitioning create table t1 (x int) @@ -83,15 +85,57 @@ alter table t1 drop partition p1; --error ER_VERS_WRONG_PARAMS alter table t1 drop partition p0; -# insertion, deletion +# insert, delete, update +set @now= now(6); insert into t1 values (1); -select * from t1; -select * from t1 partition (p0); -select * from t1 partition (pn); +set @ts_start= sys_commit_ts('sys_trx_start'); +set @ts_end= sys_commit_ts('sys_trx_end'); +set @str= concat('select x, ', @ts_start, ' < @now as A, ', @ts_end, ' > @now as B from t1 partition (p0) for system_time all'); +prepare select_p0 from @str; +set @str= concat('select x, ', @ts_start, ' > @now as C, ', @ts_end, ' = timestamp\'2038-01-19 03:14:07\' as D from t1 partition (pn) for system_time all'); +prepare select_pn from @str; +execute select_p0; +execute select_pn; + +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +set @now= now(6); delete from t1; -select * from t1 partition (p0) for system_time all; -select * from t1 partition (pn) for system_time all; +execute select_p0; +execute select_pn; + +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all into @ts1'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +select @ts0 = @ts1; + +set @now= now(6); +insert into t1 values (2); +execute select_p0; +execute select_pn; + +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +set @now= now(6); +update t1 set x = x + 1; +execute select_p0; +execute select_pn; + +drop prepare select_p0; +drop prepare select_pn; + +set @str= concat('select ', @ts_start, ' from t1 partition (p0) for system_time all where x = 2 into @ts1'); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @str= concat('select ', @ts_end, ' from t1 partition (p0) for system_time all where x = 2 into @ts2'); +prepare stmt from @str; execute stmt; drop prepare stmt; +set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts3'); +prepare stmt from @str; execute stmt; drop prepare stmt; + +select @ts0 = @ts1; +select @ts2 = @ts3; # rotation by LIMIT create or replace table t1 (x int) @@ -150,3 +194,5 @@ select * from t1 partition (p1sp0) for system_time all; select * from t1 partition (p1sp1) for system_time all; drop table t1; + +-- source suite/versioning/common_finish.inc diff --git a/sql/partition_info.cc b/sql/partition_info.cc index c1a792c87e0..2b1bc41931d 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1211,6 +1211,7 @@ bool partition_info::vers_setup_2(THD * thd, bool is_create_table_ind) } else if (vers_scan_min_max(thd, el)) { + table->s->stat_trx= NULL; // may be a leak on endless table open error= true; break; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ac3e2edf304..bd8eb6b4d88 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8718,8 +8718,7 @@ no_commit: innobase_srv_conc_enter_innodb(m_prebuilt); vers_set_fields = table->versioned() && ( - (sql_command != SQLCOM_DELETE || - (m_int_table_flags & HA_INNOPART_DISABLED_TABLE_FLAGS)) && + !is_innopart() && sql_command != SQLCOM_CREATE_TABLE) ? ROW_INS_VERSIONED : ROW_INS_NORMAL; @@ -9527,8 +9526,7 @@ ha_innobase::update_row( innobase_srv_conc_enter_innodb(m_prebuilt); - vers_set_fields = m_prebuilt->upd_node->versioned && - (m_int_table_flags & HA_INNOPART_DISABLED_TABLE_FLAGS); + vers_set_fields = m_prebuilt->upd_node->versioned && !is_innopart(); error = row_update_for_mysql((byte*) old_row, m_prebuilt, vers_set_fields); @@ -9652,7 +9650,7 @@ ha_innobase::delete_row( bool vers_set_fields = table->versioned() && - (m_int_table_flags & HA_INNOPART_DISABLED_TABLE_FLAGS) && + !is_innopart() && table->vers_end_field()->is_max(); error = row_update_for_mysql( diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index f4600a6415b..94155fdf18b 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -519,6 +519,11 @@ protected: /** If mysql has locked with external_lock() */ bool m_mysql_has_locked; + + bool is_innopart() + { + return m_share == NULL; + } }; diff --git a/storage/innobase/handler/ha_innopart.h b/storage/innobase/handler/ha_innopart.h index ab445cf25ca..ef66420acb1 100644 --- a/storage/innobase/handler/ha_innopart.h +++ b/storage/innobase/handler/ha_innopart.h @@ -1119,6 +1119,19 @@ private: write_row( uchar* record) { + if (table->versioned()) + { + trx_t* trx = thd_to_trx(ha_thd()); + if (!trx->id) + trx_start_if_not_started_xa(trx, true); + ut_a(trx->id); + ut_a(table->record[0] == record); + bitmap_set_bit(table->write_set, table->vers_start_field()->field_index); + bitmap_set_bit(table->write_set, table->vers_end_field()->field_index); + table->vers_start_field()->set_notnull(); + table->vers_start_field()->store(trx->id, true); + table->vers_end_field()->set_max(); + } return(Partition_helper::ph_write_row(record)); } @@ -1127,6 +1140,31 @@ private: const uchar* old_record, uchar* new_record) { + int err; + if (table->versioned() && table->vers_end_field()->is_max()) { + trx_t* trx = thd_to_trx(ha_thd()); + if (!trx->id) + trx_start_if_not_started_xa(trx, true); + ut_a(trx->id); + ut_a(table->record[0] == new_record); + ut_a(table->record[1] == old_record); + store_record(table, record[2]); // store new_record + restore_record(table, record[1]); // restore old_record + // modify and insert old_record + bitmap_set_bit(table->write_set, table->vers_end_field()->field_index); + table->vers_end_field()->set_notnull(); + table->vers_end_field()->store(trx->id, true); + err = Partition_helper::ph_write_row(const_cast<uchar*>(table->record[0])); + restore_record(table, record[2]); // restore new_record + if (err) + return err; + table->vers_start_field()->store(trx->id, true); + } + if (unlikely(get_part_for_delete(old_record, + new_record, + m_part_info, + &m_last_part))) + return HA_ERR_INTERNAL_ERROR; return(Partition_helper::ph_update_row(old_record, new_record)); } @@ -1145,6 +1183,8 @@ private: ut_a(table->record[0] == record); store_record(table, record[1]); ut_a(trx->id); + bitmap_set_bit(table->write_set, table->vers_end_field()->field_index); + table->vers_end_field()->set_notnull(); table->vers_end_field()->store(trx->id, true); return Partition_helper::ph_update_row(table->record[1], table->record[0]); } |