diff options
author | unknown <ingo@mysql.com> | 2005-09-23 17:27:07 +0200 |
---|---|---|
committer | unknown <ingo@mysql.com> | 2005-09-23 17:27:07 +0200 |
commit | 944db06bbb328288d5e9cfc85de86876895b8b62 (patch) | |
tree | 48baa8a8836b9aa39f3616c84580cec8a057ba32 | |
parent | 79b79064fafc92b5b5fcb5402ad7b2bace2cdb77 (diff) | |
parent | 9c0d809270a1d74ec33711d94cd65930eab11579 (diff) | |
download | mariadb-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.c | 4 | ||||
-rw-r--r-- | myisam/mi_rkey.c | 7 | ||||
-rw-r--r-- | myisam/mi_search.c | 16 | ||||
-rw-r--r-- | myisam/myisamdef.h | 1 | ||||
-rw-r--r-- | myisammrg/myrg_rkey.c | 17 | ||||
-rw-r--r-- | mysql-test/r/merge.result | 26 | ||||
-rw-r--r-- | mysql-test/t/merge.test | 36 |
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)); |