diff options
-rw-r--r-- | mysql-test/r/partition.result | 8 | ||||
-rw-r--r-- | mysql-test/t/partition.test | 11 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 16 | ||||
-rw-r--r-- | sql/ha_ndbcluster.cc | 8 | ||||
-rw-r--r-- | sql/key.cc | 23 |
6 files changed, 52 insertions, 16 deletions
diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 8e0ae617a6b..3549e987d73 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1225,4 +1225,12 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY RANGE (i) (PARTITION p01 VALUES LESS THAN (1000) ENGINE = MyISAM) */ DROP TABLE t1, t2; 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 diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 961b1319fc4..36f3a40503b 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1431,4 +1431,15 @@ show create table t2; DROP TABLE t1, t2; 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 diff --git a/sql/field.cc b/sql/field.cc index e8718c9e407..dca2d7137e0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7006,7 +7006,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) { case 1: diff --git a/sql/field.h b/sql/field.h index f9d77fe17ab..9d89e53c36c 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1307,7 +1307,12 @@ public: } int reset(void) { bzero(ptr, packlength+sizeof(char*)); return 0; } 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) { return get_length(ptr+row_offset); } uint32 get_length(const char *ptr); @@ -1325,10 +1330,15 @@ public: memcpy(ptr,length,packlength); 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) { - store_length(length); - memcpy_fixed(ptr+packlength,&data,sizeof(char*)); + set_ptr_offset(0, length, data); } uint get_key_image(char *buff,uint length, imagetype type); void set_key_image(char *buff,uint length); diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 5bbaa793939..4229d4eb4a3 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -874,9 +874,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, i, offset, (long) buf, len, (int)ptrdiff)); DBUG_ASSERT(len == len64); // Ugly hack assumes only ptr needs to be changed - field_blob->ptr+= ptrdiff; - field_blob->set_ptr(len, buf); - field_blob->ptr-= ptrdiff; + field_blob->set_ptr_offset(ptrdiff, len, buf); } offset+= size; } @@ -885,9 +883,7 @@ int get_ndb_blobs_value(TABLE* table, NdbValue* value_array, // have to set length even in this case char *buf= buffer + offset; // or maybe NULL uint32 len= 0; - field_blob->ptr+= ptrdiff; - field_blob->set_ptr(len, buf); - field_blob->ptr-= ptrdiff; + field_blob->set_ptr_offset(ptrdiff, len, buf); DBUG_PRINT("info", ("[%u] isNull=%d", i, isNull)); } } diff --git a/sql/key.cc b/sql/key.cc index 19861cee134..9a3155c459e 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -214,23 +214,34 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, } 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); + Field_blob *field= (Field_blob*) key_part->field; from_key+= HA_KEY_BLOB_LENGTH; key_length-= HA_KEY_BLOB_LENGTH; - ((Field_blob*) key_part->field)->set_ptr((ulong) blob_length, - (char*) from_key); + field->set_ptr_offset(to_record - field->table->record[0], + (ulong) blob_length, (char*) from_key); length= key_part->length; } else if (key_part->key_part_flag & HA_VAR_LENGTH_PART) { + Field *field= key_part->field; 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; 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); + old_map= dbug_tmp_use_all_columns(field->table, field->table->write_set); + field->set_key_image((char *) from_key, length); + dbug_tmp_restore_column_map(field->table->write_set, old_map); from_key+= HA_KEY_BLOB_LENGTH; + field->move_field_offset(-ptrdiff); } else { |