Commit 045cde1c authored by unknown's avatar unknown

BUG#20257: Fix partition pruning for BIGINT UNSIGNED:

 - Fix problems in the "Interval walking" partition interval analyzer.


mysql-test/r/partition_pruning.result:
  BUG#20257: Add more testcases for partition pruning
mysql-test/t/partition_pruning.test:
  BUG#20257: Add more testcases for partition pruning
sql/sql_partition.cc:
  BUG#20257: Fix partition pruning for BIGINT UNSIGNED, interval walking:
   - provide special handling for an edge case of interval of size 4G-1.
   - Store interval size in ulonglong, not uint (it was possible to miss partitions this way)
   - In get_next_partition_via_walking(), interpret the value of walked-over field as having the 
     same "signedness" as field (this is so because this value was obtained by calling field->val_int())
   - Remove out of date todo comment.
parent 9b7de67c
......@@ -704,3 +704,82 @@ id select_type table partitions type possible_keys key key_len ref rows Extra
2 UNION NULL NULL NULL NULL NULL NULL NULL NULL No tables used
NULL UNION RESULT <union1,2> NULL ALL NULL NULL NULL NULL NULL
drop table t1;
create table t1 (a bigint unsigned not null) partition by range(a) (
partition p0 values less than (10),
partition p1 values less than (100),
partition p2 values less than (1000),
partition p3 values less than (18446744073709551000),
partition p4 values less than (18446744073709551614)
);
insert into t1 values (5),(15),(105),(1005);
insert into t1 values (18446744073709551000+1);
insert into t1 values (18446744073709551614-1);
explain partitions select * from t1 where a < 10;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 system NULL NULL NULL NULL 1
explain partitions select * from t1
where a >= 18446744073709551000-1 and a <= 18446744073709551000+1;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p3,p4 ALL NULL NULL NULL NULL 3 Using where
explain partitions select * from t1
where a between 18446744073709551001 and 18446744073709551002;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551000;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551613;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p4 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a = 18446744073709551614;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1;
create table t1 (a int)
partition by range((a & 0xFF) << 56) (
partition p0 values less than (0x40 << 56),
partition p1 values less than (0x80 << 56),
partition p2 values less than (0xFF << 56)
);
insert into t1 values (0x20), (0x20), (0x41), (0x41), (0xFE), (0xFE);
explain partitions select * from t1 where a=0;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a=0xFE;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2 ALL NULL NULL NULL NULL 2 Using where
explain partitions select * from t1 where a>0xFE and a<= 0xFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1;
create table t1(a bigint unsigned not null) partition by range(a+0) (
partition p1 values less than (10),
partition p2 values less than (20),
partition p3 values less than (2305561538531885056),
partition p4 values less than (2305561538531950591)
);
insert into t1 values (9),(19),(0xFFFF0000FFFF000-1), (0xFFFF0000FFFFFFF-1);
insert into t1 values (9),(19),(0xFFFF0000FFFF000-1), (0xFFFF0000FFFFFFF-1);
explain partitions select * from t1 where
a >= 2305561538531885056-10 and a <= 2305561538531885056-8;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p3 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where
a > 0xFFFFFFFFFFFFFFEC and a < 0xFFFFFFFFFFFFFFEE;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain partitions select * from t1 where a>=0 and a <= 0xFFFFFFFFFFFFFFFF;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1,p2,p3,p4 ALL NULL NULL NULL NULL 8 Using where
drop table t1;
create table t1 (a bigint) partition by range(a+0) (
partition p1 values less than (-1000),
partition p2 values less than (-10),
partition p3 values less than (10),
partition p4 values less than (1000)
);
insert into t1 values (-15),(-5),(5),(15),(-15),(-5),(5),(15);
explain partitions select * from t1 where a>-2 and a <=0;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p3 ALL NULL NULL NULL NULL 4 Using where
drop table t1;
......@@ -597,3 +597,69 @@ explain partitions select 1 from t1 union all select 2;
drop table t1;
# BUG#20257: partition pruning test coverage for BIGINT UNSIGNED
create table t1 (a bigint unsigned not null) partition by range(a) (
partition p0 values less than (10),
partition p1 values less than (100),
partition p2 values less than (1000),
partition p3 values less than (18446744073709551000),
partition p4 values less than (18446744073709551614)
);
insert into t1 values (5),(15),(105),(1005);
insert into t1 values (18446744073709551000+1);
insert into t1 values (18446744073709551614-1);
explain partitions select * from t1 where a < 10;
explain partitions select * from t1
where a >= 18446744073709551000-1 and a <= 18446744073709551000+1;
explain partitions select * from t1
where a between 18446744073709551001 and 18446744073709551002;
explain partitions select * from t1 where a = 18446744073709551000;
explain partitions select * from t1 where a = 18446744073709551613;
explain partitions select * from t1 where a = 18446744073709551614;
drop table t1;
create table t1 (a int)
partition by range((a & 0xFF) << 56) (
partition p0 values less than (0x40 << 56),
partition p1 values less than (0x80 << 56),
partition p2 values less than (0xFF << 56)
);
insert into t1 values (0x20), (0x20), (0x41), (0x41), (0xFE), (0xFE);
explain partitions select * from t1 where a=0;
explain partitions select * from t1 where a=0xFE;
explain partitions select * from t1 where a>0xFE and a<= 0xFF;
drop table t1;
create table t1(a bigint unsigned not null) partition by range(a+0) (
partition p1 values less than (10),
partition p2 values less than (20),
partition p3 values less than (2305561538531885056),
partition p4 values less than (2305561538531950591)
);
insert into t1 values (9),(19),(0xFFFF0000FFFF000-1), (0xFFFF0000FFFFFFF-1);
insert into t1 values (9),(19),(0xFFFF0000FFFF000-1), (0xFFFF0000FFFFFFF-1);
explain partitions select * from t1 where
a >= 2305561538531885056-10 and a <= 2305561538531885056-8;
explain partitions select * from t1 where
a > 0xFFFFFFFFFFFFFFEC and a < 0xFFFFFFFFFFFFFFEE;
explain partitions select * from t1 where a>=0 and a <= 0xFFFFFFFFFFFFFFFF;
drop table t1;
create table t1 (a bigint) partition by range(a+0) (
partition p1 values less than (-1000),
partition p2 values less than (-10),
partition p3 values less than (10),
partition p4 values less than (1000)
);
insert into t1 values (-15),(-5),(5),(15),(-15),(-5),(5),(15);
explain partitions select * from t1 where a>-2 and a <=0;
drop table t1;
......@@ -6566,10 +6566,19 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
store_key_image_to_rec(field, max_value, len);
b= field->val_int();
/*
Handle a special case where the distance between interval bounds is
exactly 4G-1. This interval is too big for range walking, and if it is an
(x,y]-type interval then the following "b +=..." code will convert it to
an empty interval by "wrapping around" a + 4G-1 + 1 = a.
*/
if ((ulonglong)b - (ulonglong)a == ~0ULL)
return -1;
a += test(flags & NEAR_MIN);
b += test(!(flags & NEAR_MAX));
uint n_values= b - a;
ulonglong n_values= b - a;
if (n_values > total_parts || n_values > MAX_RANGE_TO_WALK)
return -1;
......@@ -6673,7 +6682,8 @@ static uint32 get_next_partition_via_walking(PARTITION_ITERATOR *part_iter)
while (part_iter->field_vals.cur != part_iter->field_vals.end)
{
longlong dummy;
field->store(part_iter->field_vals.cur++, FALSE);
field->store(part_iter->field_vals.cur++,
((Field_num*)field)->unsigned_flag);
if (part_iter->part_info->is_sub_partitioned() &&
!part_iter->part_info->get_part_partition_id(part_iter->part_info,
&part_id, &dummy) ||
......@@ -6681,8 +6691,6 @@ static uint32 get_next_partition_via_walking(PARTITION_ITERATOR *part_iter)
&part_id, &dummy))
return part_id;
}
//psergey-todo: return partition(part_func(NULL)) here...
part_iter->field_vals.cur= part_iter->field_vals.start;
return NOT_A_PARTITION_ID;
}
......
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