diff options
author | Nikita Malyavin <nikitamalyavin@gmail.com> | 2019-02-22 22:17:41 +1000 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2019-03-29 12:51:19 +0100 |
commit | e6230e844c096e321294f5489d6088cfd8f0293f (patch) | |
tree | c1eb8c463db1ae4f4124c0b0427f6ef2ad6fa126 | |
parent | f6ee132491f45dfe1856a627a686d29efbfa3034 (diff) | |
download | mariadb-git-e6230e844c096e321294f5489d6088cfd8f0293f.tar.gz |
MDEV-15951 system versioning by trx id doesn't work with partitioning
Fix partitioning for trx_id-versioned tables.
`partition by hash`, `range` and others now work.
`partition by system_time` is forbidden.
Currently we cannot use row_start and row_end in `partition by`, because
insertion of versioned field is done by engine's handler, as well as
row_start/row_end's value set up, which is a transaction id -- so it's
also forbidden.
The drawback is that it's now impossible to use `partition by key()`
without parameters for such tables, because it references row_start and
row_end implicitly.
* add handler::vers_can_native()
* drop Table_scope_and_contents_source_st::vers_native()
* drop partition_element::find_engine_flag as unused
* forbid versioning partitioning for trx_id as not supported
* adopt vers tests for trx_id partitioning
* forbid any row_end referencing in `partition by` clauses,
including implicit `by key()`
-rw-r--r-- | mysql-test/suite/versioning/r/partition.result | 31 | ||||
-rw-r--r-- | mysql-test/suite/versioning/r/partition_innodb.result | 69 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/partition.combinations | 5 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/partition.test | 40 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/partition_innodb.test | 80 | ||||
-rw-r--r-- | sql/ha_partition.h | 16 | ||||
-rw-r--r-- | sql/handler.cc | 32 | ||||
-rw-r--r-- | sql/handler.h | 8 | ||||
-rw-r--r-- | sql/partition_element.h | 15 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 4 | ||||
-rw-r--r-- | sql/sql_partition.cc | 8 | ||||
-rw-r--r-- | sql/table.cc | 2 |
12 files changed, 244 insertions, 66 deletions
diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index bfec0ce2d4b..3c33967b780 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -1,6 +1,10 @@ set system_versioning_alter_history=keep; # Check conventional partitioning on temporal tables -create table t1 (x int) +create or replace table t1 ( +x 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 partition by range columns (x) ( partition p0 values less than (100), @@ -34,7 +38,13 @@ select * from t1 partition (p1) for system_time all; x 300 # Engine change native <-> non-native versioning prohibited -create or replace table t1 (i int) engine=DEFAULT_ENGINE with system versioning partition by hash(i); +create or replace table t1 ( +i 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)) +engine=DEFAULT_ENGINE +with system versioning partition by hash(i); alter table t1 engine=NON_DEFAULT_ENGINE; ERROR HY000: Not allowed for system-versioned `test`.`t1`. Change to/from native system versioning engine is not supported. ## CREATE TABLE @@ -322,14 +332,21 @@ select * from t1 partition (p1sp0); x select * from t1 partition (p1sp1); x -create or replace table t1 (a bigint) +create or replace table t1 ( +a bigint, +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 partition by range (a) (partition p0 values less than (20) engine innodb, partition p1 values less than maxvalue engine innodb); insert into t1 values (1); create or replace table t1 ( -f_int1 integer default 0 +f_int1 integer default 0, +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 partition by range(f_int1) subpartition by hash(f_int1) @@ -338,7 +355,11 @@ subpartition by hash(f_int1) subpartition subpart12 storage engine = 'innodb')); insert into t1 values (1); create or replace table t1 (i int) engine=innodb partition by key(i); -alter table t1 add system versioning; +alter table t1 +add column row_start SYS_DATATYPE as row start invisible, +add column row_end SYS_DATATYPE as row end invisible, +add period for system_time(row_start, row_end), +add system versioning; insert into t1 values(); # MDEV-14722 Assertion in ha_commit_trans for sub-statement create or replace table t1 (i int) with system versioning diff --git a/mysql-test/suite/versioning/r/partition_innodb.result b/mysql-test/suite/versioning/r/partition_innodb.result new file mode 100644 index 00000000000..3b285365280 --- /dev/null +++ b/mysql-test/suite/versioning/r/partition_innodb.result @@ -0,0 +1,69 @@ +# MDEV-15951 system versioning by trx id doesn't work with partitioning +# currently trx_id does not support partitioning by system_time +create or replace table t1( +i int, +row_start bigint unsigned generated always as row start, +row_end bigint unsigned generated always as row end, +period for system_time(row_start, row_end) +) engine=InnoDB with system versioning partition by system_time ( +partition p0 history, +partition pn current +); +ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1` +create or replace table t1( +i int, +row_start bigint unsigned generated always as row start, +row_end bigint unsigned generated always as row end, +period for system_time(row_start, row_end) +) engine=InnoDB with system versioning; +alter table t1 partition by system_time ( +partition p0 history, +partition pn current +); +ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `#sql-temporary` +create or replace table t ( +a int primary key, +row_start bigint unsigned as row start invisible, +row_end bigint unsigned as row end invisible, +period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by key() ( +partition p1, +partition p2 +); +ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END +create or replace table t ( +a int primary key, +row_start bigint unsigned as row start invisible, +row_end bigint unsigned as row end invisible, +period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by key(a, row_start) ( +partition p1, +partition p2 +); +ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END +create or replace table t ( +a int primary key, +row_start bigint unsigned as row start invisible, +row_end bigint unsigned as row end invisible, +period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by hash(a + row_end * 2) ( +partition p1, +partition p2 +); +ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END +create or replace table t ( +a int primary key, +row_start bigint unsigned as row start invisible, +row_end bigint unsigned as row end invisible, +period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by range columns (a, row_start) ( +partition p1 values less than (100, 100) +); +ERROR HY000: Transactional system versioned tables do not support partitioning by ROW START or ROW END +# Test cleanup +drop database test; +create database test; diff --git a/mysql-test/suite/versioning/t/partition.combinations b/mysql-test/suite/versioning/t/partition.combinations deleted file mode 100644 index 4d73ef5a5ea..00000000000 --- a/mysql-test/suite/versioning/t/partition.combinations +++ /dev/null @@ -1,5 +0,0 @@ -[timestamp] -default-storage-engine=innodb - -[myisam] -default-storage-engine=myisam diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index d9e784b082b..88411468516 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -1,10 +1,16 @@ -- source include/have_partition.inc -- source suite/versioning/common.inc +-- source suite/versioning/engines.inc set system_versioning_alter_history=keep; --echo # Check conventional partitioning on temporal tables -create table t1 (x int) +--replace_result $sys_datatype_expl SYS_DATATYPE +eval create or replace table t1 ( + x 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 partition by range columns (x) ( partition p0 values less than (100), @@ -24,8 +30,14 @@ select * from t1 partition (p0) for system_time all; select * from t1 partition (p1) for system_time all; --echo # Engine change native <-> non-native versioning prohibited ---replace_result $default_engine DEFAULT_ENGINE -eval create or replace table t1 (i int) engine=$default_engine with system versioning partition by hash(i); +--replace_result $sys_datatype_expl SYS_DATATYPE $default_engine DEFAULT_ENGINE +eval create or replace table t1 ( + i 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)) +engine=$default_engine +with system versioning partition by hash(i); --replace_result $non_default_engine NON_DEFAULT_ENGINE --error ER_VERS_ALTER_ENGINE_PROHIBITED eval alter table t1 engine=$non_default_engine; @@ -273,15 +285,24 @@ select * from t1 partition (p0sp1); select * from t1 partition (p1sp0); select * from t1 partition (p1sp1); -create or replace table t1 (a bigint) +--replace_result $sys_datatype_expl SYS_DATATYPE +eval create or replace table t1 ( + a bigint, + 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 partition by range (a) (partition p0 values less than (20) engine innodb, partition p1 values less than maxvalue engine innodb); insert into t1 values (1); -create or replace table t1 ( - f_int1 integer default 0 +--replace_result $sys_datatype_expl SYS_DATATYPE +eval create or replace table t1 ( + f_int1 integer default 0, + 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 partition by range(f_int1) subpartition by hash(f_int1) @@ -291,7 +312,12 @@ subpartition subpart12 storage engine = 'innodb')); insert into t1 values (1); create or replace table t1 (i int) engine=innodb partition by key(i); -alter table t1 add system versioning; +--replace_result $sys_datatype_expl SYS_DATATYPE +eval alter table t1 + add column row_start $sys_datatype_expl as row start invisible, + add column row_end $sys_datatype_expl as row end invisible, + add period for system_time(row_start, row_end), + add system versioning; insert into t1 values(); --echo # MDEV-14722 Assertion in ha_commit_trans for sub-statement diff --git a/mysql-test/suite/versioning/t/partition_innodb.test b/mysql-test/suite/versioning/t/partition_innodb.test new file mode 100644 index 00000000000..bb4fe50ce91 --- /dev/null +++ b/mysql-test/suite/versioning/t/partition_innodb.test @@ -0,0 +1,80 @@ +--source include/have_innodb.inc +--source include/have_partition.inc + +--echo # MDEV-15951 system versioning by trx id doesn't work with partitioning +--echo # currently trx_id does not support partitioning by system_time +--error ER_VERS_FIELD_WRONG_TYPE +create or replace table t1( + i int, + row_start bigint unsigned generated always as row start, + row_end bigint unsigned generated always as row end, + period for system_time(row_start, row_end) +) engine=InnoDB with system versioning partition by system_time ( + partition p0 history, + partition pn current +); + +create or replace table t1( + i int, + row_start bigint unsigned generated always as row start, + row_end bigint unsigned generated always as row end, + period for system_time(row_start, row_end) +) engine=InnoDB with system versioning; + +--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ +--error ER_VERS_FIELD_WRONG_TYPE +alter table t1 partition by system_time ( + partition p0 history, + partition pn current +); + +--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED +create or replace table t ( + a int primary key, + row_start bigint unsigned as row start invisible, + row_end bigint unsigned as row end invisible, + period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by key() ( + partition p1, + partition p2 +); + +--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED +create or replace table t ( + a int primary key, + row_start bigint unsigned as row start invisible, + row_end bigint unsigned as row end invisible, + period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by key(a, row_start) ( + partition p1, + partition p2 +); + +--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED +create or replace table t ( + a int primary key, + row_start bigint unsigned as row start invisible, + row_end bigint unsigned as row end invisible, + period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by hash(a + row_end * 2) ( + partition p1, + partition p2 +); + +--error ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED +create or replace table t ( + a int primary key, + row_start bigint unsigned as row start invisible, + row_end bigint unsigned as row end invisible, + period for system_time(row_start, row_end) +) engine=innodb with system versioning +partition by range columns (a, row_start) ( + partition p1 values less than (100, 100) +); + +--echo # Test cleanup +drop database test; +create database test; diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 202f27840dc..e1f1503f8ec 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -412,6 +412,22 @@ public: virtual void return_record_by_parent(); + virtual bool vers_can_native(THD *thd) + { + if (thd->lex->part_info) + { + // PARTITION BY SYSTEM_TIME is not supported for now + return thd->lex->part_info->part_type != VERSIONING_PARTITION; + } + else + { + bool can= true; + for (uint i= 0; i < m_tot_parts && can; i++) + can= can && m_file[i]->vers_can_native(thd); + return can; + } + } + /* ------------------------------------------------------------------------- MODULE create/delete handler object diff --git a/sql/handler.cc b/sql/handler.cc index e01392d236c..f2ea9365974 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7035,28 +7035,6 @@ bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info) return false; } -bool Table_scope_and_contents_source_pod_st::vers_native(THD *thd) const -{ - if (ha_check_storage_engine_flag(db_type, HTON_NATIVE_SYS_VERSIONING)) - return true; - -#ifdef WITH_PARTITION_STORAGE_ENGINE - partition_info *info= thd->work_part_info; - if (info && !(used_fields & HA_CREATE_USED_ENGINE)) - { - if (handlerton *hton= info->default_engine_type) - return ha_check_storage_engine_flag(hton, HTON_NATIVE_SYS_VERSIONING); - - List_iterator_fast<partition_element> it(info->partitions); - while (partition_element *partition_element= it++) - { - if (partition_element->find_engine_flag(HTON_NATIVE_SYS_VERSIONING)) - return true; - } - } -#endif - return false; -} bool Table_scope_and_contents_source_st::vers_fix_system_fields( THD *thd, Alter_info *alter_info, const TABLE_LIST &create_table, @@ -7133,7 +7111,7 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields( if (!(options & HA_VERSIONED_TABLE)) return false; return vers_info.check_sys_fields(create_table.table_name, create_table.db, - alter_info, vers_native(thd)); + alter_info); } @@ -7242,8 +7220,7 @@ bool Vers_parse_info::fix_alter_info(THD *thd, Alter_info *alter_info, if (alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING) { - bool native= create_info->vers_native(thd); - if (check_sys_fields(table_name, share->db, alter_info, native)) + if (check_sys_fields(table_name, share->db, alter_info)) return true; } @@ -7350,7 +7327,7 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name, bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name, const Lex_table_name &db, - Alter_info *alter_info, bool native) + Alter_info *alter_info) { if (check_conditions(table_name, db)) return true; @@ -7381,8 +7358,7 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name, { f_check_unit= VERS_TIMESTAMP; } - else if (native - && f->type_handler() == &type_handler_longlong + else if (f->type_handler() == &type_handler_longlong && (f->flags & UNSIGNED_FLAG) && f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1)) { diff --git a/sql/handler.h b/sql/handler.h index f3401bdfc48..384166cf5c4 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1993,7 +1993,7 @@ public: TABLE_LIST &src_table, TABLE_LIST &table); bool check_sys_fields(const Lex_table_name &table_name, const Lex_table_name &db, - Alter_info *alter_info, bool native); + Alter_info *alter_info); /** At least one field was specified 'WITH/WITHOUT SYSTEM VERSIONING'. @@ -2077,8 +2077,6 @@ struct Table_scope_and_contents_source_pod_st // For trivial members bool table_was_deleted; sequence_definition *seq_create_info; - bool vers_native(THD *thd) const; - void init() { bzero(this, sizeof(*this)); @@ -3456,6 +3454,10 @@ public: ha_pre_index_end() : pre_inited == RND ? ha_pre_rnd_end() : 0 ); } + virtual bool vers_can_native(THD *thd) + { + return ht->flags & HTON_NATIVE_SYS_VERSIONING; + } /** @brief diff --git a/sql/partition_element.h b/sql/partition_element.h index 45900c77cfc..2c89562adda 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -176,21 +176,6 @@ public: DBUG_ASSERT(ev->col_val_array); return ev->col_val_array[idx]; } - - bool find_engine_flag(uint32 flag) - { - if (ha_check_storage_engine_flag(engine_type, flag)) - return true; - - List_iterator_fast<partition_element> it(subpartitions); - while (partition_element *element= it++) - { - if (element->find_engine_flag(flag)) - return true; - } - - return false; - } }; #endif /* PARTITION_ELEMENT_INCLUDED */ diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 71010ddc111..c7a5a2a48f0 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7907,8 +7907,8 @@ ER_UNUSED_24 ER_VERS_TEMPORARY eng "TEMPORARY tables do not support system versioning" -ER_VERS_NOT_SUPPORTED - eng "%s is not supported for %s system-versioned tables" +ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED + eng "Transactional system versioned tables do not support partitioning by ROW START or ROW END" ER_INDEX_FILE_FULL eng "The index file for table '%-.192s' is full" ER_UPDATED_COLUMN_ONLY_ONCE diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 9e6c333d3c9..80565eab208 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -341,7 +341,15 @@ static bool set_up_field_array(THD *thd, TABLE *table, while ((field= *(ptr++))) { if (field->flags & GET_FIXED_FIELDS_FLAG) + { + if (table->versioned(VERS_TRX_ID) + && unlikely(field->flags & VERS_SYSTEM_FIELD)) + { + my_error(ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED, MYF(0)); + DBUG_RETURN(TRUE); + } num_fields++; + } } if (unlikely(num_fields > MAX_REF_PARTS)) { diff --git a/sql/table.cc b/sql/table.cc index d99dc771ee5..80995abc1f9 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1781,7 +1781,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, goto err; DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, row_end)); versioned= VERS_TIMESTAMP; - vers_can_native= plugin_hton(se_plugin)->flags & HTON_NATIVE_SYS_VERSIONING; + vers_can_native= handler_file->vers_can_native(thd); row_start_field= row_start; row_end_field= row_end; status_var_increment(thd->status_var.feature_system_versioning); |