[Commits] 5319846: Postreview changes by Monty & me

Oleksandr Byelkin sanja at mariadb.com
Tue Sep 6 23:13:00 EEST 2016


revision-id: 531984686d9cd92da2b0f61cd362f220c5c2c012 (mariadb-10.2.1-53-g5319846)
parent(s): 442a3d4766f9115bfd496dd4fafd38f7aeb0e273
committer: Oleksandr Byelkin
timestamp: 2016-09-06 22:13:00 +0200
message:

Postreview changes by Monty  & me

---
 mysql-test/r/partition_default.result |  79 ++++++++++++++++++
 mysql-test/t/partition_default.test   |  40 ++++++++-
 sql/partition_info.cc                 | 153 +++++++++++++++-------------------
 sql/partition_info.h                  |   3 +-
 sql/sql_partition.cc                  |  46 +++++++---
 5 files changed, 223 insertions(+), 98 deletions(-)

diff --git a/mysql-test/r/partition_default.result b/mysql-test/r/partition_default.result
index cfd214a..51a8e44 100644
--- a/mysql-test/r/partition_default.result
+++ b/mysql-test/r/partition_default.result
@@ -2,6 +2,16 @@ create table t1 (a int, b int)
 PARTITION BY LIST (a)
 (
 PARTITION p2 VALUES IN (4,5,6),
+PARTITION p1 VALUES IN (1)
+)
+;
+insert into t1 values (10,10);
+ERROR HY000: Table has no partition for value 10
+drop table t1;
+create table t1 (a int, b int)
+PARTITION BY LIST (a)
+(
+PARTITION p2 VALUES IN (4,5,6),
 PARTITION p1 VALUES IN (1),
 PARTITION p0 DEFAULT
 )
@@ -17,9 +27,16 @@ t1	CREATE TABLE `t1` (
  PARTITION p1 VALUES IN (1) ENGINE = MyISAM,
  PARTITION p0 DEFAULT ENGINE = MyISAM) */
 insert into t1 values (10,10);
+insert into t1 values (4,4);
 select * from t1;
 a	b
+4	4
 10	10
+select partition_name, table_rows from INFORMATION_SCHEMA.PARTITIONS where table_name='t1';
+partition_name	table_rows
+p2	1
+p1	0
+p0	1
 drop table t1;
 create table t1 (a int, b int)
 PARTITION BY LIST (a)
@@ -848,6 +865,37 @@ id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
 explain partitions select * from t1 where a=10 and b=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	
+alter table t1 drop partition p2;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL,
+  `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST (a)
+(PARTITION p1 VALUES IN (20,0) ENGINE = MyISAM,
+ PARTITION p0 VALUES IN (10) ENGINE = MyISAM) */
+select * from t1;
+a	b
+0	0
+10	10
+alter table t1 add partition (PARTITION pd DEFAULT);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL,
+  `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY LIST (a)
+(PARTITION p1 VALUES IN (20,0) ENGINE = MyISAM,
+ PARTITION p0 VALUES IN (10) ENGINE = MyISAM,
+ PARTITION pd DEFAULT ENGINE = MyISAM) */
+alter table t1 add partition (PARTITION pdd DEFAULT);
+ERROR HY000: Only one DEFAULT partition allowed
+alter table t1 drop partition pd;
+alter table t1 add partition (PARTITION pdd DEFAULT,
+PARTITION pd DEFAULT);
+ERROR HY000: Only one DEFAULT partition allowed
 drop table t1;
 create table t1 (a int, b int);
 insert into t1 values (10,10),(2,5),(0,0);
@@ -943,4 +991,35 @@ id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
 explain partitions select * from t1 where a=10 and b=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	
+alter table t1 drop partition p2;
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL,
+  `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50500 PARTITION BY LIST  COLUMNS(a,b)
+(PARTITION p1 VALUES IN ((1,1),(0,0)) ENGINE = MyISAM,
+ PARTITION p0 VALUES IN ((10,10)) ENGINE = MyISAM) */
+select * from t1;
+a	b
+0	0
+10	10
+alter table t1 add partition (PARTITION pd DEFAULT);
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL,
+  `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+/*!50500 PARTITION BY LIST  COLUMNS(a,b)
+(PARTITION p1 VALUES IN ((1,1),(0,0)) ENGINE = MyISAM,
+ PARTITION p0 VALUES IN ((10,10)) ENGINE = MyISAM,
+ PARTITION pd DEFAULT ENGINE = MyISAM) */
+alter table t1 add partition (PARTITION pdd DEFAULT);
+ERROR HY000: Only one DEFAULT partition allowed
+alter table t1 drop partition pd;
+alter table t1 add partition (PARTITION pdd DEFAULT,
+PARTITION pd DEFAULT);
+ERROR HY000: Only one DEFAULT partition allowed
 drop table t1;
diff --git a/mysql-test/t/partition_default.test b/mysql-test/t/partition_default.test
index 9faf777..dc4c58c 100644
--- a/mysql-test/t/partition_default.test
+++ b/mysql-test/t/partition_default.test
@@ -8,13 +8,25 @@ create table t1 (a int, b int)
   PARTITION BY LIST (a)
   (
     PARTITION p2 VALUES IN (4,5,6),
+    PARTITION p1 VALUES IN (1)
+  )
+;
+--error ER_NO_PARTITION_FOR_GIVEN_VALUE
+insert into t1 values (10,10);
+drop table t1;
+create table t1 (a int, b int)
+  PARTITION BY LIST (a)
+  (
+    PARTITION p2 VALUES IN (4,5,6),
     PARTITION p1 VALUES IN (1),
     PARTITION p0 DEFAULT
   )
 ;
 show create table t1;
 insert into t1 values (10,10);
+insert into t1 values (4,4);
 select * from t1;
+select partition_name, table_rows from INFORMATION_SCHEMA.PARTITIONS where table_name='t1';
 drop table t1;
 
 --error ER_PARTITION_DEFAULT_ERROR
@@ -290,8 +302,21 @@ show create table t1;
 select * from t1;
 explain partitions select * from t1 where a=2 and b=5;
 explain partitions select * from t1 where a=10 and b=10;
-drop table t1;
 
+alter table t1 drop partition p2;
+show create table t1;
+select * from t1;
+
+alter table t1 add partition (PARTITION pd DEFAULT);
+show create table t1;
+--error ER_PARTITION_DEFAULT_ERROR
+alter table t1 add partition (PARTITION pdd DEFAULT);
+alter table t1 drop partition pd;
+--error ER_PARTITION_DEFAULT_ERROR
+alter table t1 add partition (PARTITION pdd DEFAULT,
+                              PARTITION pd DEFAULT);
+
+drop table t1;
 
 create table t1 (a int, b int);
 
@@ -335,4 +360,17 @@ show create table t1;
 select * from t1;
 explain partitions select * from t1 where a=2 and b=5;
 explain partitions select * from t1 where a=10 and b=10;
+
+alter table t1 drop partition p2;
+show create table t1;
+select * from t1;
+
+alter table t1 add partition (PARTITION pd DEFAULT);
+show create table t1;
+--error ER_PARTITION_DEFAULT_ERROR
+alter table t1 add partition (PARTITION pdd DEFAULT);
+alter table t1 drop partition pd;
+--error ER_PARTITION_DEFAULT_ERROR
+alter table t1 add partition (PARTITION pdd DEFAULT,
+                              PARTITION pd DEFAULT);
 drop table t1;
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index db14c198..de41523 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -1503,21 +1503,15 @@ bool partition_info::check_list_constants(THD *thd)
       has_null_part_id= i;
       found_null= TRUE;
     }
-    List_iterator<part_elem_value> list_val_it1(part_def->list_val_list);
-    while (list_val_it1++)
-      num_list_values++;
+    num_list_values+= part_def->list_val_list.elements;
   } while (++i < num_parts);
   list_func_it.rewind();
   num_column_values= part_field_list.elements;
   size_entries= column_list ?
         (num_column_values * sizeof(part_column_list_val)) :
         sizeof(LIST_PART_ENTRY);
-  ptr= thd->calloc((num_list_values+1) * size_entries);
-  if (unlikely(ptr == NULL))
-  {
-    mem_alloc_error(num_list_values * size_entries);
+  if (unlikely(!(ptr= thd->calloc((num_list_values+1) * size_entries))))
     goto end;
-  }
   if (column_list)
   {
     part_column_list_val *loc_list_col_array;
@@ -1528,8 +1522,9 @@ bool partition_info::check_list_constants(THD *thd)
     do
     {
       part_def= list_func_it++;
-      if (part_def->max_value && part_type == LIST_PARTITION)
+      if (part_def->max_value)
       {
+        DBUG_ASSERT(part_type == LIST_PARTITION);
         // DEFAULT is not a real value so let's exclude it from sorting.
         DBUG_ASSERT(num_list_values);
         num_list_values--;
@@ -2302,8 +2297,7 @@ int partition_info::add_max_value(THD *thd)
 
   part_column_list_val *col_val;
   /*
-    Makes for LIST COLUMNS list of tuple DEFAULT valeus and one in other
-    cases
+    Makes for LIST COLUMNS 'num_columns' DEFAULT tuples, 1 tuple for RANGEs
   */
   uint max_val= (num_columns && part_type == LIST_PARTITION) ?
                  num_columns : 1;
@@ -2589,8 +2583,7 @@ int partition_info::reorganize_into_single_field_col_val(THD *thd)
 */
 int partition_info::fix_partition_values(THD *thd,
                                          part_elem_value *val,
-                                         partition_element *part_elem,
-                                         uint part_id)
+                                         partition_element *part_elem)
 {
   part_column_list_val *col_val= val->col_val_array;
   DBUG_ENTER("partition_info::fix_partition_values");
@@ -2599,65 +2592,31 @@ int partition_info::fix_partition_values(THD *thd,
   {
     DBUG_RETURN(FALSE);
   }
-  if (val->added_items != 1)
-  {
-    my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-  if (col_val->max_value)
+
+  Item *item_expr= col_val->item_expression;
+  if ((val->null_value= item_expr->null_value))
   {
-    /* The parser ensures we're not LIST partitioned here */
-    DBUG_ASSERT(part_type == RANGE_PARTITION ||
-                part_type == LIST_PARTITION);
-    if (defined_max_value)
-    {
-      my_error((part_type == RANGE_PARTITION) ?
-               ER_PARTITION_MAXVALUE_ERROR :
-               ER_PARTITION_DEFAULT_ERROR, MYF(0));
-      DBUG_RETURN(TRUE);
-    }
-    if (part_id == (num_parts - 1) ||
-        part_type == LIST_PARTITION)
-    {
-      defined_max_value= TRUE;
-      default_partition_id= part_id;
-      part_elem->max_value= TRUE;
-      part_elem->range_value= LONGLONG_MAX;
-    }
-    else
+    if (part_elem->has_null_value)
     {
-      DBUG_ASSERT(part_type != LIST_PARTITION);
-      my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
+      my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
       DBUG_RETURN(TRUE);
     }
+    part_elem->has_null_value= TRUE;
   }
-  else
+  else if (item_expr->result_type() != INT_RESULT)
   {
-    Item *item_expr= col_val->item_expression;
-    if ((val->null_value= item_expr->null_value))
-    {
-      if (part_elem->has_null_value)
-      {
-         my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
-         DBUG_RETURN(TRUE);
-      }
-      part_elem->has_null_value= TRUE;
-    }
-    else if (item_expr->result_type() != INT_RESULT)
+    my_error(ER_VALUES_IS_NOT_INT_TYPE_ERROR, MYF(0),
+             part_elem->partition_name);
+    DBUG_RETURN(TRUE);
+  }
+  if (part_type == RANGE_PARTITION)
+  {
+    if (part_elem->has_null_value)
     {
-      my_error(ER_VALUES_IS_NOT_INT_TYPE_ERROR, MYF(0),
-               part_elem->partition_name);
+      my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
       DBUG_RETURN(TRUE);
     }
-    if (part_type == RANGE_PARTITION)
-    {
-      if (part_elem->has_null_value)
-      {
-        my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
-        DBUG_RETURN(TRUE);
-      }
-      part_elem->range_value= val->value;
-    }
+    part_elem->range_value= val->value;
   }
   col_val->fixed= 2;
   DBUG_RETURN(FALSE);
@@ -2864,34 +2823,60 @@ bool partition_info::fix_parser_data(THD *thd)
     num_elements= part_elem->list_val_list.elements;
     DBUG_ASSERT(part_type == RANGE_PARTITION ?
                 num_elements == 1U : TRUE);
+
     for (j= 0; j < num_elements; j++)
     {
       part_elem_value *val= list_val_it++;
-      if (column_list)
+
+      if (val->added_items != (column_list ? num_columns : 1))
       {
-        if (part_type == LIST_PARTITION)
+        my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
+        DBUG_RETURN(TRUE);
+      }
+
+      /*
+        Check the last MAX_VALUE for range partitions and DEFAULT value
+        for LIST partitions.
+        Both values are marked with defined_max_value and
+        default_partition_id.
+
+        This is a max_value/default is max_value is set and this is 
+        a normal RANGE (no column list) or if it's a LIST partition:
+
+        PARTITION p3 VALUES LESS THAN MAXVALUE
+        or
+        PARTITION p3 VALUES DEFAULT
+      */
+      if (val->added_items && val->col_val_array[0].max_value &&
+          (!column_list || part_type == LIST_PARTITION))
+      {
+        DBUG_ASSERT(part_type == RANGE_PARTITION ||
+                    part_type == LIST_PARTITION);
+        if (defined_max_value)
         {
-          DBUG_ASSERT(val->added_items);
-          if (val->col_val_array[0].max_value)
-          {
-            //default value
-            DBUG_ASSERT(val->added_items == num_columns);
-            if (defined_max_value)
-            {
-              my_error(ER_PARTITION_DEFAULT_ERROR, MYF(0));
-              DBUG_RETURN(TRUE);
-            }
-            defined_max_value= TRUE;
-            default_partition_id= i; // i is a partition id
-            part_elem->max_value= TRUE;
-            continue;
-          }
+          my_error((part_type == RANGE_PARTITION) ?
+                   ER_PARTITION_MAXVALUE_ERROR :
+                   ER_PARTITION_DEFAULT_ERROR, MYF(0));
+          DBUG_RETURN(TRUE);
         }
-        if (val->added_items != num_columns)
+
+        /* For RANGE PARTITION MAX_VALUE must be last */
+        if (i != (num_parts - 1) &&
+            part_type != LIST_PARTITION)
         {
-          my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
+          my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
           DBUG_RETURN(TRUE);
         }
+
+        defined_max_value= TRUE;
+        default_partition_id= i;
+        part_elem->max_value= TRUE;
+        part_elem->range_value= LONGLONG_MAX;
+        continue;
+      }
+
+      if (column_list)
+      {
         for (k= 0; k < num_columns; k++)
         {
           part_column_list_val *col_val= &val->col_val_array[k];
@@ -2904,10 +2889,8 @@ bool partition_info::fix_parser_data(THD *thd)
       }
       else
       {
-        if (fix_partition_values(thd, val, part_elem, i))
-        {
+        if (fix_partition_values(thd, val, part_elem))
           DBUG_RETURN(TRUE);
-        }
         if (val->null_value)
         {
           /*
diff --git a/sql/partition_info.h b/sql/partition_info.h
index f70a68b..66579be 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -328,8 +328,7 @@ class partition_info : public Sql_alloc
   Item* get_column_item(Item *item, Field *field);
   int fix_partition_values(THD *thd,
                            part_elem_value *val,
-                           partition_element *part_elem,
-                           uint part_id);
+                           partition_element *part_elem);
   bool fix_column_value_functions(THD *thd,
                                   part_elem_value *val,
                                   uint part_id);
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 9cef2b1..f6246f9 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -2314,9 +2314,10 @@ static int add_partition_values(File fptr, partition_info *part_info,
 
     if (p_elem->max_value)
     {
-      DBUG_ASSERT(part_info->defined_max_value);
+      DBUG_ASSERT(part_info->defined_max_value ||
+                  current_thd->lex->sql_command == SQLCOM_ALTER_TABLE);
       err+= add_string(fptr, " DEFAULT");
-      goto end;
+      return err;
     }
 
     err+= add_string(fptr, " VALUES IN ");
@@ -4710,6 +4711,19 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
   }
 
   thd->work_part_info= thd->lex->part_info;
+  partition_info *alt_part_info= thd->work_part_info;
+  bool only_default_value=
+    (alt_part_info &&
+     alt_part_info->current_partition &&
+     alt_part_info->current_partition->list_val_list.elements == 1 &&
+     alt_part_info->current_partition->list_val_list.head()->
+     added_items >= 1 &&
+     alt_part_info->current_partition->list_val_list.head()->
+     col_val_array[0].max_value) &&
+    alt_part_info->part_type == LIST_PARTITION;
+  if (only_default_value &&
+      !thd->lex->part_info->num_columns)
+    thd->lex->part_info->num_columns= 1; // to make correct clone
 
   if (thd->work_part_info &&
       !(thd->work_part_info= thd->lex->part_info->get_clone(thd)))
@@ -4727,12 +4741,12 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
        Alter_info::ALTER_REBUILD_PARTITION))
   {
     partition_info *tab_part_info;
-    partition_info *alt_part_info= thd->work_part_info;
     uint flags= 0;
     bool is_last_partition_reorged= FALSE;
     part_elem_value *tab_max_elem_val= NULL;
     part_elem_value *alt_max_elem_val= NULL;
     longlong tab_max_range= 0, alt_max_range= 0;
+    alt_part_info= thd->work_part_info;
 
     if (!table->part_info)
     {
@@ -4897,14 +4911,16 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
         }
       }
       if ((tab_part_info->column_list &&
-          alt_part_info->num_columns != tab_part_info->num_columns) ||
+          alt_part_info->num_columns != tab_part_info->num_columns &&
+          !only_default_value) ||
           (!tab_part_info->column_list &&
             (tab_part_info->part_type == RANGE_PARTITION ||
              tab_part_info->part_type == LIST_PARTITION) &&
-            alt_part_info->num_columns != 1U) ||
+            alt_part_info->num_columns != 1U &&
+             !only_default_value) ||
           (!tab_part_info->column_list &&
             tab_part_info->part_type == HASH_PARTITION &&
-            alt_part_info->num_columns != 0))
+            (alt_part_info->num_columns != 0)))
       {
         my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
         goto err;
@@ -4939,7 +4955,9 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
       }
       if (tab_part_info->defined_max_value)
       {
-        my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
+        my_error((tab_part_info->part_type == RANGE_PARTITION?
+                  ER_PARTITION_MAXVALUE_ERROR:
+                  ER_PARTITION_DEFAULT_ERROR), MYF(0));
         goto err;
       }
       if (num_new_partitions == 0)
@@ -7715,9 +7733,11 @@ int get_part_iter_for_interval_cols_via_map(partition_info *part_info,
   else
     assert(0);
 
-  can_match_multiple_values= (flags || !min_value || !max_value ||
-                              (min_len != max_len) ||
+  can_match_multiple_values= ((flags &
+                               (NO_MIN_RANGE | NO_MAX_RANGE | NEAR_MIN |
+                                NEAR_MAX)) ||
                               memcmp(min_value, max_value, min_len));
+  DBUG_ASSERT(can_match_multiple_values || !(flags & (~EQ_RANGE)));
   if (can_match_multiple_values && part_info->has_default_partititon())
     part_iter->ret_default_part= part_iter->ret_default_part_orig= TRUE;
 
@@ -7757,6 +7777,7 @@ int get_part_iter_for_interval_cols_via_map(partition_info *part_info,
   }
   if (part_iter->part_nums.start == part_iter->part_nums.end)
   {
+    // No matching partition found.
     if (part_info->has_default_partititon())
     {
       part_iter->ret_default_part= part_iter->ret_default_part_orig= TRUE;
@@ -7861,8 +7882,11 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
   else
     MY_ASSERT_UNREACHABLE();
 
-  can_match_multiple_values= (flags || !min_value || !max_value ||
+  can_match_multiple_values= ((flags &
+                               (NO_MIN_RANGE | NO_MAX_RANGE | NEAR_MIN |
+                                NEAR_MAX)) ||
                               memcmp(min_value, max_value, field_len));
+  DBUG_ASSERT(can_match_multiple_values || !(flags & (~EQ_RANGE)));
   if (can_match_multiple_values && part_info->has_default_partititon())
     part_iter->ret_default_part= part_iter->ret_default_part_orig= TRUE;
   if (can_match_multiple_values &&
@@ -8185,6 +8209,7 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter)
       part_iter->ret_null_part= FALSE;
       return 0;                    /* NULL always in first range partition */
     }
+    // we do not have default partition in RANGE partitioning
     DBUG_ASSERT(!part_iter->ret_default_part);
 
     part_iter->part_nums.cur= part_iter->part_nums.start;
@@ -8229,6 +8254,7 @@ uint32 get_next_partition_id_list(PARTITION_ITERATOR *part_iter)
       part_iter->ret_default_part= FALSE;
       return part_iter->part_info->default_partition_id;
     }
+    /* Reset partition for next read */
     part_iter->part_nums.cur= part_iter->part_nums.start;
     part_iter->ret_null_part= part_iter->ret_null_part_orig;
     part_iter->ret_default_part= part_iter->ret_default_part_orig;


More information about the commits mailing list