Commit 64416b1d authored by unknown's avatar unknown
Browse files

Merge spetrunia@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into  mysql.com:/home/psergey/mysql-5.1-ppruning-r5


sql/handler.h:
  Auto merged
sql/item.h:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
parents cf735347 ce782428
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -271,3 +271,10 @@ t1 CREATE TABLE `t1` (
  `b` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) (PARTITION x1 VALUES LESS THAN (6) ENGINE = MyISAM, PARTITION x3 VALUES LESS THAN (8) ENGINE = MyISAM, PARTITION x4 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION x5 VALUES LESS THAN (12) ENGINE = MyISAM, PARTITION x6 VALUES LESS THAN (14) ENGINE = MyISAM, PARTITION x7 VALUES LESS THAN (16) ENGINE = MyISAM, PARTITION x8 VALUES LESS THAN (18) ENGINE = MyISAM, PARTITION x9 VALUES LESS THAN (20) ENGINE = MyISAM)
drop table t1;
create table t1 (a int not null, b int not null) partition by LIST (a+b) (
partition p0 values in (12),
partition p1 values in (14)
);
insert into t1 values (10,1);
ERROR HY000: Table has no partition for value 11
drop table t1;
+45 −0
Original line number Diff line number Diff line
@@ -259,3 +259,48 @@ explain partitions select * from t1 where a is not null;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	p0,p1	ALL	NULL	NULL	NULL	NULL	2	Using where
drop table t1;
create table t1 (a int not null, b int not null, key(a), key(b))
partition by hash(a) partitions 4;
insert into t1 values (1,1),(2,2),(3,3),(4,4);
explain partitions 
select * from t1 X, t1 Y 
where X.b = Y.b and (X.a=1 or X.a=2) and (Y.a=2 or Y.a=3);
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	X	p1,p2	ALL	a,b	NULL	NULL	NULL	4	Using where
1	SIMPLE	Y	p2,p3	ref	a,b	b	4	test.X.b	2	Using where
explain partitions
select * from t1 X, t1 Y where X.a = Y.a and (X.a=1 or X.a=2);
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	X	p1,p2	ALL	a	NULL	NULL	NULL	4	Using where
1	SIMPLE	Y	p1,p2	ref	a	a	4	test.X.a	2	
drop table t1;
create table t1 (a int) partition by hash(a) partitions 20;
insert into t1 values (1),(2),(3);
explain partitions select * from t1 where a >  1 and a < 3;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	p2	ALL	NULL	NULL	NULL	NULL	3	Using where
explain partitions select * from t1 where a >= 1 and a < 3;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	p1,p2	ALL	NULL	NULL	NULL	NULL	3	Using where
explain partitions select * from t1 where a >  1 and a <= 3;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	p2,p3	ALL	NULL	NULL	NULL	NULL	3	Using where
explain partitions select * from t1 where a >= 1 and a <= 3;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	p1,p2,p3	ALL	NULL	NULL	NULL	NULL	3	Using where
drop table t1;
create table t1 (a int, b int) 
partition by list(a) subpartition by hash(b) subpartitions 20 
(
partition p0 values in (0),
partition p1 values in (1),
partition p2 values in (2),
partition p3 values in (3)
);
insert into t1 values (1,1),(2,2),(3,3);
explain partitions select * from t1 where b >  1 and b < 3;
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	p0_sp2,p1_sp2,p2_sp2,p3_sp2	ALL	NULL	NULL	NULL	NULL	3	Using where
explain partitions select * from t1 where b >  1 and b < 3 and (a =1 or a =2);
id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	t1	p1_sp2,p2_sp2	ALL	NULL	NULL	NULL	NULL	3	Using where
+10 −0
Original line number Diff line number Diff line
@@ -343,3 +343,13 @@ ALTER TABLE t1 REORGANIZE PARTITION x0,x1,x2 INTO
show create table t1;
drop table t1;

# Testcase for BUG#15819
create table t1 (a int not null, b int not null) partition by LIST (a+b) (
  partition p0 values in (12),
  partition p1 values in (14)
);
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (10,1);

drop table t1;
+37 −1
Original line number Diff line number Diff line
@@ -230,9 +230,45 @@ create table t1 (a int) partition by hash(a) partitions 2;
insert into t1 values (1),(2);
explain partitions select * from t1 where a is null;

# this selects both
# this uses both partitions
explain partitions select * from t1 where a is not null;
drop table t1;

# Join tests
create table t1 (a int not null, b int not null, key(a), key(b))
  partition by hash(a) partitions 4;
insert into t1 values (1,1),(2,2),(3,3),(4,4);

explain partitions 
select * from t1 X, t1 Y 
where X.b = Y.b and (X.a=1 or X.a=2) and (Y.a=2 or Y.a=3);

explain partitions
select * from t1 X, t1 Y where X.a = Y.a and (X.a=1 or X.a=2);

drop table t1;

# Tests for "short ranges"
create table t1 (a int) partition by hash(a) partitions 20;
insert into t1 values (1),(2),(3);
explain partitions select * from t1 where a >  1 and a < 3;
explain partitions select * from t1 where a >= 1 and a < 3;
explain partitions select * from t1 where a >  1 and a <= 3;
explain partitions select * from t1 where a >= 1 and a <= 3;
drop table t1;

create table t1 (a int, b int) 
 partition by list(a) subpartition by hash(b) subpartitions 20 
(
  partition p0 values in (0),
  partition p1 values in (1),
  partition p2 values in (2),
  partition p3 values in (3)
);
insert into t1 values (1,1),(2,2),(3,3);

explain partitions select * from t1 where b >  1 and b < 3;
explain partitions select * from t1 where b >  1 and b < 3 and (a =1 or a =2);

# No tests for NULLs in RANGE(monotonic_expr()) - they depend on BUG#15447
# being fixed.
+162 −7
Original line number Diff line number Diff line
@@ -620,6 +620,8 @@ typedef struct {
  uint32 end_part;
  bool use_bit_array;
} part_id_range;


/**
 * An enum and a struct to handle partitioning and subpartitioning.
 */
@@ -699,7 +701,109 @@ typedef int (*get_part_id_func)(partition_info *part_info,
                                 longlong *func_value);
typedef uint32 (*get_subpart_id_func)(partition_info *part_info);

class partition_info :public Sql_alloc {

struct st_partition_iter;
#define NOT_A_PARTITION_ID ((uint32)-1)

/*
  A "Get next" function for partition iterator.
  SYNOPSIS
    partition_iter_func()
      part_iter  Partition iterator, you call only "iter.get_next(&iter)"

  RETURN 
    NOT_A_PARTITION_ID if there are no more partitions.
    [sub]partition_id  of the next partition
*/

typedef uint32 (*partition_iter_func)(st_partition_iter* part_iter);


/*
  Partition set iterator. Used to enumerate a set of [sub]partitions
  obtained in partition interval analysis (see get_partitions_in_range_iter).

  For the user, the only meaningful field is get_next, which may be used as
  follows:
             part_iterator.get_next(&part_iterator);
  
  Initialization is done by any of the following calls:
    - get_partitions_in_range_iter-type function call
    - init_single_partition_iterator()
    - init_all_partitions_iterator()
  Cleanup is not needed.
*/

typedef struct st_partition_iter
{
  partition_iter_func get_next;

  union {
    struct {
      uint32 start_part_num;
      uint32 end_part_num;
    };
    struct {
      longlong start_val;
      longlong end_val;
    };
    bool null_returned;
  };
  partition_info *part_info;
} PARTITION_ITERATOR;


/*
  Get an iterator for set of partitions that match given field-space interval

  SYNOPSIS
    get_partitions_in_range_iter()
      part_info   Partitioning info
      is_subpart  
      min_val     Left edge,  field value in opt_range_key format.
      max_val     Right edge, field value in opt_range_key format. 
      flags       Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
                  NO_MAX_RANGE.
      part_iter   Iterator structure to be initialized

  DESCRIPTION
    Functions with this signature are used to perform "Partitioning Interval
    Analysis". This analysis is applicable for any type of [sub]partitioning 
    by some function of a single fieldX. The idea is as follows:
    Given an interval "const1 <=? fieldX <=? const2", find a set of partitions
    that may contain records with value of fieldX within the given interval.

    The min_val, max_val and flags parameters specify the interval.
    The set of partitions is returned by initializing an iterator in *part_iter

  NOTES
    There are currently two functions of this type:
     - get_part_iter_for_interval_via_walking
     - get_part_iter_for_interval_via_mapping

  RETURN 
    0 - No matching partitions, iterator not initialized
    1 - Some partitions would match, iterator intialized for traversing them
   -1 - All partitions would match, iterator not initialized
*/

typedef int (*get_partitions_in_range_iter)(partition_info *part_info,
                                            bool is_subpart,
                                            byte *min_val, byte *max_val,
                                            uint flags,
                                            PARTITION_ITERATOR *part_iter);


/* Initialize the iterator to return a single partition with given part_id */
inline void init_single_partition_iterator(uint32 part_id,
                                           PARTITION_ITERATOR *part_iter);

/* Initialize the iterator to enumerate all partitions */
inline void init_all_partitions_iterator(partition_info *part_info,
                                         PARTITION_ITERATOR *part_iter);

class partition_info : public Sql_alloc
{
public:
  /*
   * Here comes a set of definitions needed for partitioned table handlers.
@@ -729,9 +833,9 @@ class partition_info :public Sql_alloc {
  */
  get_subpart_id_func get_subpartition_id;
 
  /* NULL-terminated list of fields used in partitioned expression */
  /* NULL-terminated array of fields used in partitioned expression */
  Field **part_field_array;
  /* NULL-terminated list of fields used in subpartitioned expression */
  /* NULL-terminated array of fields used in subpartitioned expression */
  Field **subpart_field_array;

  /* 
@@ -748,11 +852,10 @@ class partition_info :public Sql_alloc {
  /* 
    A bitmap of partitions used by the current query. 
    Usage pattern:
    * It is guaranteed that all partitions are set to be unused on query start.
    * The handler->extra(HA_EXTRA_RESET) call at query start/end sets all
      partitions to be unused.
    * Before index/rnd_init(), partition pruning code sets the bits for used
      partitions.
    * The handler->extra(HA_EXTRA_RESET) call at query end sets all partitions
      to be unused.
  */
  MY_BITMAP used_partitions;

@@ -760,6 +863,39 @@ class partition_info :public Sql_alloc {
    longlong *range_int_array;
    LIST_PART_ENTRY *list_array;
  };
  
  /********************************************
   * INTERVAL ANALYSIS
   ********************************************/
  /*
    Partitioning interval analysis function for partitioning, or NULL if 
    interval analysis is not supported for this kind of partitioning.
  */
  get_partitions_in_range_iter get_part_iter_for_interval;
  /*
    Partitioning interval analysis function for subpartitioning, or NULL if
    interval analysis is not supported for this kind of partitioning.
  */
  get_partitions_in_range_iter get_subpart_iter_for_interval;
  
  /*
    Valid iff
    get_part_iter_for_interval=get_part_iter_for_interval_via_walking:
      controls how we'll process "field < C" and "field > C" intervals.
      If the partitioning function F is strictly increasing, then for any x, y
      "x < y" => "F(x) < F(y)" (*), i.e. when we get interval "field < C" 
      we can perform partition pruning on the equivalent "F(field) < F(C)".

      If the partitioning function not strictly increasing (it is simply
      increasing), then instead of (*) we get "x < y" => "F(x) <= F(y)"
      i.e. for interval "field < C" we can perform partition pruning for
      "F(field) <= F(C)".
  */
  bool range_analysis_include_bounds;
  /********************************************
   * INTERVAL ANALYSIS ENDS 
   ********************************************/
  
  char* part_info_string;

  char *part_func_string;
@@ -863,6 +999,25 @@ class partition_info :public Sql_alloc {


#ifdef WITH_PARTITION_STORAGE_ENGINE
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);

inline void init_single_partition_iterator(uint32 part_id,
                                           PARTITION_ITERATOR *part_iter)
{
  part_iter->start_part_num= part_id;
  part_iter->end_part_num= part_id+1;
  part_iter->get_next= get_next_partition_id_range;
}

inline 
void init_all_partitions_iterator(partition_info *part_info,
                                  PARTITION_ITERATOR *part_iter)
{
  part_iter->start_part_num= 0;
  part_iter->end_part_num= part_info->no_parts;
  part_iter->get_next= get_next_partition_id_range;
}

/*
  Answers the question if subpartitioning is used for a certain table
  SYNOPSIS
Loading