summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoringo@mysql.com <>2004-06-25 14:44:37 +0200
committeringo@mysql.com <>2004-06-25 14:44:37 +0200
commit8db6c064dfb8f0d1eb255200125328217e323bbd (patch)
tree6d0e12ffaf9e7fc190cab4a67d9c64cfa69163b9
parent958cf857a3cee868ec11a4b352581554705ac3b2 (diff)
parent57da928039a322df37e17d1a139b42b76f45cdc1 (diff)
downloadmariadb-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.result16
-rw-r--r--mysql-test/t/bdb.test19
-rw-r--r--sql/field.cc80
-rw-r--r--sql/field.h6
-rw-r--r--sql/ha_berkeley.cc4
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);
}
}