List:Commits« Previous MessageNext Message »
From:Sergey Petrunia Date:December 27 2005 12:04pm
Subject:bk commit into 5.1 tree (sergefp:1.1997)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of psergey. When psergey does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1997 05/12/27 15:04:35 sergefp@stripped +8 -0
  WL#2985 "Partition pruning", postreview fixes: Small code fixes and better comments

  sql/sql_partition.cc
    1.19 05/12/27 15:04:27 sergefp@stripped +9 -1
    WL#2985 "Partition pruning", postreview fixes: better comments

  sql/sql_lex.h
    1.214 05/12/27 15:04:27 sergefp@stripped +1 -1
    WL#2985 "Partition pruning", postreview fixes: better comments

  sql/sql_class.cc
    1.229 05/12/27 15:04:27 sergefp@stripped +4 -1
    WL#2985 "Partition pruning", postreview fixes: 
    Set correct max. length of "partitions" column in EXPLAIN output

  sql/opt_range.cc
    1.192 05/12/27 15:04:27 sergefp@stripped +92 -29
    WL#2985 "Partition pruning", postreview fixes: 
    - better comments, local function renames
    - Made SEL_ARG::is_singlepoint() to correctly handle NULL edge values.
    - fix uninitialized variable access: s/res |=/res =/

  sql/item_timefunc.cc
    1.103 05/12/27 15:04:27 sergefp@stripped +30 -0
    WL#2985 "Partition pruning", postreview fixes: better comments

  sql/item.h
    1.187 05/12/27 15:04:27 sergefp@stripped +9 -2
    WL#2985 "Partition pruning", postreview fixes: better comments

  mysql-test/t/partition.test
    1.9 05/12/27 15:04:27 sergefp@stripped +11 -0
    Added testcase for BUG#15819

  mysql-test/r/partition.result
    1.9 05/12/27 15:04:27 sergefp@stripped +7 -0
    Added testcase for BUG#15819

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	sergefp
# Host:	newbox.mylan
# Root:	/home/psergey/mysql-5.1-ppruning-r4

--- 1.186/sql/item.h	2005-12-26 14:53:40 +03:00
+++ 1.187/sql/item.h	2005-12-27 15:04:27 +03:00
@@ -381,13 +381,20 @@
     put values of field_i into table record buffer;
     return item->val_int(); 
   }
+
+  NOTE
+  At the moment function monotonicity is not well defined (and so may be
+  incorrect) for Item trees with parameters/return types that are different
+  from INT_RESULT, may be NULL, or are unsigned.
+  It will be possible to address this issue once the related partitioning bugs
+  (BUG#16002, BUG#15447, BUG#13436) are fixed.
 */
 
 typedef enum monotonicity_info 
 {
    NON_MONOTONIC,              /* none of the below holds */
-   MONOTONIC_INCREASING,       /* F() is unary and "x < y" => "F(x) <  F(y)" */
-   MONOTONIC_STRICT_INCREASING /* F() is unary and "x < y" => "F(x) <= F(y)" */
+   MONOTONIC_INCREASING,       /* F() is unary and (x < y) => (F(x) <= F(y)) */
+   MONOTONIC_STRICT_INCREASING /* F() is unary and (x < y) => (F(x) <  F(y)) */
 } enum_monotonicity_info;
 
 /*************************************************************************/

--- 1.102/sql/item_timefunc.cc	2005-12-22 12:28:50 +03:00
+++ 1.103/sql/item_timefunc.cc	2005-12-27 15:04:27 +03:00
@@ -885,6 +885,21 @@
   return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
 }
 
+
+/*
+  Get information about this Item tree monotonicity
+
+  SYNOPSIS
+    Item_func_to_days::get_monotonicity_info()
+
+  DESCRIPTION
+  Get information about monotonicity of the function represented by this item
+  tree.
+
+  RETURN
+    See enum_monotonicity_info.
+*/
+
 enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
 {
   if (args[0]->type() == Item::FIELD_ITEM)
@@ -1079,6 +1094,21 @@
   (void) get_arg0_date(&ltime, TIME_FUZZY_DATE);
   return (longlong) ltime.year;
 }
+
+
+/*
+  Get information about this Item tree monotonicity
+
+  SYNOPSIS
+    Item_func_to_days::get_monotonicity_info()
+
+  DESCRIPTION
+  Get information about monotonicity of the function represented by this item
+  tree.
+
+  RETURN
+    See enum_monotonicity_info.
+*/
 
 enum_monotonicity_info Item_func_year::get_monotonicity_info() const
 {

--- 1.191/sql/opt_range.cc	2005-12-26 09:46:16 +03:00
+++ 1.192/sql/opt_range.cc	2005-12-27 15:04:27 +03:00
@@ -313,11 +313,46 @@
   }
   SEL_ARG *clone_tree();
 
-  /* Return TRUE if this represents "keypartK = const" or "keypartK IS NULL" */
+
+  /*
+    Check if this SEL_ARG object represents a single-point interval
+
+    SYNOPSIS
+      is_singlepoint()
+    
+    DESCRIPTION
+      Check if this SEL_ARG object (not tree) represents a single-point
+      interval, i.e. if it represents a "keypart = const" or 
+      "keypart IS NULL".
+
+    RETURN
+      TRUE   This SEL_ARG object represents a singlepoint interval
+      FALSE  Otherwise
+  */
+
   bool is_singlepoint()
   {
-    return !min_flag && !max_flag && 
-           !field->key_cmp((byte*) min_value, (byte*)max_value);
+    /* 
+      Check for NEAR_MIN ("strictly less") and NO_MIN_RANGE (-inf < field) 
+      flags, and the same for right edge.
+    */
+    if (min_flag || max_flag)
+      return FALSE;
+    byte *min_val= min_value;
+    byte *max_val= min_value;
+
+    if (maybe_null)
+    {
+      /* First byte is a NULL value indicator */
+      if (*min_val != *max_val)
+        return FALSE;
+
+      if (*min_val)
+        return TRUE; /* This "x IS NULL" */
+      min_val++;
+      max_val++;
+    }
+    return !field->key_cmp(min_val, max_val);
   }
 };
 
@@ -2110,7 +2145,7 @@
    Putting it all together, partitioning module works as follows:
    
    prune_partitions() {
-     call create_partition_index_descrition();
+     call create_partition_index_description();
 
      call get_mm_tree(); // invoke the RangeAnalysisModule
      
@@ -2229,7 +2264,7 @@
   part_num_to_partition_id_func part_num_to_part_id;
 } PART_PRUNE_PARAM;
 
-static bool create_partition_index_descrition(PART_PRUNE_PARAM *prune_par);
+static bool create_partition_index_description(PART_PRUNE_PARAM *prune_par);
 static int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree);
 static int find_used_partitions_imerge(PART_PRUNE_PARAM *ppar,
                                        SEL_IMERGE *imerge);
@@ -2243,7 +2278,7 @@
 static void print_partitioning_index(KEY_PART *parts, KEY_PART *parts_end);
 static void dbug_print_field(Field *field);
 static void dbug_print_segment_range(SEL_ARG *arg, KEY_PART *part);
-static void dbug_print_onepoint_range(SEL_ARG **start, uint num);
+static void dbug_print_singlepoint_range(SEL_ARG **start, uint num);
 #endif
 
 
@@ -2297,7 +2332,7 @@
   range_par->mem_root= &alloc;
   range_par->old_root= thd->mem_root;
 
-  if (create_partition_index_descrition(&prune_param))
+  if (create_partition_index_description(&prune_param))
   {
     mark_all_partitions_as_used(part_info);
     free_root(&alloc,MYF(0));		// Return memory & allocator
@@ -2335,9 +2370,10 @@
 
   if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER)
     goto all_used;
-   
+
   if (tree->merges.is_empty())
   {
+    /* Range analysis has produced a single list of intervals. */
     prune_param.arg_stack_end= prune_param.arg_stack;
     prune_param.cur_part_fields= 0;
     prune_param.cur_subpart_fields= 0;
@@ -2352,14 +2388,30 @@
   {
     if (tree->merges.elements == 1)
     {
-      if (-1 == (res |= find_used_partitions_imerge(&prune_param,
-                                                    tree->merges.head())))
+      /* 
+        Range analysis has produced a "merge" of several intervals lists, a 
+        SEL_TREE that represents an expression in form         
+          sel_imerge = (tree1 OR tree2 OR ... OR treeN)
+        that cannot be reduced to one tree. This can only happen when 
+        partitioning index has several keyparts and the condition is OR of
+        conditions that refer to different key parts. For example, we'll get
+        here for "partitioning_field=const1 OR subpartitioning_field=const2"
+      */
+      if (-1 == (res= find_used_partitions_imerge(&prune_param,
+                                                  tree->merges.head())))
         goto all_used;
     }
     else
     {
-      if (-1 == (res |= find_used_partitions_imerge_list(&prune_param,
-                                                         tree->merges)))
+      /* 
+        Range analysis has produced a list of several imerges, i.e. a
+        structure that represents a condition in form 
+        imerge_list= (sel_imerge1 AND sel_imerge2 AND ... AND sel_imergeN)
+        This is produced for complicated WHERE clauses that range analyzer
+        can't really analyze properly.
+      */
+      if (-1 == (res= find_used_partitions_imerge_list(&prune_param,
+                                                       tree->merges)))
         goto all_used;
     }
   }
@@ -2384,12 +2436,19 @@
 
 
 /*
-  Store key image to table record
+  Store field key image to table record
 
   SYNOPSIS
-    field  Field which key image should be stored.
-    ptr    Field value in key format.
-    len    Length of the value, in bytes.
+    store_key_image_to_rec()
+      field  Field which key image should be stored
+      ptr    Field value in key format
+      len    Length of the value, in bytes
+
+  DESCRIPTION
+    Copy the field value from its key image to the table record. The source
+    is the value in key image format, occupying len bytes in buffer pointed
+    by ptr. The destination is table record, in "field value in table record"
+    format.
 */
 
 static void store_key_image_to_rec(Field *field, char *ptr, uint len)
@@ -2414,8 +2473,12 @@
   SYNOPSIS
     store_selargs_to_rec()
       ppar   Partition pruning context
-      start  Array SEL_ARG* for which the minimum values should be stored
+      start  Array of SEL_ARG* for which the minimum values should be stored
       num    Number of elements in the array
+
+  DESCRIPTION
+    For each SEL_ARG* interval in the specified array, store the left edge
+    field value (sel_arg->min, key image format) into the table record.
 */
 
 static void store_selargs_to_rec(PART_PRUNE_PARAM *ppar, SEL_ARG **start,
@@ -2569,7 +2632,7 @@
 
   DESCRIPTION
     This function 
-      * recursively walks the SEL_ARG* tree, collecting partitioning 
+      * recursively walks the SEL_ARG* tree collecting partitioning 
         "intervals";
       * finds the partitions one needs to use to get rows in these intervals;
       * marks these partitions as used.
@@ -2578,9 +2641,9 @@
     A partition pruning "interval" is equivalent to condition in one of the 
     forms:
     
-    "partition_field1=const1 AND ... partition_fieldN=constN"          (1)
-    "subpartition_field1=const1 AND ... subpartition_fieldN=constN"    (2)
-    "(1) AND (2)"                                                      (3)
+    "partition_field1=const1 AND ... AND partition_fieldN=constN"        (1)
+    "subpartition_field1=const1 AND ... AND subpartition_fieldN=constN"  (2)
+    "(1) AND (2)"                                                        (3)
     
     In (1) and (2) all [sub]partitioning fields must be used, and "x=const"
     includes "x IS NULL". 
@@ -2591,7 +2654,7 @@
        
     then the following is also an interval:
 
-           "   const1 OP1 single_partition_field OR const2"            (4)
+           "   const1 OP1 single_partition_field OP2 const2"              (4)
      
     where OP1 and OP2 are '<' OR '<=', and const_i can be +/- inf.
     Everything else is not a partition pruning "interval".
@@ -2695,7 +2758,7 @@
           fields. Save all constN constants into table record buffer.
         */
         store_selargs_to_rec(ppar, ppar->arg_stack, ppar->part_fields);
-        DBUG_EXECUTE("info", dbug_print_onepoint_range(ppar->arg_stack,
+        DBUG_EXECUTE("info", dbug_print_singlepoint_range(ppar->arg_stack,
                                                        ppar->part_fields););
         uint32 part_id;
         /* then find in which partition the {const1, ...,constN} tuple goes */
@@ -2725,7 +2788,7 @@
         */
         store_selargs_to_rec(ppar, ppar->arg_stack_end - ppar->subpart_fields,
                              ppar->subpart_fields);
-        DBUG_EXECUTE("info", dbug_print_onepoint_range(ppar->arg_stack_end - 
+        DBUG_EXECUTE("info", dbug_print_singlepoint_range(ppar->arg_stack_end- 
                                                        ppar->subpart_fields,
                                                        ppar->subpart_fields););
         /* Find the subpartition (it's HASH/KEY so we always have one) */
@@ -2852,7 +2915,7 @@
   struct
 
   SYNOPSIS
-    create_partition_index_descrition()
+    create_partition_index_description()
       prune_par  INOUT Partition pruning context
 
   DESCRIPTION
@@ -2869,7 +2932,7 @@
     FALSE  OK
 */
 
-static bool create_partition_index_descrition(PART_PRUNE_PARAM *ppar)
+static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
 {
   RANGE_OPT_PARAM *range_par= &(ppar->range_param);
   partition_info *part_info= ppar->part_info;
@@ -3056,7 +3119,7 @@
   Print a singlepoint multi-keypart range interval to debug trace
  
   SYNOPSIS
-    dbug_print_onepoint_range()
+    dbug_print_singlepoint_range()
       start  Array of SEL_ARG* ptrs representing conditions on key parts
       num    Number of elements in the array.
 
@@ -3065,9 +3128,9 @@
     interval to debug trace.
 */
 
-static void dbug_print_onepoint_range(SEL_ARG **start, uint num)
+static void dbug_print_singlepoint_range(SEL_ARG **start, uint num)
 {
-  DBUG_ENTER("dbug_print_onepoint_range");
+  DBUG_ENTER("dbug_print_singlepoint_range");
   DBUG_LOCK_FILE;
   SEL_ARG **end= start + num;
 

--- 1.228/sql/sql_class.cc	2005-12-26 14:53:40 +03:00
+++ 1.229/sql/sql_class.cc	2005-12-27 15:04:27 +03:00
@@ -758,7 +758,10 @@
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   if (lex->describe & DESCRIBE_PARTITIONS)
   {
-    field_list.push_back(item= new Item_empty_string("partitions", 10, cs));
+    /* Maximum length of string that make_used_partitions_str() can produce */
+    item= new Item_empty_string("partitions", MAX_PARTITIONS * (1 + FN_LEN),
+                                cs);
+    field_list.push_back(item);
     item->maybe_null= 1;
   }
 #endif

--- 1.213/sql/sql_lex.h	2005-12-26 14:53:40 +03:00
+++ 1.214/sql/sql_lex.h	2005-12-27 15:04:27 +03:00
@@ -104,7 +104,7 @@
 #define DESCRIBE_NORMAL		1
 #define DESCRIBE_EXTENDED	2
 /*
-  This is not #ifdef'ed because we want "EXPLAIN PARTITIONS ..." to produce
+  This is not within #ifdef because we want "EXPLAIN PARTITIONS ..." to produce
   additional "partitions" column even if partitioning is not compiled in.
 */
 #define DESCRIBE_PARTITIONS	4

--- 1.8/mysql-test/r/partition.result	2005-12-15 14:22:59 +03:00
+++ 1.9/mysql-test/r/partition.result	2005-12-27 15:04:27 +03:00
@@ -148,3 +148,10 @@
   `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;

--- 1.8/mysql-test/t/partition.test	2005-12-15 14:22:59 +03:00
+++ 1.9/mysql-test/t/partition.test	2005-12-27 15:04:27 +03:00
@@ -203,3 +203,14 @@
 (PARTITION x1 VALUES LESS THAN (6));
 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 1500
+insert into t1 values (10,1);
+
+drop table t1;
+

--- 1.18/sql/sql_partition.cc	2005-12-26 14:53:40 +03:00
+++ 1.19/sql/sql_partition.cc	2005-12-27 15:04:27 +03:00
@@ -3467,11 +3467,19 @@
 
 
 /*
-  Fill the string comma-separated line of used partitions names
+  Return comma-separated list of used partitions in the provided given string
+
   SYNOPSIS
     make_used_partitions_str()
       part_info  IN  Partitioning info
       parts_str  OUT The string to fill
+
+  DESCRIPTION
+    Generate a list of used partitions (from bits in part_info->used_partitions
+    bitmap), asd store it into the provided String object.
+    
+  NOTE
+    The produced string must not be longer then MAX_PARTITIONS * (1 + FN_LEN).
 */
 
 void make_used_partitions_str(partition_info *part_info, String *parts_str)
Thread
bk commit into 5.1 tree (sergefp:1.1997)Sergey Petrunia27 Dec