Commit edfa3dcf authored by unknown's avatar unknown

Merge gshchepa.loc:/home/uchum/work/bk-trees/mysql-4.1-opt

into  gshchepa.loc:/home/uchum/work/bk-trees/mysql-5.0-opt-13191


mysql-test/r/innodb_mysql.result:
  SCCS merged
mysql-test/t/innodb_mysql.test:
  SCCS merged
sql/field.cc:
  Merge with 4.1, fix of bug #13191.
sql/field.h:
  Merge with 4.1, fix of bug #13191.
sql/key.cc:
  Merge with 4.1, fix of bug #13191.
parents cecc0495 25033826
...@@ -111,6 +111,39 @@ c1 ...@@ -111,6 +111,39 @@ c1
Before and after comparison Before and after comparison
0 0
drop table t1; drop table t1;
CREATE TABLE t1(c1 TEXT, UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
c1 cnt
1a 1
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
c1 cnt
1a 2
DROP TABLE t1;
CREATE TABLE t1(c1 VARCHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
c1 cnt
1a 1
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
c1 cnt
1a 2
DROP TABLE t1;
CREATE TABLE t1(c1 CHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
c1 cnt
1a 1
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
c1 cnt
1a 2
DROP TABLE t1;
End of 4.1 tests End of 4.1 tests
create table t1m (a int) engine=myisam; create table t1m (a int) engine=myisam;
create table t1i (a int) engine=innodb; create table t1i (a int) engine=innodb;
......
...@@ -139,6 +139,36 @@ eval select STRCMP("$before", "$after") as "Before and after comparison"; ...@@ -139,6 +139,36 @@ eval select STRCMP("$before", "$after") as "Before and after comparison";
connection default; connection default;
drop table t1; drop table t1;
disconnect con1; disconnect con1;
#
# Bug #13191: INSERT...ON DUPLICATE KEY UPDATE of UTF-8 string fields
# used in partial unique indices.
#
CREATE TABLE t1(c1 TEXT, UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(c1 VARCHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1(c1 CHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1)
ENGINE=INNODB CHARACTER SET UTF8;
INSERT INTO t1 (c1) VALUES ('1a');
SELECT * FROM t1;
INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1;
SELECT * FROM t1;
DROP TABLE t1;
--echo End of 4.1 tests --echo End of 4.1 tests
# #
# Bug #12882 min/max inconsistent on empty table # Bug #12882 min/max inconsistent on empty table
......
...@@ -6221,6 +6221,15 @@ uint Field_string::max_packed_col_length(uint max_length) ...@@ -6221,6 +6221,15 @@ uint Field_string::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length; return (max_length > 255 ? 2 : 1)+max_length;
} }
uint Field_string::get_key_image(char *buff, uint length, imagetype type_arg)
{
uint bytes = my_charpos(field_charset, ptr, ptr + field_length,
length / field_charset->mbmaxlen);
memcpy(buff, ptr, bytes);
if (bytes < length)
bzero(buff + bytes, length - bytes);
return bytes;
}
Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table, Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
bool keep_type) bool keep_type)
...@@ -6672,9 +6681,7 @@ uint Field_varstring::max_packed_col_length(uint max_length) ...@@ -6672,9 +6681,7 @@ uint Field_varstring::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length; return (max_length > 255 ? 2 : 1)+max_length;
} }
uint Field_varstring::get_key_image(char *buff, uint length, imagetype type)
void Field_varstring::get_key_image(char *buff, uint length,
imagetype type_arg)
{ {
uint f_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr); uint f_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
uint local_char_length= length / field_charset->mbmaxlen; uint local_char_length= length / field_charset->mbmaxlen;
...@@ -6693,6 +6700,7 @@ void Field_varstring::get_key_image(char *buff, uint length, ...@@ -6693,6 +6700,7 @@ void Field_varstring::get_key_image(char *buff, uint length,
*/ */
bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length)); bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length));
} }
return HA_KEY_BLOB_LENGTH+f_length;
} }
...@@ -7064,7 +7072,7 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr, ...@@ -7064,7 +7072,7 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */ /* The following is used only when comparing a key */
void Field_blob::get_key_image(char *buff, uint length, imagetype type_arg) uint Field_blob::get_key_image(char *buff,uint length, imagetype type_arg)
{ {
uint32 blob_length= get_length(ptr); uint32 blob_length= get_length(ptr);
char *blob; char *blob;
...@@ -7076,16 +7084,17 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type_arg) ...@@ -7076,16 +7084,17 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type_arg)
MBR mbr; MBR mbr;
Geometry_buffer buffer; Geometry_buffer buffer;
Geometry *gobj; Geometry *gobj;
const uint image_length= SIZEOF_STORED_DOUBLE*4;
if (blob_length < SRID_SIZE) if (blob_length < SRID_SIZE)
{ {
bzero(buff, SIZEOF_STORED_DOUBLE*4); bzero(buff, image_length);
return; return image_length;
} }
get_ptr(&blob); get_ptr(&blob);
gobj= Geometry::construct(&buffer, blob, blob_length); gobj= Geometry::construct(&buffer, blob, blob_length);
if (!gobj || gobj->get_mbr(&mbr, &dummy)) if (!gobj || gobj->get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4); bzero(buff, image_length);
else else
{ {
float8store(buff, mbr.xmin); float8store(buff, mbr.xmin);
...@@ -7093,7 +7102,7 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type_arg) ...@@ -7093,7 +7102,7 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type_arg)
float8store(buff+16, mbr.ymin); float8store(buff+16, mbr.ymin);
float8store(buff+24, mbr.ymax); float8store(buff+24, mbr.ymax);
} }
return; return image_length;
} }
#endif /*HAVE_SPATIAL*/ #endif /*HAVE_SPATIAL*/
...@@ -7114,6 +7123,7 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type_arg) ...@@ -7114,6 +7123,7 @@ void Field_blob::get_key_image(char *buff, uint length, imagetype type_arg)
} }
int2store(buff,length); int2store(buff,length);
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length); memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
return HA_KEY_BLOB_LENGTH+length;
} }
...@@ -7399,7 +7409,7 @@ uint Field_blob::max_packed_col_length(uint max_length) ...@@ -7399,7 +7409,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
#ifdef HAVE_SPATIAL #ifdef HAVE_SPATIAL
void Field_geom::get_key_image(char *buff, uint length, imagetype type_arg) uint Field_geom::get_key_image(char *buff, uint length, imagetype type)
{ {
char *blob; char *blob;
const char *dummy; const char *dummy;
...@@ -7407,16 +7417,17 @@ void Field_geom::get_key_image(char *buff, uint length, imagetype type_arg) ...@@ -7407,16 +7417,17 @@ void Field_geom::get_key_image(char *buff, uint length, imagetype type_arg)
ulong blob_length= get_length(ptr); ulong blob_length= get_length(ptr);
Geometry_buffer buffer; Geometry_buffer buffer;
Geometry *gobj; Geometry *gobj;
const uint image_length= SIZEOF_STORED_DOUBLE*4;
if (blob_length < SRID_SIZE) if (blob_length < SRID_SIZE)
{ {
bzero(buff, SIZEOF_STORED_DOUBLE*4); bzero(buff, image_length);
return; return image_length;
} }
get_ptr(&blob); get_ptr(&blob);
gobj= Geometry::construct(&buffer, blob, blob_length); gobj= Geometry::construct(&buffer, blob, blob_length);
if (!gobj || gobj->get_mbr(&mbr, &dummy)) if (!gobj || gobj->get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4); bzero(buff, image_length);
else else
{ {
float8store(buff, mbr.xmin); float8store(buff, mbr.xmin);
...@@ -7424,6 +7435,7 @@ void Field_geom::get_key_image(char *buff, uint length, imagetype type_arg) ...@@ -7424,6 +7435,7 @@ void Field_geom::get_key_image(char *buff, uint length, imagetype type_arg)
float8store(buff + 16, mbr.ymin); float8store(buff + 16, mbr.ymin);
float8store(buff + 24, mbr.ymax); float8store(buff + 24, mbr.ymax);
} }
return image_length;
} }
...@@ -8132,7 +8144,7 @@ int Field_bit::cmp_offset(uint row_offset) ...@@ -8132,7 +8144,7 @@ int Field_bit::cmp_offset(uint row_offset)
} }
void Field_bit::get_key_image(char *buff, uint length, imagetype type_arg) uint Field_bit::get_key_image(char *buff, uint length, imagetype type_arg)
{ {
if (bit_len) if (bit_len)
{ {
...@@ -8140,7 +8152,9 @@ void Field_bit::get_key_image(char *buff, uint length, imagetype type_arg) ...@@ -8140,7 +8152,9 @@ void Field_bit::get_key_image(char *buff, uint length, imagetype type_arg)
*buff++= bits; *buff++= bits;
length--; length--;
} }
memcpy(buff, ptr, min(length, bytes_in_rec)); uint data_length = min(length, bytes_in_rec);
memcpy(buff, ptr, data_length);
return data_length + 1;
} }
......
...@@ -235,8 +235,39 @@ public: ...@@ -235,8 +235,39 @@ public:
{ memcpy(buff,ptr,length); } { memcpy(buff,ptr,length); }
inline void set_image(char *buff,uint length, CHARSET_INFO *cs) inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
{ memcpy(ptr,buff,length); } { memcpy(ptr,buff,length); }
virtual void get_key_image(char *buff, uint length, imagetype type_arg)
{ get_image(buff,length, &my_charset_bin); }
/*
Copy a field part into an output buffer.
SYNOPSIS
Field::get_key_image()
buff [out] output buffer
length output buffer size
type itMBR for geometry blobs, otherwise itRAW
DESCRIPTION
This function makes a copy of field part of size equal to or
less than "length" parameter value.
For fields of string types (CHAR, VARCHAR, TEXT) the rest of buffer
is padded by zero byte.
NOTES
For variable length character fields (i.e. UTF-8) the "length"
parameter means a number of output buffer bytes as if all field
characters have maximal possible size (mbmaxlen). In the other words,
"length" parameter is a number of characters multiplied by
field_charset->mbmaxlen.
RETURN
Number of copied bytes (excluding padded zero bytes -- see above).
*/
virtual uint get_key_image(char *buff, uint length, imagetype type)
{
get_image(buff, length, &my_charset_bin);
return length;
}
virtual void set_key_image(char *buff,uint length) virtual void set_key_image(char *buff,uint length)
{ set_image(buff,length, &my_charset_bin); } { set_image(buff,length, &my_charset_bin); }
inline longlong val_int_offset(uint row_offset) inline longlong val_int_offset(uint row_offset)
...@@ -1071,6 +1102,7 @@ public: ...@@ -1071,6 +1102,7 @@ public:
bool has_charset(void) const bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; } { return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type); Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
virtual uint get_key_image(char *buff,uint length, imagetype type);
}; };
...@@ -1122,7 +1154,7 @@ public: ...@@ -1122,7 +1154,7 @@ public:
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
void get_key_image(char *buff,uint length, imagetype type); uint 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;
char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack(char *to, const char *from, uint max_length=~(uint) 0);
...@@ -1227,7 +1259,7 @@ public: ...@@ -1227,7 +1259,7 @@ public:
store_length(length); store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*)); memcpy_fixed(ptr+packlength,&data,sizeof(char*));
} }
void get_key_image(char *buff,uint length, imagetype type); uint 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;
inline bool copy() inline bool copy()
...@@ -1285,7 +1317,7 @@ public: ...@@ -1285,7 +1317,7 @@ public:
int store(double nr); int store(double nr);
int store(longlong nr, bool unsigned_val); int store(longlong nr, bool unsigned_val);
int store_decimal(const my_decimal *); int store_decimal(const my_decimal *);
void get_key_image(char *buff,uint length,imagetype type); uint get_key_image(char *buff,uint length,imagetype type);
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
int reset(void) { return !maybe_null() || Field_blob::reset(); } int reset(void) { return !maybe_null() || Field_blob::reset(); }
}; };
...@@ -1395,7 +1427,7 @@ public: ...@@ -1395,7 +1427,7 @@ public:
int cmp_offset(uint row_offset); int cmp_offset(uint row_offset);
int cmp_binary_offset(uint row_offset) int cmp_binary_offset(uint row_offset)
{ return cmp_offset(row_offset); } { return cmp_offset(row_offset); }
void get_key_image(char *buff, uint length, imagetype type); uint 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)
{ Field_bit::store(buff, length, &my_charset_bin); } { Field_bit::store(buff, length, &my_charset_bin); }
void sort_string(char *buff, uint length) void sort_string(char *buff, uint length)
......
...@@ -119,29 +119,22 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) ...@@ -119,29 +119,22 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length)
key_length--; key_length--;
} }
} }
if (key_part->key_part_flag & HA_BLOB_PART) if (key_part->key_part_flag & HA_BLOB_PART ||
{ key_part->key_part_flag & HA_VAR_LENGTH_PART)
char *pos;
ulong blob_length= ((Field_blob*) key_part->field)->get_length();
key_length-= HA_KEY_BLOB_LENGTH;
((Field_blob*) key_part->field)->get_ptr(&pos);
length=min(key_length, key_part->length);
set_if_smaller(blob_length, length);
int2store(to_key, (uint) blob_length);
to_key+= HA_KEY_BLOB_LENGTH; // Skip length info
memcpy(to_key, pos, blob_length);
}
else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
{ {
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);
key_part->field->get_key_image((char *) to_key, length, Field::itRAW); key_part->field->get_key_image(to_key, length, Field::itRAW);
to_key+= HA_KEY_BLOB_LENGTH; to_key+= HA_KEY_BLOB_LENGTH;
} }
else else
{ {
length= min(key_length, key_part->length); length= min(key_length, key_part->length);
memcpy(to_key, from_record + key_part->offset, (size_t) length); Field *field= key_part->field;
CHARSET_INFO *cs= field->charset();
uint bytes= field->get_key_image(to_key, length, Field::itRAW);
if (bytes < length)
cs->cset->fill(cs, to_key + bytes, length - bytes, ' ');
} }
to_key+= length; to_key+= length;
key_length-= length; key_length-= length;
......
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