Commit c3f35ea5 authored by Aleksey Midenkov's avatar Aleksey Midenkov

MDEV-18501 Partition pruning doesn't work for historical queries (refactoring)

SYSTEM_TYPE partitioning: COLUMN properties removed. Partitioning is
now pure RANGE based on UNIX_TIMESTAMP(row_end).

DECIMAL type is now allowed as RANGE partitioning, we can partition by
UNIX_TIMESTAMP() (but not for DATETIME which depends on local timezone
of course).
parent a3e49c0d
...@@ -981,4 +981,31 @@ a MAX(b) ...@@ -981,4 +981,31 @@ a MAX(b)
SHOW status LIKE 'handler_read_key'; SHOW status LIKE 'handler_read_key';
Variable_name Value Variable_name Value
Handler_read_key 4 Handler_read_key 4
#
# MDEV-18501 Partition pruning doesn't work for historical queries
#
set time_zone= '+00:00';
create or replace table t1 (d datetime(6))
partition by range (unix_timestamp(d)) (
partition p0 values less than (1),
partition p1 values less than (maxvalue));
ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
# DECIMAL functions are now allowed, partitioning is done by integer part
create or replace table t1 (d timestamp(6))
partition by range (unix_timestamp(d)) (
partition p0 values less than (946684801),
partition p1 values less than (maxvalue));
insert into t1 values
# go to p0
('2000-01-01 00:00:00'),
('2000-01-01 00:00:00.000001'),
# goes to p1
('2000-01-01 00:00:01');
select * from t1 partition (p0);
d
2000-01-01 00:00:00.000000
2000-01-01 00:00:00.000001
select * from t1 partition (p1);
d
2000-01-01 00:00:01.000000
DROP TABLE t1, t2; DROP TABLE t1, t2;
...@@ -971,4 +971,31 @@ SELECT a, MAX(b) FROM t2 WHERE a IN (10, 100) GROUP BY a; ...@@ -971,4 +971,31 @@ SELECT a, MAX(b) FROM t2 WHERE a IN (10, 100) GROUP BY a;
--echo # Should be no more than 4 reads. --echo # Should be no more than 4 reads.
SHOW status LIKE 'handler_read_key'; SHOW status LIKE 'handler_read_key';
--echo #
--echo # MDEV-18501 Partition pruning doesn't work for historical queries
--echo #
set time_zone= '+00:00';
let $ts= `select unix_timestamp('2000-01-01 00:00:00') + 1`;
--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR
create or replace table t1 (d datetime(6))
partition by range (unix_timestamp(d)) (
partition p0 values less than (1),
partition p1 values less than (maxvalue));
--echo # DECIMAL functions are now allowed, partitioning is done by integer part
eval create or replace table t1 (d timestamp(6))
partition by range (unix_timestamp(d)) (
partition p0 values less than ($ts),
partition p1 values less than (maxvalue));
insert into t1 values
# go to p0
('2000-01-01 00:00:00'),
('2000-01-01 00:00:00.000001'),
# goes to p1
('2000-01-01 00:00:01');
select * from t1 partition (p0);
select * from t1 partition (p1);
DROP TABLE t1, t2; DROP TABLE t1, t2;
...@@ -98,7 +98,7 @@ enum stat_trx_field ...@@ -98,7 +98,7 @@ enum stat_trx_field
class partition_element :public Sql_alloc class partition_element :public Sql_alloc
{ {
public: public:
enum elem_type enum elem_type_enum
{ {
CONVENTIONAL= 0, CONVENTIONAL= 0,
CURRENT, CURRENT,
...@@ -125,19 +125,7 @@ class partition_element :public Sql_alloc ...@@ -125,19 +125,7 @@ class partition_element :public Sql_alloc
bool max_value; // MAXVALUE range bool max_value; // MAXVALUE range
uint32 id; uint32 id;
bool empty; bool empty;
elem_type_enum type;
// TODO: subclass partition_element by partitioning type to avoid such semantic
// mixup
elem_type type()
{
return (elem_type)(int(signed_flag) << 1 | int(max_value));
}
void type(elem_type val)
{
max_value= (bool)(val & 1);
signed_flag= (bool)(val & 2);
}
partition_element() partition_element()
: part_max_rows(0), part_min_rows(0), range_value(0), : part_max_rows(0), part_min_rows(0), range_value(0),
...@@ -148,7 +136,8 @@ class partition_element :public Sql_alloc ...@@ -148,7 +136,8 @@ class partition_element :public Sql_alloc
nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE), nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE),
signed_flag(FALSE), max_value(FALSE), signed_flag(FALSE), max_value(FALSE),
id(UINT_MAX32), id(UINT_MAX32),
empty(true) empty(true),
type(CONVENTIONAL)
{} {}
partition_element(partition_element *part_elem) partition_element(partition_element *part_elem)
: part_max_rows(part_elem->part_max_rows), : part_max_rows(part_elem->part_max_rows),
...@@ -164,13 +153,13 @@ class partition_element :public Sql_alloc ...@@ -164,13 +153,13 @@ class partition_element :public Sql_alloc
nodegroup_id(part_elem->nodegroup_id), nodegroup_id(part_elem->nodegroup_id),
has_null_value(FALSE), has_null_value(FALSE),
id(part_elem->id), id(part_elem->id),
empty(part_elem->empty) empty(part_elem->empty),
type(CONVENTIONAL)
{} {}
~partition_element() {} ~partition_element() {}
part_column_list_val& get_col_val(uint idx) part_column_list_val& get_col_val(uint idx)
{ {
DBUG_ASSERT(type() == CONVENTIONAL || list_val_list.elements == 1);
part_elem_value *ev= list_val_list.head(); part_elem_value *ev= list_val_list.head();
DBUG_ASSERT(ev); DBUG_ASSERT(ev);
DBUG_ASSERT(ev->col_val_array); DBUG_ASSERT(ev->col_val_array);
......
...@@ -894,15 +894,16 @@ bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add) ...@@ -894,15 +894,16 @@ bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add)
DBUG_ASSERT(part_type == VERSIONING_PARTITION); DBUG_ASSERT(part_type == VERSIONING_PARTITION);
DBUG_ASSERT(table->versioned(VERS_TIMESTAMP)); DBUG_ASSERT(table->versioned(VERS_TIMESTAMP));
DBUG_ASSERT(num_columns == 1);
if (!alter_add) if (!alter_add)
{ {
Field *row_end= table->vers_end_field(); Field *row_end= table->vers_end_field();
part_field_list.push_back(row_end->field_name.str, thd->mem_root);
DBUG_ASSERT(part_field_list.elements == 1);
// needed in handle_list_of_fields() // needed in handle_list_of_fields()
row_end->flags|= GET_FIXED_FIELDS_FLAG; row_end->flags|= GET_FIXED_FIELDS_FLAG;
Name_resolution_context *context= &thd->lex->current_select->context;
Item *row_end_item= new (thd->mem_root) Item_field(thd, context, row_end);
Item *row_end_ts= new (thd->mem_root) Item_func_unix_timestamp(thd, row_end_item);
set_part_expr(thd, row_end_ts, false);
} }
if (alter_add) if (alter_add)
...@@ -911,12 +912,12 @@ bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add) ...@@ -911,12 +912,12 @@ bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add)
partition_element *el; partition_element *el;
for(uint32 id= 0; ((el= it++)); id++) for(uint32 id= 0; ((el= it++)); id++)
{ {
DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL); DBUG_ASSERT(el->type != partition_element::CONVENTIONAL);
/* Newly added element is inserted before AS_OF_NOW. */ /* Newly added element is inserted before AS_OF_NOW. */
if (el->id == UINT_MAX32 || el->type() == partition_element::CURRENT) if (el->id == UINT_MAX32 || el->type == partition_element::CURRENT)
{ {
el->id= id; el->id= id;
if (el->type() == partition_element::CURRENT) if (el->type == partition_element::CURRENT)
break; break;
} }
} }
...@@ -1343,13 +1344,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, ...@@ -1343,13 +1344,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
} }
if (part_type == VERSIONING_PARTITION) if (part_type == VERSIONING_PARTITION)
{ {
if (part_elem->type() == partition_element::HISTORY) if (part_elem->type == partition_element::HISTORY)
{ {
hist_parts++; hist_parts++;
} }
else else
{ {
DBUG_ASSERT(part_elem->type() == partition_element::CURRENT); DBUG_ASSERT(part_elem->type == partition_element::CURRENT);
now_parts++; now_parts++;
} }
} }
...@@ -2690,9 +2691,8 @@ bool check_partition_dirs(partition_info *part_info) ...@@ -2690,9 +2691,8 @@ bool check_partition_dirs(partition_info *part_info)
bool partition_info::vers_init_info(THD * thd) bool partition_info::vers_init_info(THD * thd)
{ {
part_type= VERSIONING_PARTITION; part_type= VERSIONING_PARTITION;
list_of_part_fields= TRUE; list_of_part_fields= true;
column_list= TRUE; column_list= false;
num_columns= 1;
vers_info= new (thd->mem_root) Vers_part_info; vers_info= new (thd->mem_root) Vers_part_info;
if (unlikely(!vers_info)) if (unlikely(!vers_info))
return true; return true;
......
...@@ -55,11 +55,11 @@ struct Vers_part_info : public Sql_alloc ...@@ -55,11 +55,11 @@ struct Vers_part_info : public Sql_alloc
if (now_part) if (now_part)
{ {
DBUG_ASSERT(now_part->id != UINT_MAX32); DBUG_ASSERT(now_part->id != UINT_MAX32);
DBUG_ASSERT(now_part->type() == partition_element::CURRENT); DBUG_ASSERT(now_part->type == partition_element::CURRENT);
if (hist_part) if (hist_part)
{ {
DBUG_ASSERT(hist_part->id != UINT_MAX32); DBUG_ASSERT(hist_part->id != UINT_MAX32);
DBUG_ASSERT(hist_part->type() == partition_element::HISTORY); DBUG_ASSERT(hist_part->type == partition_element::HISTORY);
} }
return true; return true;
} }
......
...@@ -8168,7 +8168,7 @@ bool LEX::part_values_current(THD *thd) ...@@ -8168,7 +8168,7 @@ bool LEX::part_values_current(THD *thd)
create_last_non_select_table->table_name.str); create_last_non_select_table->table_name.str);
return true; return true;
} }
elem->type(partition_element::CURRENT); elem->type= partition_element::CURRENT;
DBUG_ASSERT(part_info->vers_info); DBUG_ASSERT(part_info->vers_info);
part_info->vers_info->now_part= elem; part_info->vers_info->now_part= elem;
if (unlikely(part_info->init_column_part(thd))) if (unlikely(part_info->init_column_part(thd)))
...@@ -8202,7 +8202,7 @@ bool LEX::part_values_history(THD *thd) ...@@ -8202,7 +8202,7 @@ bool LEX::part_values_history(THD *thd)
create_last_non_select_table->table_name.str); create_last_non_select_table->table_name.str);
return true; return true;
} }
elem->type(partition_element::HISTORY); elem->type= partition_element::HISTORY;
if (unlikely(part_info->init_column_part(thd))) if (unlikely(part_info->init_column_part(thd)))
return true; return true;
return false; return false;
......
...@@ -1975,7 +1975,6 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) ...@@ -1975,7 +1975,6 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind)
} }
} }
DBUG_ASSERT(part_info->part_type != NOT_A_PARTITION); DBUG_ASSERT(part_info->part_type != NOT_A_PARTITION);
DBUG_ASSERT(part_info->part_type != VERSIONING_PARTITION || part_info->column_list);
/* /*
Partition is defined. We need to verify that partitioning Partition is defined. We need to verify that partitioning
function is correct. function is correct.
...@@ -2008,15 +2007,15 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) ...@@ -2008,15 +2007,15 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind)
{ {
if (part_info->column_list) if (part_info->column_list)
{ {
if (part_info->part_type == VERSIONING_PARTITION &&
part_info->vers_setup_expression(thd))
goto end;
List_iterator<const char> it(part_info->part_field_list); List_iterator<const char> it(part_info->part_field_list);
if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE))) if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE)))
goto end; goto end;
} }
else else
{ {
if (part_info->part_type == VERSIONING_PARTITION &&
part_info->vers_setup_expression(thd))
goto end;
if (unlikely(fix_fields_part_func(thd, part_info->part_expr, if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
table, FALSE, is_create_table_ind))) table, FALSE, is_create_table_ind)))
goto end; goto end;
...@@ -2032,7 +2031,8 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind) ...@@ -2032,7 +2031,8 @@ bool fix_partition_func(THD *thd, TABLE *table, bool is_create_table_ind)
goto end; goto end;
} }
if (unlikely(!part_info->column_list && if (unlikely(!part_info->column_list &&
part_info->part_expr->result_type() != INT_RESULT)) part_info->part_expr->result_type() != INT_RESULT &&
part_info->part_expr->result_type() != DECIMAL_RESULT))
{ {
part_info->report_part_expr_error(FALSE); part_info->report_part_expr_error(FALSE);
goto end; goto end;
...@@ -2541,7 +2541,7 @@ static int add_partition_values(String *str, partition_info *part_info, ...@@ -2541,7 +2541,7 @@ static int add_partition_values(String *str, partition_info *part_info,
} }
else if (part_info->part_type == VERSIONING_PARTITION) else if (part_info->part_type == VERSIONING_PARTITION)
{ {
switch (p_elem->type()) switch (p_elem->type)
{ {
case partition_element::CURRENT: case partition_element::CURRENT:
err+= str->append(STRING_WITH_LEN(" CURRENT")); err+= str->append(STRING_WITH_LEN(" CURRENT"));
...@@ -5321,7 +5321,7 @@ that are reorganised. ...@@ -5321,7 +5321,7 @@ that are reorganised.
partition_element *el; partition_element *el;
while ((el= it++)) while ((el= it++))
{ {
if (el->type() == partition_element::CURRENT) if (el->type == partition_element::CURRENT)
{ {
it.remove(); it.remove();
now_part= el; now_part= el;
...@@ -5417,7 +5417,7 @@ that are reorganised. ...@@ -5417,7 +5417,7 @@ that are reorganised.
{ {
if (tab_part_info->part_type == VERSIONING_PARTITION) if (tab_part_info->part_type == VERSIONING_PARTITION)
{ {
if (part_elem->type() == partition_element::CURRENT) if (part_elem->type == partition_element::CURRENT)
{ {
my_error(ER_VERS_WRONG_PARTS, MYF(0), table->s->table_name.str); my_error(ER_VERS_WRONG_PARTS, MYF(0), table->s->table_name.str);
goto err; goto err;
......
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