summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <ingo@mysql.com>2005-09-23 17:27:07 +0200
committerunknown <ingo@mysql.com>2005-09-23 17:27:07 +0200
commit944db06bbb328288d5e9cfc85de86876895b8b62 (patch)
tree48baa8a8836b9aa39f3616c84580cec8a057ba32
parent79b79064fafc92b5b5fcb5402ad7b2bace2cdb77 (diff)
parent9c0d809270a1d74ec33711d94cd65930eab11579 (diff)
downloadmariadb-git-944db06bbb328288d5e9cfc85de86876895b8b62.tar.gz
Merge mysql.com:/home/mydev/mysql-4.1-4100
into mysql.com:/home/mydev/mysql-5.0-5000 myisam/mi_dbug.c: Auto merged myisam/mi_rkey.c: Auto merged myisam/mi_search.c: Auto merged myisam/myisamdef.h: Auto merged mysql-test/r/merge.result: Auto merged mysql-test/t/merge.test: Auto merged
-rw-r--r--myisam/mi_dbug.c4
-rw-r--r--myisam/mi_rkey.c7
-rw-r--r--myisam/mi_search.c16
-rw-r--r--myisam/myisamdef.h1
-rw-r--r--myisammrg/myrg_rkey.c17
-rw-r--r--mysql-test/r/merge.result26
-rw-r--r--mysql-test/t/merge.test36
7 files changed, 95 insertions, 12 deletions
diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c
index e782d21afe7..ddc8a403a33 100644
--- a/myisam/mi_dbug.c
+++ b/myisam/mi_dbug.c
@@ -40,12 +40,12 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg,
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) {
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 635a7eb2c48..575a5e34488 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -31,8 +31,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
HA_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);
@@ -56,9 +56,12 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
{
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););
}
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index b7360dba7f3..185f196a814 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -915,11 +915,21 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
reg1 HA_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)
{
@@ -930,7 +940,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
DBUG_DUMP("key",(char*) *page_pos,16);
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
- return 0; /* Wrong key */
+ DBUG_RETURN(0); /* Wrong key */
}
from=key; from_end=key+length;
}
@@ -992,12 +1002,12 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
DBUG_PRINT("error",("Error when unpacking key"));
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
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);
}
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 82f7fd7360e..6b040f2ef0e 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -261,6 +261,7 @@ struct st_myisam_info {
uint last_rkey_length; /* Last length in mi_rkey() */
enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */
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 */
diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c
index a85ef6a3b5e..f87b264081e 100644
--- a/myisammrg/myrg_rkey.c
+++ b/myisammrg/myrg_rkey.c
@@ -44,11 +44,12 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
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 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
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
{
@@ -71,17 +73,22 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
{
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;
mi->once_flags|= RRND_PRESERVE_LASTINX;
- 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));
}
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index d4e19201173..4ddc1fdab12 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -653,6 +653,32 @@ ERROR HY000: You can't specify target table 't2' for update in FROM clause
create table t3 engine=merge union=(t1, t2) select (select max(a) from t2);
ERROR HY000: You can't specify target table 't2' for update in FROM clause
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;
create table t1 (a int,b int,c int, index (a,b,c));
create table t2 (a int,b int,c int, index (a,b,c));
create table t3 (a int,b int,c int, index (a,b,c))
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 7d708243a10..7cb8a089188 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -288,6 +288,42 @@ create table t3 engine=merge union=(t1, t2) select * from t2;
create table t3 engine=merge union=(t1, t2) select (select max(a) 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, '');
+# We may have insufficient accuracy for 16 digits of '9'.
+# Suppress a "truncate" warning due to accuracy problems.
+--disable_warnings
+insert into t2 values ( 9999999999.999999, '');
+--enable_warnings
+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;
# BUG#6699 : no sorting on 'ref' retrieval
create table t1 (a int,b int,c int, index (a,b,c));
create table t2 (a int,b int,c int, index (a,b,c));