diff options
author | ingo@mysql.com <> | 2004-06-25 14:44:37 +0200 |
---|---|---|
committer | ingo@mysql.com <> | 2004-06-25 14:44:37 +0200 |
commit | 8db6c064dfb8f0d1eb255200125328217e323bbd (patch) | |
tree | 6d0e12ffaf9e7fc190cab4a67d9c64cfa69163b9 | |
parent | 958cf857a3cee868ec11a4b352581554705ac3b2 (diff) | |
parent | 57da928039a322df37e17d1a139b42b76f45cdc1 (diff) | |
download | mariadb-git-8db6c064dfb8f0d1eb255200125328217e323bbd.tar.gz |
Merge mysql.com:/home/mydev/mysql-4.0
into mysql.com:/home/mydev/mysql-4.0-bug2686
-rw-r--r-- | mysql-test/r/bdb.result | 16 | ||||
-rw-r--r-- | mysql-test/t/bdb.test | 19 | ||||
-rw-r--r-- | sql/field.cc | 80 | ||||
-rw-r--r-- | sql/field.h | 6 | ||||
-rw-r--r-- | sql/ha_berkeley.cc | 4 |
5 files changed, 123 insertions, 2 deletions
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 7d4b42e6a8c..684efc3ef1b 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1190,6 +1190,22 @@ a A a drop table t1; +create table t1( +pk1 text not null, pk2 text not null, pk3 char(4), +key1 int, key2 int, +primary key(pk1(4), pk2(4), pk3), key(key1), key(key2) +) engine=bdb; +insert into t1 values (concat('aaa-', repeat('A', 4000)), +concat('eee-', repeat('e', 4000)), 'a++a', 1, 1); +insert into t1 values (concat('bbb-', repeat('B', 4000)), +concat('ggg-', repeat('G', 4000)), 'b++b', 1, 1); +select substring(pk1, 1, 4), substring(pk1, 4001), +substring(pk2, 1, 4), substring(pk2, 4001), pk3, key1, key2 +from t1 force index(key1, key2) where key1 < 3 or key2 < 3; +substring(pk1, 1, 4) substring(pk1, 4001) substring(pk2, 1, 4) substring(pk2, 4001) pk3 key1 key2 +aaa- AAAA eee- eeee a++a 1 1 +bbb- BBBB ggg- GGGG b++b 1 1 +drop table t1; create table t1 ( pk1 varchar(8) not null default '', pk2 varchar(4) not null default '', diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index bed0cbe269d..1e6d7035989 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -831,6 +831,25 @@ select a from t1; drop table t1; # +# bug#2686 - index_merge select on BerkeleyDB table with varchar PK causes mysqld to crash +# + +create table t1( + pk1 text not null, pk2 text not null, pk3 char(4), + key1 int, key2 int, + primary key(pk1(4), pk2(4), pk3), key(key1), key(key2) +) engine=bdb; +insert into t1 values (concat('aaa-', repeat('A', 4000)), + concat('eee-', repeat('e', 4000)), 'a++a', 1, 1); +insert into t1 values (concat('bbb-', repeat('B', 4000)), + concat('ggg-', repeat('G', 4000)), 'b++b', 1, 1); +select substring(pk1, 1, 4), substring(pk1, 4001), + substring(pk2, 1, 4), substring(pk2, 4001), pk3, key1, key2 + from t1 force index(key1, key2) where key1 < 3 or key2 < 3; +drop table t1; + + +# # bug#2688 - Wrong index_merge query results for BDB table with variable length primary key # diff --git a/sql/field.cc b/sql/field.cc index 7273c9036c4..e3bdf78e718 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4167,6 +4167,42 @@ uint32 Field_blob::get_length(const char *pos) } +/* + Put a blob length field into a record buffer. + + SYNOPSIS + Field_blob::put_length() + pos Pointer into the record buffer. + length The length value to put. + + DESCRIPTION + Depending on the maximum length of a blob, its length field is + put into 1 to 4 bytes. This is a property of the blob object, + described by 'packlength'. + + RETURN + nothing +*/ + +void Field_blob::put_length(char *pos, uint32 length) +{ + switch (packlength) { + case 1: + *pos= (char) length; + break; + case 2: + int2store(pos, length); + break; + case 3: + int3store(pos, length); + break; + case 4: + int4store(pos, length); + break; + } +} + + void Field_blob::store(const char *from,uint len) { if (!len) @@ -4525,6 +4561,50 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length) return to+length; } + +/* + Unpack a blob key into a record buffer. + + SYNOPSIS + Field_blob::unpack_key() + to Pointer into the record buffer. + from Pointer to the packed key. + max_length Key length limit from key description. + + DESCRIPTION + A blob key has a maximum size of 64K-1. + In its packed form, the length field is one or two bytes long, + depending on 'max_length'. + Depending on the maximum length of a blob, its length field is + put into 1 to 4 bytes. This is a property of the blob object, + described by 'packlength'. + Blobs are internally stored apart from the record buffer, which + contains a pointer to the blob buffer. + + RETURN + Pointer into 'from' past the last byte copied from packed key. +*/ + +const char *Field_blob::unpack_key(char *to, const char *from, uint max_length) +{ + /* get length of the blob key */ + uint32 length= *((uchar*) from++); + if (max_length > 255) + length+= (*((uchar*) from++)) << 8; + + /* put the length into the record buffer */ + put_length(to, length); + + /* put the address of the blob buffer or NULL */ + if (length) + memcpy_fixed(to + packlength, &from, sizeof(from)); + else + bzero(to + packlength, sizeof(from)); + + /* point to first byte of next field in 'from' */ + return from + length; +} + /* Create a packed key that will be used for storage from a MySQL key */ char *Field_blob::pack_key_from_key_image(char *to, const char *from, diff --git a/sql/field.h b/sql/field.h index 5a1ab163266..d93ed1db9b5 100644 --- a/sql/field.h +++ b/sql/field.h @@ -189,6 +189,10 @@ public: { return pack(to,from,max_length); } + virtual const char *unpack_key(char* to, const char *from, uint max_length) + { + return unpack(to,from); + } virtual uint packed_col_length(const char *to, uint length) { return length;} virtual uint max_packed_col_length(uint max_length) @@ -890,6 +894,7 @@ public: inline uint32 get_length(uint row_offset=0) { return get_length(ptr+row_offset); } uint32 get_length(const char *ptr); + void put_length(char *pos, uint32 length); bool binary() const { return binary_flag; } inline void get_ptr(char **str) { @@ -923,6 +928,7 @@ public: const char *unpack(char *to, const char *from); char *pack_key(char *to, const char *from, uint max_length); char *pack_key_from_key_image(char* to, const char *from, uint max_length); + const char *unpack_key(char* to, const char *from, uint max_length); int pack_cmp(const char *a, const char *b, uint key_length); int pack_cmp(const char *b, uint key_length); uint packed_col_length(const char *col_ptr, uint length); diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 18af688d07c..b307b3a4b75 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -720,8 +720,8 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index) } record[key_part->null_offset]&= ~key_part->null_bit; } - pos= (char*) key_part->field->unpack(record + key_part->field->offset(), - pos); + pos= (char*) key_part->field->unpack_key(record + key_part->field->offset(), + pos, key_part->length); } } |