Below is the list of changes that have just been committed into a local
4.0 repository of mydev. When mydev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2155 05/09/23 10:15:11 ingo@stripped +7 -0
Bug#9112 - Merge table with composite index producing invalid results with some queries
The problem was an ab-use of last_rkey_length.
Formerly we saved the packed key length (of the search key)
in this element. But in certain cases it got replaced by
the (packed) result key length.
Now we use a new element of MI_INFO to save the packed key
length of the search key.
mysql-test/t/merge.test
1.23 05/09/23 10:15:08 ingo@stripped +33 -0
Bug#9112 - Merge table with composite index producing invalid results with some queries
The test case.
mysql-test/r/merge.result
1.25 05/09/23 10:15:08 ingo@stripped +26 -0
Bug#9112 - Merge table with composite index producing invalid results with some queries
The test result.
myisammrg/myrg_rkey.c
1.16 05/09/23 10:15:08 ingo@stripped +12 -5
Bug#9112 - Merge table with composite index producing invalid results with some queries
Changed to use the new element of MI_INFO to get at the
packed key length.
myisam/myisamdef.h
1.63 05/09/23 10:15:08 ingo@stripped +1 -0
Bug#9112 - Merge table with composite index producing invalid results with some queries
Added a new element to store the packed key length
for use by the MyISAMMRG engine.
myisam/mi_search.c
1.43 05/09/23 10:15:08 ingo@stripped +13 -3
Bug#9112 - Merge table with composite index producing invalid results with some queries
Added a comment and trace prints.
myisam/mi_rkey.c
1.14 05/09/23 10:15:08 ingo@stripped +5 -2
Bug#9112 - Merge table with composite index producing invalid results with some queries
Saved the packed key length in a new element of MI_INFO.
myisam/mi_dbug.c
1.11 05/09/23 10:15:08 ingo@stripped +2 -2
Bug#9112 - Merge table with composite index producing invalid results with some queries
Fixed the recognition of NULL values in _mi_print_key().
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: ingo
# Host: chilla.local
# Root: /home/mydev/mysql-4.0-4000
--- 1.10/myisam/mi_dbug.c 2003-12-14 14:12:05 +01:00
+++ 1.11/myisam/mi_dbug.c 2005-09-23 10:15:08 +02:00
@@ -40,12 +40,12 @@
end= key+ keyseg->length;
if (keyseg->flag & HA_NULL_PART)
{
- if (!*key)
+ /* A NULL value is encoded by a 1-byte flag. Zero means NULL. */
+ if (! *(key++))
{
fprintf(stream,"NULL");
continue;
}
- key++;
}
switch (keyseg->type) {
--- 1.13/myisam/mi_rkey.c 2003-04-30 09:15:08 +02:00
+++ 1.14/myisam/mi_rkey.c 2005-09-23 10:15:08 +02:00
@@ -31,8 +31,8 @@
MI_KEYSEG *last_used_keyseg;
uint pack_key_length, use_key_length, nextflag;
DBUG_ENTER("mi_rkey");
- DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d",
- info,inx,search_flag));
+ DBUG_PRINT("enter", ("base: %p buf: %p inx: %d search_flag: %d",
+ info, buf, inx, search_flag));
if ((inx = _mi_check_index(info,inx)) < 0)
DBUG_RETURN(my_errno);
@@ -44,9 +44,12 @@
{
if (key_len == 0)
key_len=USE_WHOLE_KEY;
+ /* Save the packed key for later use in the second buffer of lastkey. */
key_buff=info->lastkey+info->s->base.max_key_length;
pack_key_length=_mi_pack_key(info, (uint) inx, key_buff, (uchar*) key,
key_len, &last_used_keyseg);
+ /* Save packed_key_length for use by the MERGE engine. */
+ info->pack_key_length= pack_key_length;
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg,
key_buff, pack_key_length););
}
--- 1.42/myisam/mi_search.c 2004-07-26 15:32:50 +02:00
+++ 1.43/myisam/mi_search.c 2005-09-23 10:15:08 +02:00
@@ -1237,11 +1237,21 @@
reg1 MI_KEYSEG *keyseg;
uchar *start_key,*page,*page_end,*from,*from_end;
uint length,tmp;
+ DBUG_ENTER("_mi_get_binary_pack_key");
page= *page_pos;
page_end=page+MI_MAX_KEY_BUFF+1;
start_key=key;
+ /*
+ Keys are compressed the following way:
+
+ prefix length Packed length of prefix for the prev key. (1 or 3 bytes)
+ for each key segment:
+ [is null] Null indicator if can be null (1 byte, zero means null)
+ [length] Packed length if varlength (1 or 3 bytes)
+ pointer Reference to the data file (last_keyseg->length).
+ */
get_key_length(length,page);
if (length)
{
@@ -1251,7 +1261,7 @@
length, keyinfo->maxlength, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
my_errno=HA_ERR_CRASHED;
- return 0; /* Wrong key */
+ DBUG_RETURN(0); /* Wrong key */
}
from=key; from_end=key+length;
}
@@ -1312,12 +1322,12 @@
{
DBUG_PRINT("error",("Error when unpacking key"));
my_errno=HA_ERR_CRASHED;
- return 0; /* Error */
+ DBUG_RETURN(0); /* Error */
}
memcpy((byte*) key,(byte*) from,(size_t) length);
*page_pos= from+length;
}
- return((uint) (key-start_key)+keyseg->length);
+ DBUG_RETURN((uint) (key-start_key)+keyseg->length);
}
--- 1.62/myisam/myisamdef.h 2004-01-20 09:05:35 +01:00
+++ 1.63/myisam/myisamdef.h 2005-09-23 10:15:08 +02:00
@@ -255,6 +255,7 @@
uint lastkey_length; /* Length of key in lastkey */
uint last_rkey_length; /* Last length in mi_rkey() */
uint save_lastkey_length;
+ uint pack_key_length; /* For MYISAMMRG */
int errkey; /* Got last error on this key */
int lock_type; /* How database was locked */
int tmp_lock_type; /* When locked by readinfo */
--- 1.24/mysql-test/r/merge.result 2004-08-27 13:42:58 +02:00
+++ 1.25/mysql-test/r/merge.result 2005-09-23 10:15:08 +02:00
@@ -619,3 +619,29 @@
create table t3 engine=merge union=(t1, t2) select * from t2;
INSERT TABLE 't2' isn't allowed in FROM table list
drop table t1, t2;
+create table t1 (
+a double(16,6),
+b varchar(10),
+index (a,b)
+) engine=merge union=(t2,t3);
+create table t2 (
+a double(16,6),
+b varchar(10),
+index (a,b)
+) engine=myisam;
+create table t3 (
+a double(16,6),
+b varchar(10),
+index (a,b)
+) engine=myisam;
+insert into t2 values ( null, '');
+insert into t2 values ( 9999999999.999999, '');
+insert into t3 select * from t2;
+select min(a), max(a) from t1;
+min(a) max(a)
+9999999999.999998 9999999999.999998
+flush tables;
+select min(a), max(a) from t1;
+min(a) max(a)
+9999999999.999998 9999999999.999998
+drop table t1, t2, t3;
--- 1.22/mysql-test/t/merge.test 2004-08-27 13:42:58 +02:00
+++ 1.23/mysql-test/t/merge.test 2005-09-23 10:15:08 +02:00
@@ -264,3 +264,36 @@
--error 1093
create table t3 engine=merge union=(t1, t2) select * from t2;
drop table t1, t2;
+
+#
+# Bug#9112 - Merge table with composite index producing invalid results with some queries
+# This test case will fail only without the bugfix and some
+# non-deterministic circumstances. It depends on properly initialized
+# "un-initialized" memory. At the time it happens with a standard
+# non-debug build. But there is no guarantee that this will be always so.
+#
+create table t1 (
+ a double(16,6),
+ b varchar(10),
+ index (a,b)
+) engine=merge union=(t2,t3);
+
+create table t2 (
+ a double(16,6),
+ b varchar(10),
+ index (a,b)
+) engine=myisam;
+
+create table t3 (
+ a double(16,6),
+ b varchar(10),
+ index (a,b)
+) engine=myisam;
+
+insert into t2 values ( null, '');
+insert into t2 values ( 9999999999.999999, '');
+insert into t3 select * from t2;
+select min(a), max(a) from t1;
+flush tables;
+select min(a), max(a) from t1;
+drop table t1, t2, t3;
--- 1.15/myisammrg/myrg_rkey.c 2003-08-01 14:58:00 +02:00
+++ 1.16/myisammrg/myrg_rkey.c 2005-09-23 10:15:08 +02:00
@@ -44,11 +44,12 @@
MYRG_TABLE *table;
MI_INFO *mi;
int err;
+ DBUG_ENTER("myrg_rkey");
LINT_INIT(key_buff);
LINT_INIT(pack_key_length);
if (_myrg_init_queue(info,inx,search_flag))
- return my_errno;
+ DBUG_RETURN(my_errno);
for (table=info->open_tables ; table != info->end_table ; table++)
{
@@ -57,8 +58,9 @@
if (table == info->open_tables)
{
err=mi_rkey(mi,0,inx,key,key_len,search_flag);
+ /* Get the saved packed key and packed key length. */
key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
- pack_key_length=mi->last_rkey_length;
+ pack_key_length=mi->pack_key_length;
}
else
{
@@ -72,16 +74,21 @@
{
if (err == HA_ERR_KEY_NOT_FOUND)
continue;
- return err;
+ DBUG_PRINT("exit", ("err: %d", err));
+ DBUG_RETURN(err);
}
/* adding to queue */
queue_insert(&(info->by_key),(byte *)table);
}
+ DBUG_PRINT("info", ("tables with matches: %u", info->by_key.elements));
if (!info->by_key.elements)
- return HA_ERR_KEY_NOT_FOUND;
+ DBUG_RETURN(HA_ERR_KEY_NOT_FOUND);
mi=(info->current_table=(MYRG_TABLE *)queue_top(&(info->by_key)))->table;
- return _myrg_mi_read_record(mi,buf);
+ DBUG_PRINT("info", ("using table no: %d",
+ info->current_table - info->open_tables + 1));
+ DBUG_DUMP("result key", (byte*) mi->lastkey, mi->lastkey_length);
+ DBUG_RETURN(_myrg_mi_read_record(mi,buf));
}
| Thread |
|---|
| • bk commit into 4.0 tree (ingo:1.2155) BUG#9112 | ingo | 23 Sep |