mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
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).
This commit is contained in:
@ -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;
|
|||||||
--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
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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.
|
|||||||
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.
|
|||||||
{
|
{
|
||||||
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;
|
||||||
|
Reference in New Issue
Block a user