summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2019-02-22 22:17:41 +1000
committerSergei Golubchik <serg@mariadb.org>2019-03-29 12:51:19 +0100
commite6230e844c096e321294f5489d6088cfd8f0293f (patch)
treec1eb8c463db1ae4f4124c0b0427f6ef2ad6fa126
parentf6ee132491f45dfe1856a627a686d29efbfa3034 (diff)
downloadmariadb-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.result31
-rw-r--r--mysql-test/suite/versioning/r/partition_innodb.result69
-rw-r--r--mysql-test/suite/versioning/t/partition.combinations5
-rw-r--r--mysql-test/suite/versioning/t/partition.test40
-rw-r--r--mysql-test/suite/versioning/t/partition_innodb.test80
-rw-r--r--sql/ha_partition.h16
-rw-r--r--sql/handler.cc32
-rw-r--r--sql/handler.h8
-rw-r--r--sql/partition_element.h15
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sql_partition.cc8
-rw-r--r--sql/table.cc2
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);