Commit 4d5ae2b3 authored by Aleksey Midenkov's avatar Aleksey Midenkov

MDEV-27217 DELETE partition selection doesn't work for history partitions

LIMIT history switching requires the number of history partitions to
be marked for read: from first to last non-empty plus one empty. The
least we can do is to fail with error message if the needed partition
was not marked for read. As this is handler interface we require new
handler error code to display user-friendly error message.

Switching by INTERVAL works out-of-the-box with
ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET error.
parent f9f6b190
......@@ -522,7 +522,8 @@ enum ha_base_keytype {
#define HA_ERR_TABLESPACE_MISSING 194 /* Missing Tablespace */
#define HA_ERR_SEQUENCE_INVALID_DATA 195
#define HA_ERR_SEQUENCE_RUN_OUT 196
#define HA_ERR_LAST 196 /* Copy of last error nr * */
#define HA_ERR_PARTITION_LIST 197
#define HA_ERR_LAST 197 /* Copy of last error nr * */
/* Number of different errors */
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)
......
......@@ -107,7 +107,8 @@ static const char *handler_error_messages[]=
"Foreign key cascade delete/update exceeds max depth",
"Tablespace is missing for a table",
"Sequence has been run out",
"Sequence values are conflicting"
"Sequence values are conflicting",
"Cannot select partitions"
};
#endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */
......@@ -767,4 +767,36 @@ alter table t1 add x serial;
alter table t1 add partition (partition p1 history);
alter table t1 add partition (partition p2 history);
drop table t1;
#
# MDEV-27217 DELETE partition selection doesn't work for history partitions
#
create table t1 (f char) with system versioning
partition by system_time limit 10 (
partition p0 history,
partition p1 history,
partition p2 history,
partition pn current);
delete from t1 partition (p1);
ERROR HY000: Not allowed for system-versioned table `test`.`t1`
delete from t1 partition (p0, pn);
ERROR HY000: Not allowed for system-versioned table `test`.`t1`
delete from t1 partition (p0, p1);
ERROR HY000: Not allowed for system-versioned table `test`.`t1`
delete from t1 partition (p0, p1, pn);
ERROR HY000: Not allowed for system-versioned table `test`.`t1`
drop table t1;
set timestamp=unix_timestamp('2000-01-01 00:00:00');
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day (
partition p0 history,
partition p1 history,
partition pn current);
set timestamp=unix_timestamp('2000-01-02 00:00:00');
insert t1 values (1);
delete from t1 partition (p0, pn);
ERROR HY000: Not allowed for system-versioned table `test`.`t1`
delete from t1 partition (p0, p1, pn);
ERROR HY000: Not allowed for system-versioned table `test`.`t1`
drop table t1;
set timestamp= default;
# End of 10.3 tests
......@@ -748,6 +748,40 @@ alter table t1 add partition (partition p1 history);
alter table t1 add partition (partition p2 history);
drop table t1;
--echo #
--echo # MDEV-27217 DELETE partition selection doesn't work for history partitions
--echo #
create table t1 (f char) with system versioning
partition by system_time limit 10 (
partition p0 history,
partition p1 history,
partition p2 history,
partition pn current);
--error ER_VERS_NOT_ALLOWED
delete from t1 partition (p1);
--error ER_VERS_NOT_ALLOWED
delete from t1 partition (p0, pn);
--error ER_VERS_NOT_ALLOWED
delete from t1 partition (p0, p1);
--error ER_VERS_NOT_ALLOWED
delete from t1 partition (p0, p1, pn);
drop table t1;
set timestamp=unix_timestamp('2000-01-01 00:00:00');
create or replace table t1 (i int) with system versioning
partition by system_time interval 1 day (
partition p0 history,
partition p1 history,
partition pn current);
set timestamp=unix_timestamp('2000-01-02 00:00:00');
insert t1 values (1);
--error ER_VERS_NOT_ALLOWED
delete from t1 partition (p0, pn);
--error ER_VERS_NOT_ALLOWED
delete from t1 partition (p0, p1, pn);
drop table t1;
set timestamp= default;
--echo # End of 10.3 tests
--source suite/versioning/common_finish.inc
......@@ -3943,8 +3943,9 @@ int ha_partition::external_lock(THD *thd, int lock_type)
These commands may be excluded because working history partition is needed
only for versioned DML. */
thd->lex->sql_command != SQLCOM_SELECT &&
thd->lex->sql_command != SQLCOM_INSERT_SELECT)
m_part_info->vers_set_hist_part(thd);
thd->lex->sql_command != SQLCOM_INSERT_SELECT &&
(error= m_part_info->vers_set_hist_part(thd)))
goto err_handler;
}
DBUG_RETURN(0);
......@@ -4085,6 +4086,7 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type)
/* Add partition to be called in reset(). */
bitmap_set_bit(&m_partitions_to_reset, i);
}
// FIXME: check error?
switch (lock_type)
{
case TL_WRITE_ALLOW_WRITE:
......@@ -4100,7 +4102,7 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type)
// TODO: MDEV-20345 (see above)
thd->lex->sql_command != SQLCOM_SELECT &&
thd->lex->sql_command != SQLCOM_INSERT_SELECT)
m_part_info->vers_set_hist_part(thd);
error= m_part_info->vers_set_hist_part(thd);
default:;
}
DBUG_RETURN(error);
......
......@@ -3977,6 +3977,8 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TABLE_IN_FK_CHECK:
textno= ER_TABLE_IN_FK_CHECK;
break;
case HA_ERR_PARTITION_LIST:
my_error(ER_VERS_NOT_ALLOWED, errflag, table->s->db.str, table->s->table_name.str);
default:
{
/* The error was "unknown" to this function.
......
......@@ -174,6 +174,7 @@ static const char *HA_ERR(int i)
case HA_ERR_LOGGING_IMPOSSIBLE: return "HA_ERR_LOGGING_IMPOSSIBLE";
case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY";
case HA_ERR_PARTITION_LIST : return "HA_ERR_PARTITION_LIST";
}
return "No Error!";
}
......
......@@ -832,8 +832,13 @@ bool partition_info::has_unique_name(partition_element *element)
DBUG_RETURN(TRUE);
}
void partition_info::vers_set_hist_part(THD *thd)
int partition_info::vers_set_hist_part(THD *thd)
{
if (table->pos_in_table_list &&
table->pos_in_table_list->partition_names)
{
return HA_ERR_PARTITION_LIST;
}
if (vers_info->limit)
{
ha_partition *hp= (ha_partition*)(table->file);
......@@ -841,9 +846,11 @@ void partition_info::vers_set_hist_part(THD *thd)
List_iterator<partition_element> it(partitions);
while (next != vers_info->hist_part)
next= it++;
DBUG_ASSERT(bitmap_is_set(&read_partitions, next->id));
ha_rows records= hp->part_records(next);
while ((next= it++) != vers_info->now_part)
{
DBUG_ASSERT(bitmap_is_set(&read_partitions, next->id));
ha_rows next_records= hp->part_records(next);
if (next_records == 0)
break;
......@@ -856,13 +863,13 @@ void partition_info::vers_set_hist_part(THD *thd)
goto warn;
vers_info->hist_part= next;
}
return;
return 0;
}
if (vers_info->interval.is_set())
{
if (vers_info->hist_part->range_value > thd->query_start())
return;
return 0;
partition_element *next= NULL;
List_iterator<partition_element> it(partitions);
......@@ -873,14 +880,15 @@ void partition_info::vers_set_hist_part(THD *thd)
{
vers_info->hist_part= next;
if (next->range_value > thd->query_start())
return;
return 0;
}
}
return;
return 0;
warn:
my_error(WARN_VERS_PART_FULL, MYF(ME_WARNING|ME_ERROR_LOG),
table->s->db.str, table->s->table_name.str,
vers_info->hist_part->partition_name);
return 0;
}
......
......@@ -421,7 +421,7 @@ class partition_info : public Sql_alloc
vers_info->limit= limit;
return !limit;
}
void vers_set_hist_part(THD *thd);
int vers_set_hist_part(THD *thd);
bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */
partition_element *get_partition(uint part_id)
{
......
......@@ -6640,8 +6640,8 @@ ER_BINLOG_UNSAFE_INSERT_TWO_KEYS
ER_TABLE_IN_FK_CHECK
eng "Table is being used in foreign key check"
ER_UNUSED_1
eng "You should never see it"
ER_VERS_NOT_ALLOWED
eng "Not allowed for system-versioned table %`s.%`s"
ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST
eng "INSERT into autoincrement field which is not the first part in the composed primary key is unsafe"
......
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