Bug #27123 (partition + on duplicate key update + varchar = Can't find

record in table)

key_restore function didn't work as intended in the case of
VARCHAR or BLOB fields, stored the restored key in field->ptr instead
of to_record.
That produced the wrong key so search returned wrong result
parent bfac9ea6
...@@ -1238,4 +1238,12 @@ t2 CREATE TABLE `t2` ( ...@@ -1238,4 +1238,12 @@ t2 CREATE TABLE `t2` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (i) (PARTITION p01 VALUES LESS THAN (1000) ENGINE = MyISAM) */ ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (i) (PARTITION p01 VALUES LESS THAN (1000) ENGINE = MyISAM) */
DROP TABLE t1, t2; DROP TABLE t1, t2;
set @@sql_mode=@org_mode; set @@sql_mode=@org_mode;
create table t1 (c1 varchar(255),c2 tinyint,primary key(c1))
partition by key (c1) partitions 10 ;
insert into t1 values ('aaa','1') on duplicate key update c2 = c2 + 1;
insert into t1 values ('aaa','1') on duplicate key update c2 = c2 + 1;
select * from t1;
c1 c2
aaa 2
drop table t1;
End of 5.1 tests End of 5.1 tests
...@@ -1492,4 +1492,15 @@ show create table t2; ...@@ -1492,4 +1492,15 @@ show create table t2;
DROP TABLE t1, t2; DROP TABLE t1, t2;
set @@sql_mode=@org_mode; set @@sql_mode=@org_mode;
#
# Bug #27123 partition + on duplicate key update + varchar = Can't find record in <table>
#
create table t1 (c1 varchar(255),c2 tinyint,primary key(c1))
partition by key (c1) partitions 10 ;
insert into t1 values ('aaa','1') on duplicate key update c2 = c2 + 1;
insert into t1 values ('aaa','1') on duplicate key update c2 = c2 + 1;
select * from t1;
drop table t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -6969,7 +6969,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, ...@@ -6969,7 +6969,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
} }
void Field_blob::store_length(uint32 number) void Field_blob::store_length(char *ptr, uint packlength, uint32 number)
{ {
switch (packlength) { switch (packlength) {
case 1: case 1:
......
...@@ -1274,7 +1274,12 @@ public: ...@@ -1274,7 +1274,12 @@ public:
} }
int reset(void) { bzero(ptr, packlength+sizeof(char*)); return 0; } int reset(void) { bzero(ptr, packlength+sizeof(char*)); return 0; }
void reset_fields() { bzero((char*) &value,sizeof(value)); } void reset_fields() { bzero((char*) &value,sizeof(value)); }
void store_length(uint32 number); static void store_length(char *ptr, uint packlength, uint32 number);
inline void store_length(uint32 number)
{
store_length(ptr, packlength, number);
}
inline uint32 get_length(uint row_offset=0) inline uint32 get_length(uint row_offset=0)
{ return get_length(ptr+row_offset); } { return get_length(ptr+row_offset); }
uint32 get_length(const char *ptr); uint32 get_length(const char *ptr);
...@@ -1292,11 +1297,17 @@ public: ...@@ -1292,11 +1297,17 @@ public:
memcpy(ptr,length,packlength); memcpy(ptr,length,packlength);
memcpy_fixed(ptr+packlength,&data,sizeof(char*)); memcpy_fixed(ptr+packlength,&data,sizeof(char*));
} }
void set_ptr_offset(my_ptrdiff_t ptr_diff, uint32 length,char *data)
{
char *ptr_ofs= ADD_TO_PTR(ptr,ptr_diff,char*);
store_length(ptr_ofs, packlength, length);
memcpy_fixed(ptr_ofs+packlength,&data,sizeof(char*));
}
inline void set_ptr(uint32 length,char *data) inline void set_ptr(uint32 length,char *data)
{ {
store_length(length); set_ptr_offset(0, length, data);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
} }
void get_key_image(char *buff,uint length, imagetype type); void get_key_image(char *buff,uint length, imagetype type);
void set_key_image(char *buff,uint length); void set_key_image(char *buff,uint length);
void sql_type(String &str) const; void sql_type(String &str) const;
......
...@@ -853,9 +853,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, ...@@ -853,9 +853,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array,
i, offset, (long) buf, len, (int)ptrdiff)); i, offset, (long) buf, len, (int)ptrdiff));
DBUG_ASSERT(len == len64); DBUG_ASSERT(len == len64);
// Ugly hack assumes only ptr needs to be changed // Ugly hack assumes only ptr needs to be changed
field_blob->ptr+= ptrdiff; field_blob->set_ptr_offset(ptrdiff, len, buf);
field_blob->set_ptr(len, buf);
field_blob->ptr-= ptrdiff;
} }
offset+= size; offset+= size;
} }
...@@ -864,9 +862,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, ...@@ -864,9 +862,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array,
// have to set length even in this case // have to set length even in this case
char *buf= buffer + offset; // or maybe NULL char *buf= buffer + offset; // or maybe NULL
uint32 len= 0; uint32 len= 0;
field_blob->ptr+= ptrdiff; field_blob->set_ptr_offset(ptrdiff, len, buf);
field_blob->set_ptr(len, buf);
field_blob->ptr-= ptrdiff;
DBUG_PRINT("info", ("[%u] isNull=%d", i, isNull)); DBUG_PRINT("info", ("[%u] isNull=%d", i, isNull));
} }
} }
......
...@@ -221,23 +221,34 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, ...@@ -221,23 +221,34 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
} }
if (key_part->key_part_flag & HA_BLOB_PART) if (key_part->key_part_flag & HA_BLOB_PART)
{ {
/*
This in fact never happens, as we have only partial BLOB
keys yet anyway, so it's difficult to find any sence to
restore the part of a record.
Maybe this branch is to be removed, but now we
have to ignore GCov compaining.
*/
uint blob_length= uint2korr(from_key); uint blob_length= uint2korr(from_key);
Field_blob *field= (Field_blob*) key_part->field;
from_key+= HA_KEY_BLOB_LENGTH; from_key+= HA_KEY_BLOB_LENGTH;
key_length-= HA_KEY_BLOB_LENGTH; key_length-= HA_KEY_BLOB_LENGTH;
((Field_blob*) key_part->field)->set_ptr((ulong) blob_length, field->set_ptr_offset(to_record - field->table->record[0],
(char*) from_key); (ulong) blob_length, (char*) from_key);
length= key_part->length; length= key_part->length;
} }
else if (key_part->key_part_flag & HA_VAR_LENGTH_PART) else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
{ {
Field *field= key_part->field;
my_bitmap_map *old_map; my_bitmap_map *old_map;
my_ptrdiff_t ptrdiff= to_record - field->table->record[0];
field->move_field_offset(ptrdiff);
key_length-= HA_KEY_BLOB_LENGTH; key_length-= HA_KEY_BLOB_LENGTH;
length= min(key_length, key_part->length); length= min(key_length, key_part->length);
old_map= dbug_tmp_use_all_columns(key_part->field->table, old_map= dbug_tmp_use_all_columns(field->table, field->table->write_set);
key_part->field->table->write_set); field->set_key_image((char *) from_key, length);
key_part->field->set_key_image((char *) from_key, length); dbug_tmp_restore_column_map(field->table->write_set, old_map);
dbug_tmp_restore_column_map(key_part->field->table->write_set, old_map);
from_key+= HA_KEY_BLOB_LENGTH; from_key+= HA_KEY_BLOB_LENGTH;
field->move_field_offset(-ptrdiff);
} }
else else
{ {
......
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