Commit e6230e84 authored by Nikita Malyavin's avatar Nikita Malyavin Committed by Sergei Golubchik

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()`
parent f6ee1324
set system_versioning_alter_history=keep; set system_versioning_alter_history=keep;
# Check conventional partitioning on temporal tables # 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 with system versioning
partition by range columns (x) ( partition by range columns (x) (
partition p0 values less than (100), partition p0 values less than (100),
...@@ -34,7 +38,13 @@ select * from t1 partition (p1) for system_time all; ...@@ -34,7 +38,13 @@ select * from t1 partition (p1) for system_time all;
x x
300 300
# Engine change native <-> non-native versioning prohibited # 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; 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. ERROR HY000: Not allowed for system-versioned `test`.`t1`. Change to/from native system versioning engine is not supported.
## CREATE TABLE ## CREATE TABLE
...@@ -322,14 +332,21 @@ select * from t1 partition (p1sp0); ...@@ -322,14 +332,21 @@ select * from t1 partition (p1sp0);
x x
select * from t1 partition (p1sp1); select * from t1 partition (p1sp1);
x 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 with system versioning
partition by range (a) partition by range (a)
(partition p0 values less than (20) engine innodb, (partition p0 values less than (20) engine innodb,
partition p1 values less than maxvalue engine innodb); partition p1 values less than maxvalue engine innodb);
insert into t1 values (1); insert into t1 values (1);
create or replace table t1 ( 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 ) with system versioning
partition by range(f_int1) partition by range(f_int1)
subpartition by hash(f_int1) subpartition by hash(f_int1)
...@@ -338,7 +355,11 @@ subpartition by hash(f_int1) ...@@ -338,7 +355,11 @@ subpartition by hash(f_int1)
subpartition subpart12 storage engine = 'innodb')); subpartition subpart12 storage engine = 'innodb'));
insert into t1 values (1); insert into t1 values (1);
create or replace table t1 (i int) engine=innodb partition by key(i); 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(); insert into t1 values();
# MDEV-14722 Assertion in ha_commit_trans for sub-statement # MDEV-14722 Assertion in ha_commit_trans for sub-statement
create or replace table t1 (i int) with system versioning create or replace table t1 (i int) with system versioning
......
# 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;
[timestamp]
default-storage-engine=innodb
[myisam]
default-storage-engine=myisam
-- source include/have_partition.inc -- source include/have_partition.inc
-- source suite/versioning/common.inc -- source suite/versioning/common.inc
-- source suite/versioning/engines.inc
set system_versioning_alter_history=keep; set system_versioning_alter_history=keep;
--echo # Check conventional partitioning on temporal tables --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 with system versioning
partition by range columns (x) ( partition by range columns (x) (
partition p0 values less than (100), partition p0 values less than (100),
...@@ -24,8 +30,14 @@ select * from t1 partition (p0) for system_time all; ...@@ -24,8 +30,14 @@ select * from t1 partition (p0) for system_time all;
select * from t1 partition (p1) for system_time all; select * from t1 partition (p1) for system_time all;
--echo # Engine change native <-> non-native versioning prohibited --echo # Engine change native <-> non-native versioning prohibited
--replace_result $default_engine DEFAULT_ENGINE --replace_result $sys_datatype_expl SYS_DATATYPE $default_engine DEFAULT_ENGINE
eval create or replace table t1 (i int) engine=$default_engine with system versioning partition by hash(i); 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 --replace_result $non_default_engine NON_DEFAULT_ENGINE
--error ER_VERS_ALTER_ENGINE_PROHIBITED --error ER_VERS_ALTER_ENGINE_PROHIBITED
eval alter table t1 engine=$non_default_engine; eval alter table t1 engine=$non_default_engine;
...@@ -273,15 +285,24 @@ select * from t1 partition (p0sp1); ...@@ -273,15 +285,24 @@ select * from t1 partition (p0sp1);
select * from t1 partition (p1sp0); select * from t1 partition (p1sp0);
select * from t1 partition (p1sp1); 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 with system versioning
partition by range (a) partition by range (a)
(partition p0 values less than (20) engine innodb, (partition p0 values less than (20) engine innodb,
partition p1 values less than maxvalue engine innodb); partition p1 values less than maxvalue engine innodb);
insert into t1 values (1); insert into t1 values (1);
create or replace table t1 ( --replace_result $sys_datatype_expl SYS_DATATYPE
f_int1 integer default 0 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 ) with system versioning
partition by range(f_int1) partition by range(f_int1)
subpartition by hash(f_int1) subpartition by hash(f_int1)
...@@ -291,7 +312,12 @@ subpartition subpart12 storage engine = 'innodb')); ...@@ -291,7 +312,12 @@ subpartition subpart12 storage engine = 'innodb'));
insert into t1 values (1); insert into t1 values (1);
create or replace table t1 (i int) engine=innodb partition by key(i); 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(); insert into t1 values();
--echo # MDEV-14722 Assertion in ha_commit_trans for sub-statement --echo # MDEV-14722 Assertion in ha_commit_trans for sub-statement
......
--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;
...@@ -412,6 +412,22 @@ class ha_partition :public handler ...@@ -412,6 +412,22 @@ class ha_partition :public handler
virtual void return_record_by_parent(); 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 MODULE create/delete handler object
......
...@@ -7035,28 +7035,6 @@ bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info) ...@@ -7035,28 +7035,6 @@ bool Vers_parse_info::fix_implicit(THD *thd, Alter_info *alter_info)
return false; 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( bool Table_scope_and_contents_source_st::vers_fix_system_fields(
THD *thd, Alter_info *alter_info, const TABLE_LIST &create_table, 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( ...@@ -7133,7 +7111,7 @@ bool Table_scope_and_contents_source_st::vers_check_system_fields(
if (!(options & HA_VERSIONED_TABLE)) if (!(options & HA_VERSIONED_TABLE))
return false; return false;
return vers_info.check_sys_fields(create_table.table_name, create_table.db, 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, ...@@ -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) 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))
if (check_sys_fields(table_name, share->db, alter_info, native))
return true; return true;
} }
...@@ -7350,7 +7327,7 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name, ...@@ -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, bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db, const Lex_table_name &db,
Alter_info *alter_info, bool native) Alter_info *alter_info)
{ {
if (check_conditions(table_name, db)) if (check_conditions(table_name, db))
return true; return true;
...@@ -7381,8 +7358,7 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name, ...@@ -7381,8 +7358,7 @@ bool Vers_parse_info::check_sys_fields(const Lex_table_name &table_name,
{ {
f_check_unit= VERS_TIMESTAMP; f_check_unit= VERS_TIMESTAMP;
} }
else if (native else if (f->type_handler() == &type_handler_longlong
&& f->type_handler() == &type_handler_longlong
&& (f->flags & UNSIGNED_FLAG) && (f->flags & UNSIGNED_FLAG)
&& f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1)) && f->length == (MY_INT64_NUM_DECIMAL_DIGITS - 1))
{ {
......
...@@ -1993,7 +1993,7 @@ struct Vers_parse_info ...@@ -1993,7 +1993,7 @@ struct Vers_parse_info
TABLE_LIST &src_table, TABLE_LIST &table); TABLE_LIST &src_table, TABLE_LIST &table);
bool check_sys_fields(const Lex_table_name &table_name, bool check_sys_fields(const Lex_table_name &table_name,
const Lex_table_name &db, 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'. 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 ...@@ -2077,8 +2077,6 @@ struct Table_scope_and_contents_source_pod_st // For trivial members
bool table_was_deleted; bool table_was_deleted;
sequence_definition *seq_create_info; sequence_definition *seq_create_info;
bool vers_native(THD *thd) const;
void init() void init()
{ {
bzero(this, sizeof(*this)); bzero(this, sizeof(*this));
...@@ -3456,6 +3454,10 @@ class handler :public Sql_alloc ...@@ -3456,6 +3454,10 @@ class handler :public Sql_alloc
ha_pre_index_end() : ha_pre_index_end() :
pre_inited == RND ? ha_pre_rnd_end() : 0 ); pre_inited == RND ? ha_pre_rnd_end() : 0 );
} }
virtual bool vers_can_native(THD *thd)
{
return ht->flags & HTON_NATIVE_SYS_VERSIONING;
}
/** /**
@brief @brief
......
...@@ -176,21 +176,6 @@ class partition_element :public Sql_alloc ...@@ -176,21 +176,6 @@ class partition_element :public Sql_alloc
DBUG_ASSERT(ev->col_val_array); DBUG_ASSERT(ev->col_val_array);
return ev->col_val_array[idx]; 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 */ #endif /* PARTITION_ELEMENT_INCLUDED */
...@@ -7907,8 +7907,8 @@ ER_UNUSED_24 ...@@ -7907,8 +7907,8 @@ ER_UNUSED_24
ER_VERS_TEMPORARY ER_VERS_TEMPORARY
eng "TEMPORARY tables do not support system versioning" eng "TEMPORARY tables do not support system versioning"
ER_VERS_NOT_SUPPORTED ER_VERS_TRX_PART_HISTORIC_ROW_NOT_SUPPORTED
eng "%s is not supported for %s system-versioned tables" eng "Transactional system versioned tables do not support partitioning by ROW START or ROW END"
ER_INDEX_FILE_FULL ER_INDEX_FILE_FULL
eng "The index file for table '%-.192s' is full" eng "The index file for table '%-.192s' is full"
ER_UPDATED_COLUMN_ONLY_ONCE ER_UPDATED_COLUMN_ONLY_ONCE
......
...@@ -341,8 +341,16 @@ static bool set_up_field_array(THD *thd, TABLE *table, ...@@ -341,8 +341,16 @@ static bool set_up_field_array(THD *thd, TABLE *table,
while ((field= *(ptr++))) while ((field= *(ptr++)))
{ {
if (field->flags & GET_FIXED_FIELDS_FLAG) 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++; num_fields++;
} }
}
if (unlikely(num_fields > MAX_REF_PARTS)) if (unlikely(num_fields > MAX_REF_PARTS))
{ {
char *err_str; char *err_str;
......
...@@ -1781,7 +1781,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, ...@@ -1781,7 +1781,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
goto err; goto err;
DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, row_end)); DBUG_PRINT("info", ("Columns with system versioning: [%d, %d]", row_start, row_end));
versioned= VERS_TIMESTAMP; 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_start_field= row_start;
row_end_field= row_end; row_end_field= row_end;
status_var_increment(thd->status_var.feature_system_versioning); status_var_increment(thd->status_var.feature_system_versioning);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment