List:Commits« Previous MessageNext Message »
From:bar Date:June 21 2006 8:00am
Subject:bk commit into 5.1 tree (bar:1.2213) BUG#20086
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of bar. When bar 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.2213 06/06/21 13:00:19 bar@stripped +7 -0
  Bug#20086: Can't get data from key partitioned tables with VARCHAR key
  The problem appeared because the same values produced different hash
  during INSERT and SELECT for VARCHAR data type.
  Fix:
  VARCHAR required special treatment to avoid hashing of length bytes
  (leftmost one or two bytes) as well as trailing bytes beyond real length,
  which could contain garbage. Fix is done by introducing hash() - new method
  in the Field class.

  sql/sql_partition.cc
    1.79 06/06/21 13:00:07 bar@stripped +3 -14
    Removing old hash code.
    Using new methid field->hash() instead.

  sql/key.cc
    1.43 06/06/21 13:00:07 bar@stripped +4 -0
    Mark columns for write before executinf of set_key_image().
    Thanks for Mikael for suggesting this fix.

  sql/field.h
    1.187 06/06/21 13:00:07 bar@stripped +3 -0
    Adding prototypes for new methods

  sql/field.cc
    1.316 06/06/21 13:00:07 bar@stripped +30 -0
    Adding generic hash() method, and a special
    method for VARCHAR.

  mysql-test/t/partition_innodb.test
    1.3 06/06/21 13:00:07 bar@stripped +12 -0
    Adding test case

  mysql-test/r/partition_pruning.result
    1.17 06/06/21 13:00:07 bar@stripped +1 -1
    Fixing test results (results differ due to changes in hash function)

  mysql-test/r/partition_innodb.result
    1.3 06/06/21 13:00:07 bar@stripped +15 -0
    Adding test case

# 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:	bar
# Host:	bar.intranet.mysql.r18.ru
# Root:	/usr/home/bar/mysql-5.1.b20086

--- 1.315/sql/field.cc	2006-06-15 02:08:26 +05:00
+++ 1.316/sql/field.cc	2006-06-21 13:00:07 +05:00
@@ -1243,6 +1243,21 @@ uint Field::offset()
 }
 
 
+void Field::hash(ulong *nr, ulong *nr2)
+{
+  if (is_null())
+  {
+    *nr^= (*nr << 1) | 1;
+  }
+  else
+  {
+    uint len= pack_length();
+    CHARSET_INFO *cs= charset();
+    cs->coll->hash_sort(cs, (uchar*) ptr, len, nr, nr2);
+  }
+}
+
+
 void Field::copy_from_tmp(int row_offset)
 {
   memcpy(ptr,ptr+row_offset,pack_length());
@@ -6920,6 +6935,21 @@ uint Field_varstring::is_equal(create_fi
       return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer variable length
   }
   return IS_EQUAL_NO;
+}
+
+
+void Field_varstring::hash(ulong *nr, ulong *nr2)
+{
+  if (is_null())
+  {
+    *nr^= (*nr << 1) | 1;
+  }
+  else
+  {
+    uint len=  length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
+    CHARSET_INFO *cs= charset();
+    cs->coll->hash_sort(cs, (uchar*) ptr + length_bytes, len, nr, nr2);
+  }
 }
 
 

--- 1.186/sql/field.h	2006-06-04 21:23:38 +05:00
+++ 1.187/sql/field.h	2006-06-21 13:00:07 +05:00
@@ -351,6 +351,8 @@ public:
     return field_length / charset()->mbmaxlen;
   }
 
+  /* Hash value */
+  virtual void hash(ulong *nr, ulong *nr2);
   friend bool reopen_table(THD *,struct st_table *,bool);
   friend int cre_myisam(my_string name, register TABLE *form, uint options,
 			ulonglong auto_increment_value);
@@ -1120,6 +1122,7 @@ public:
                        char *new_ptr, uchar *new_null_ptr,
                        uint new_null_bit);
   uint is_equal(create_field *new_field);
+  void hash(ulong *nr, ulong *nr2);
 };
 
 

--- 1.42/sql/key.cc	2006-06-04 20:52:11 +05:00
+++ 1.43/sql/key.cc	2006-06-21 13:00:07 +05:00
@@ -210,9 +210,13 @@ void key_restore(byte *to_record, byte *
     }
     else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
     {
+      my_bitmap_map *old_map;
       key_length-= HA_KEY_BLOB_LENGTH;
       length= min(key_length, key_part->length);
+      old_map= dbug_tmp_use_all_columns(key_part->field->table,
+                                        key_part->field->table->write_set);
       key_part->field->set_key_image((char *) from_key, length);
+      dbug_tmp_restore_column_map(key_part->field->table->write_set, old_map);
       from_key+= HA_KEY_BLOB_LENGTH;
     }
     else

--- 1.2/mysql-test/r/partition_innodb.result	2006-05-28 05:30:48 +05:00
+++ 1.3/mysql-test/r/partition_innodb.result	2006-06-21 13:00:07 +05:00
@@ -92,3 +92,18 @@ DROP TABLE IF EXISTS t1;
 DROP TABLE IF EXISTS t0_aux;
 DROP TABLE IF EXISTS t0_definition;
 DROP TABLE IF EXISTS t0_template;
+create table t1 (id varchar(64) primary key) engine=innodb
+partition by key(id) partitions 5;
+insert into t1 values ('a');
+insert into t1 values ('aa');
+insert into t1 values ('aaa');
+select * from t1 where id = 'a';
+id
+a
+select * from t1 where id = 'aa';
+id
+aa
+select * from t1 where id = 'aaa';
+id
+aaa
+drop table t1;

--- 1.2/mysql-test/t/partition_innodb.test	2006-05-28 05:30:48 +05:00
+++ 1.3/mysql-test/t/partition_innodb.test	2006-06-21 13:00:07 +05:00
@@ -66,3 +66,15 @@ DROP TABLE IF EXISTS t0_definition;
 DROP TABLE IF EXISTS t0_template;
 --enable_warnings
 
+#
+# Bug#20086: Can't get data from key partitioned tables with VARCHAR key
+#
+create table t1 (id varchar(64) primary key) engine=innodb
+partition by key(id) partitions 5;
+insert into t1 values ('a');
+insert into t1 values ('aa');
+insert into t1 values ('aaa');
+select * from t1 where id = 'a';
+select * from t1 where id = 'aa';
+select * from t1 where id = 'aaa';
+drop table t1;

--- 1.78/sql/sql_partition.cc	2006-06-14 18:22:23 +05:00
+++ 1.79/sql/sql_partition.cc	2006-06-21 13:00:07 +05:00
@@ -2103,26 +2103,15 @@ static inline longlong part_val_int(Item
 
 static uint32 calculate_key_value(Field **field_array)
 {
-  uint32 hashnr= 0;
+  ulong nr1= 1;
   ulong nr2= 4;
 
   do
   {
     Field *field= *field_array;
-    if (field->is_null())
-    {
-      hashnr^= (hashnr << 1) | 1;
-    }
-    else
-    {
-      uint len= field->pack_length();
-      ulong nr1= 1;
-      CHARSET_INFO *cs= field->charset();
-      cs->coll->hash_sort(cs, (uchar*)field->ptr, len, &nr1, &nr2);
-      hashnr^= (uint32)nr1;
-    }
+    field->hash(&nr1, &nr2);
   } while (*(++field_array));
-  return hashnr;
+  return (uint32) nr1;
 }
 
 

--- 1.16/mysql-test/r/partition_pruning.result	2006-06-05 16:15:22 +05:00
+++ 1.17/mysql-test/r/partition_pruning.result	2006-06-21 13:00:07 +05:00
@@ -31,7 +31,7 @@ id	select_type	table	partitions	type	pos
 1	SIMPLE	t2	p0,p1	ALL	NULL	NULL	NULL	NULL	3	Using where
 explain partitions select * from t2 where a=1 and b=1;
 id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	p0	ALL	NULL	NULL	NULL	NULL	3	Using where
+1	SIMPLE	t2	p0	ALL	NULL	NULL	NULL	NULL	2	Using where
 create table t3 (
 a int
 )
Thread
bk commit into 5.1 tree (bar:1.2213) BUG#20086bar21 Jun