diff --git a/VC++Files/libmysql/libmysql.dsp b/VC++Files/libmysql/libmysql.dsp index bddf1988e03779d024d20de611310178a5fdfedc..43dee62061ffa15639fc0c8dbf3160f80e2f2032 100644 --- a/VC++Files/libmysql/libmysql.dsp +++ b/VC++Files/libmysql/libmysql.dsp @@ -25,7 +25,7 @@ CFG=libmysql - Win32 Debug # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" -CPP=cl.exe +CPP=xicl6.exe MTL=midl.exe RSC=rc.exe @@ -52,14 +52,14 @@ RSC=rc.exe BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=link.exe +LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 # ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" -PostBuild_Desc=Copy .lib file -PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release\ +PostBuild_Desc=Move DLL export lib +PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release /y # End Special Build Tool !ELSEIF "$(CFG)" == "libmysql - Win32 Debug" @@ -85,14 +85,14 @@ PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release\ BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo -LINK32=link.exe +LINK32=xilink6.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug" # SUBTRACT LINK32 /pdb:none # Begin Special Build Tool SOURCE="$(InputPath)" -PostBuild_Desc=Copy .lib file -PostBuild_Cmds=xcopy ..\lib_debug\libmysql.dll C:\winnt\system32\ xcopy debug\libmysql.lib ..\lib_debug\ +PostBuild_Desc=Move DLL export lib +PostBuild_Cmds=xcopy ..\lib_debug\libmysql.dll C:\winnt\system32\ /y xcopy debug\libmysql.lib ..\lib_debug\ /y # End Special Build Tool !ENDIF @@ -239,6 +239,10 @@ SOURCE=..\mysys\mf_pack.c # End Source File # Begin Source File +SOURCE=..\mysys\mf_path.c +# End Source File +# Begin Source File + SOURCE=..\mysys\mf_unixpath.c # End Source File # Begin Source File @@ -395,6 +399,10 @@ SOURCE=..\client\select_test.c # End Source File # Begin Source File +SOURCE=..\mysys\sha1.c +# End Source File +# Begin Source File + SOURCE=..\client\sql_string.cpp # End Source File # Begin Source File diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 9ec1ca99e0eddfd54b7cddc5a1ac001f5bf42683..5b167cc9ab01b786a51d129925a26a0bb2176fba 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -136,11 +136,26 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, } /* _mi_make_key */ - /* Pack a key to intern format from given format (c_rkey) */ - /* returns length of packed key */ +/* + Pack a key to intern format from given format (c_rkey) + + SYNOPSIS + _mi_pack_key() + info MyISAM handler + uint keynr key number + key Store packed key here + old Not packed key + k_length Length of 'old' to use + last_used_keyseg out parameter. May be NULL + + RETURN + length of packed key + + last_use_keyseg Store pointer to the keyseg after the last used one +*/ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, - uint k_length) + uint k_length, MI_KEYSEG **last_used_keyseg) { uint length; uchar *pos,*end,*start_key=key; @@ -211,6 +226,8 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old, key+= length; k_length-=length; } + if (last_used_keyseg) + *last_used_keyseg= keyseg; #ifdef NOT_USED if (keyseg->type) diff --git a/myisam/mi_range.c b/myisam/mi_range.c index 70694bf462065106f6c7201e2fe91fd4da410e2f..8e85afc5f805a5abb9452659691d0cbd83a4fd3e 100644 --- a/myisam/mi_range.c +++ b/myisam/mi_range.c @@ -83,7 +83,8 @@ static ha_rows _mi_record_pos(MI_INFO *info, const byte *key, uint key_len, if (key_len == 0) key_len=USE_WHOLE_KEY; key_buff=info->lastkey+info->s->base.max_key_length; - key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len); + key_len=_mi_pack_key(info,inx,key_buff,(uchar*) key,key_len, + (MI_KEYSEG**) 0); DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg, (uchar*) key_buff,key_len);); nextflag=myisam_read_vec[search_flag]; diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 86547d3ef04b0139f18e20495846b6659b03ecc1..60dec0449a01a90ef37aebdda4e56e20021b462b 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -23,10 +23,12 @@ /* Ordinary search_flag is 0 ; Give error if no record with key */ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, - enum ha_rkey_function search_flag) + enum ha_rkey_function search_flag) { uchar *key_buff; MYISAM_SHARE *share=info->s; + MI_KEYDEF *keyinfo; + 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", @@ -36,23 +38,27 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, DBUG_RETURN(my_errno); info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); + keyinfo= share->keyinfo + inx; if (!info->use_packed_key) { if (key_len == 0) key_len=USE_WHOLE_KEY; 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); - info->last_rkey_length=pack_key_length; - DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,share->keyinfo[inx].seg, - key_buff,pack_key_length);); + pack_key_length=_mi_pack_key(info, (uint) inx, key_buff, (uchar*) key, + key_len, &last_used_keyseg); + DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg, + key_buff, pack_key_length);); } else { - /* key is already packed! */ + /* + key is already packed!; This happens when we are using a MERGE TABLE + */ key_buff=info->lastkey+info->s->base.max_key_length; - info->last_rkey_length=pack_key_length=key_len; + pack_key_length= key_len; bmove(key_buff,key,key_len); + last_used_keyseg= 0; } if (fast_mi_readinfo(info)) @@ -65,8 +71,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))) use_key_length=USE_WHOLE_KEY; - if (!_mi_search(info,info->s->keyinfo+inx,key_buff,use_key_length, - myisam_read_vec[search_flag],info->s->state.key_root[inx])) + if (!_mi_search(info,keyinfo, key_buff, use_key_length, + myisam_read_vec[search_flag], info->s->state.key_root[inx])) { while (info->lastpos >= info->state->data_file_length) { @@ -76,7 +82,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, exact key, because the keys are sorted according to position */ - if (_mi_search_next(info,info->s->keyinfo+inx,info->lastkey, + if (_mi_search_next(info, keyinfo, info->lastkey, info->lastkey_length, myisam_readnext_vec[search_flag], info->s->state.key_root[inx])) @@ -86,6 +92,12 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); + /* Calculate length of the found key; Used by mi_rnext_same */ + if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg) + info->last_rkey_length= _mi_keylength_part(keyinfo, info->lastkey, + last_used_keyseg); + else + info->last_rkey_length= pack_key_length; if (!buf) DBUG_RETURN(info->lastpos==HA_OFFSET_ERROR ? my_errno : 0); @@ -99,6 +111,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, /* Store key for read next */ memcpy(info->lastkey,key_buff,pack_key_length); + info->last_rkey_length= pack_key_length; bzero((char*) info->lastkey+pack_key_length,info->s->base.rec_reflength); info->lastkey_length=pack_key_length+info->s->base.rec_reflength; diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 41d53e762419f90b7f98d0e02fd96468efef784b..32db69144d86985f8f73f89e86024886e022e8d8 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -1441,6 +1441,37 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key) } /* _mi_keylength */ +/* + Calculate length of part key. + + Used in mi_rkey() to find the key found for the key-part that was used. + This is needed in case of multi-byte character sets where we may search + after '0xDF' but find 'ss' +*/ + +uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key, + MI_KEYSEG *end) +{ + reg1 MI_KEYSEG *keyseg; + uchar *start= key; + + for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++) + { + if (keyseg->flag & HA_NULL_PART) + if (!*key++) + continue; + if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH)) + { + uint length; + get_key_length(length,key); + key+=length; + } + else + key+= keyseg->length; + } + return (uint) (key-start); +} + /* Move a key */ uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from) diff --git a/myisam/mi_test2.c b/myisam/mi_test2.c index 93538e3ead71a1aae521a0173d583f5e4e3b76ca..e3a2ecfbb1f00404ad400dd12aacc14376008b21 100644 --- a/myisam/mi_test2.c +++ b/myisam/mi_test2.c @@ -639,14 +639,14 @@ int main(int argc, char *argv[]) if ((long) range_records < (long) records*7/10-2 || (long) range_records > (long) records*14/10+2) { - printf("mi_records_range for key: %d returned %ld; Should be about %ld\n", - i, range_records, records); + printf("mi_records_range for key: %d returned %lu; Should be about %lu\n", + i, (ulong) range_records, (ulong) records); goto end; } if (verbose && records) { - printf("mi_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n", - range_records,records, + printf("mi_records_range returned %lu; Exact is %lu (diff: %4.2g %%)\n", + (ulong) range_records, (ulong) records, labs((long) range_records-(long) records)*100.0/records); } @@ -660,8 +660,8 @@ int main(int argc, char *argv[]) || info.keys != keys) { puts("Wrong info from mi_info"); - printf("Got: records: %ld delete: %ld i_keys: %d\n", - info.records,info.deleted,info.keys); + printf("Got: records: %lu delete: %lu i_keys: %d\n", + (ulong) info.records, (ulong) info.deleted, info.keys); } if (verbose) { diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 7c035bc60974181a53814f614279d8725613f2bb..7631b245b9b2a5df5a5464d50d3b5a9da7f2defa 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -505,6 +505,8 @@ extern uchar *_mi_get_last_key(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *keypos, extern uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uchar *key, uchar *keypos, uint *return_key_length); extern uint _mi_keylength(MI_KEYDEF *keyinfo,uchar *key); +extern uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key, + MI_KEYSEG *end); extern uchar *_mi_move_key(MI_KEYDEF *keyinfo,uchar *to,uchar *from); extern int _mi_search_next(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, uint key_length,uint nextflag,my_off_t pos); @@ -519,7 +521,7 @@ extern my_off_t _mi_new(MI_INFO *info,MI_KEYDEF *keyinfo); extern uint _mi_make_key(MI_INFO *info,uint keynr,uchar *key, const byte *record,my_off_t filepos); extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old, - uint key_length); + uint key_length, MI_KEYSEG **last_used_keyseg); extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf); extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos, uint length,int re_read_if_possibly); diff --git a/myisam/sort.c b/myisam/sort.c index ddf565d5092d22108aaece03e4bab01fa5ebf230..224b4ad842081e07101079dc6b9d66fce9e99a26 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -163,8 +163,8 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (maxbuffer == 0) { if (!no_messages) - printf(" - Dumping %lu keys\n",records); - if (write_index(info,sort_keys,(uint) records)) + printf(" - Dumping %lu keys\n", (ulong) records); + if (write_index(info,sort_keys, (uint) records)) goto err; /* purecov: inspected */ } else @@ -173,7 +173,7 @@ int _create_index_by_sort(MI_SORT_PARAM *info,my_bool no_messages, if (maxbuffer >= MERGEBUFF2) { if (!no_messages) - printf(" - Merging %lu keys\n",records); /* purecov: tested */ + printf(" - Merging %lu keys\n", (ulong) records); /* purecov: tested */ if (merge_many_buff(info,keys,sort_keys, dynamic_element(&buffpek,0,BUFFPEK *),&maxbuffer,&tempfile)) goto err; /* purecov: inspected */ diff --git a/mysql-test/r/ctype_latin1_de.result b/mysql-test/r/ctype_latin1_de.result index b79bc67138c177dc7fb4b5fc7b02dd73faf89649..630fef9b679113a29cdce01441d86e38ee259acb 100644 --- a/mysql-test/r/ctype_latin1_de.result +++ b/mysql-test/r/ctype_latin1_de.result @@ -212,3 +212,55 @@ select * from t1 where match a against ("te*" in boolean mode)+0; a test drop table t1; +create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word)); +insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae'); +update t1 set word2=word; +select word, word=0xdf as t from t1 having t > 0; +word t +ß 1 +select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0; +word t +ss 1 +ß 1 +select * from t1 where word=0xDF; +word word2 +ß ß +select * from t1 where word=CAST(0xDF as CHAR); +word word2 +ss ss +ß ß +select * from t1 where word2=0xDF; +word word2 +ß ß +select * from t1 where word2=CAST(0xDF as CHAR); +word word2 +ss ss +ß ß +select * from t1 where word='ae'; +word word2 +ä ä +ae ae +select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR); +word word2 +ä ä +ae ae +select * from t1 where word between 0xDF and 0xDF; +word word2 +ß ß +select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR); +word word2 +ss ss +ß ß +select * from t1 where word like 'ae'; +word word2 +ae ae +select * from t1 where word like 'AE'; +word word2 +ae ae +select * from t1 where word like 0xDF; +word word2 +ß ß +select * from t1 where word like CAST(0xDF as CHAR); +word word2 +ß ß +drop table t1; diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 1b5766e3ab45c57f41815288ddfc2fdf9a276021..e063b5c3e02004f7dd012c8b31c7ce849a19b2f4 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -273,8 +273,16 @@ cust 20 SELECT emp.rate_code, lr.base_rate FROM t1 AS emp LEFT JOIN t2 AS lr USING (siteid, rate_code) WHERE lr.siteid = 'rivercats' AND emp.emp_id = 'psmith'; rate_code base_rate cust 20 +drop table t1,t2; +CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, Value1 VARCHAR(255)); +CREATE TABLE t2 (ID INTEGER NOT NULL PRIMARY KEY, Value2 VARCHAR(255)); +INSERT INTO t1 VALUES (1, 'A'); +INSERT INTO t2 VALUES (1, 'B'); +SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND (Value1 = 'A' AND Value2 <> 'B'); ID Value1 ID Value2 +SELECT * FROM t1 NATURAL JOIN t2 WHERE 1 AND Value1 = 'A' AND Value2 <> 'B'; ID Value1 ID Value2 +SELECT * FROM t1 NATURAL JOIN t2 WHERE (Value1 = 'A' AND Value2 <> 'B') AND 1; ID Value1 ID Value2 drop table t1,t2; create table t1 (i int); diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index 8b50f9a92e81174a05b83fb1b9a4e9ed4bb542ae..adc09ded0e2ac14dd0fdfe79edede5ac4df13034 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -4,4 +4,8 @@ repair table t1 use_frm; Table Op Msg_type Msg_text test.t1 repair warning Number of rows changed from 0 to 1 test.t1 repair status OK -drop table if exists t1; +alter table t1 TYPE=HEAP; +repair table t1 use_frm; +Table Op Msg_type Msg_text +test.t1 repair error The handler for the table doesn't support repair +drop table t1; diff --git a/mysql-test/r/rpl_alter.result b/mysql-test/r/rpl_alter.result index 1dc73c6524a6ca711307ec54782b4faf5b2e6a11..729c7df6808452cca04a76a3c52561d9ef8c92ac 100644 --- a/mysql-test/r/rpl_alter.result +++ b/mysql-test/r/rpl_alter.result @@ -4,18 +4,18 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; slave start; -drop database if exists d1; -create database d1; -create table d1.t1 ( n int); -alter table d1.t1 add m int; -insert into d1.t1 values (1,2); -create table d1.t2 (n int); -insert into d1.t2 values (45); -rename table d1.t2 to d1.t3, d1.t1 to d1.t2; -select * from d1.t2; +drop database if exists test_$1; +create database test_$1; +create table test_$1.t1 ( n int); +alter table test_$1.t1 add m int; +insert into test_$1.t1 values (1,2); +create table test_$1.t2 (n int); +insert into test_$1.t2 values (45); +rename table test_$1.t2 to test_$1.t3, test_$1.t1 to test_$1.t2; +select * from test_$1.t2; n m 1 2 -select * from d1.t3; +select * from test_$1.t3; n 45 -drop database d1; +drop database test_$1; diff --git a/mysql-test/t/ctype_latin1_de-master.opt b/mysql-test/t/ctype_latin1_de-master.opt index 98accd58c462dddc11e919b46ecb563759f078c0..895a62364d62e63a189c7278854801f81162a739 100644 --- a/mysql-test/t/ctype_latin1_de-master.opt +++ b/mysql-test/t/ctype_latin1_de-master.opt @@ -1 +1,2 @@ ---default-character-set=latin1_de +--default-character-set=latin1_de --new + diff --git a/mysql-test/t/ctype_latin1_de.test b/mysql-test/t/ctype_latin1_de.test index 4b96f5f58674e4ea368ab9be636672dcc66c0a77..6353650f420b432750d20e650611819c7147ec0f 100644 --- a/mysql-test/t/ctype_latin1_de.test +++ b/mysql-test/t/ctype_latin1_de.test @@ -45,3 +45,26 @@ select * from t1 where a like "test%"; select * from t1 where a like "te_t"; select * from t1 where match a against ("te*" in boolean mode)+0; drop table t1; + +# +# Test bug report #152 (problem with index on latin1_de) +# + +create table t1 (word varchar(255) not null, word2 varchar(255) not null, index(word)); +insert into t1 (word) values ('ss'),(0xDF),(0xE4),('ae'); +update t1 set word2=word; +select word, word=0xdf as t from t1 having t > 0; +select word, word=cast(0xdf AS CHAR) as t from t1 having t > 0; +select * from t1 where word=0xDF; +select * from t1 where word=CAST(0xDF as CHAR); +select * from t1 where word2=0xDF; +select * from t1 where word2=CAST(0xDF as CHAR); +select * from t1 where word='ae'; +select * from t1 where word= 0xe4 or word=CAST(0xe4 as CHAR); +select * from t1 where word between 0xDF and 0xDF; +select * from t1 where word between CAST(0xDF AS CHAR) and CAST(0xDF AS CHAR); +select * from t1 where word like 'ae'; +select * from t1 where word like 'AE'; +select * from t1 where word like 0xDF; +select * from t1 where word like CAST(0xDF as CHAR); +drop table t1; diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index 6d79014b23db50d0dd5d32bb128abb032b69a7ea..b901fb3467fc974d38ea09def7fc8d18b2fb410d 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -5,4 +5,6 @@ drop table if exists t1; create table t1 SELECT 1,"table 1"; repair table t1 use_frm; -drop table if exists t1; +alter table t1 TYPE=HEAP; +repair table t1 use_frm; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index eb7d3dc56864b600f823327b11d976a854d3842b..a2663626723ddc9c625c1cc4fa57471a06634539 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -162,6 +162,14 @@ static bool test_if_real(const char *str,int length) } +static inline uint field_length_without_space(const char *ptr, uint length) +{ + const char *end= ptr+length; + while (end > ptr && end[-1] == ' ') + end--; + return (uint) (end-ptr); +} + /**************************************************************************** ** Functions for the base classes ** This is an unpacked number. @@ -3673,8 +3681,21 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr) { if (binary_flag) return memcmp(a_ptr,b_ptr,field_length); - else - return my_sortcmp(a_ptr,b_ptr,field_length); +#ifdef USE_STRCOLL + if (use_strcoll(default_charset_info)) + { + /* + We have to remove end space to be able to compare multi-byte-characters + like in latin_de 'ae' and 0xe4 + */ + uint a_length= field_length_without_space(a_ptr, field_length); + uint b_length= field_length_without_space(b_ptr, field_length); + return my_strnncoll(default_charset_info, + (const uchar*) a_ptr, a_length, + (const uchar*) b_ptr, b_length); + } +#endif + return my_sortcmp(a_ptr,b_ptr,field_length); } void Field_string::sort_string(char *to,uint length) diff --git a/sql/item.cc b/sql/item.cc index 4fefae7358fe83461c2aafc89b8b802ad0b386b4..79501755cbf01bd5b3949b2ab64a60ed3efc24b1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -576,6 +576,14 @@ inline uint char_val(char X) X-'a'+10); } +/* In MySQL 4.1 this will always return STRING_RESULT */ + +enum Item_result Item_varbinary::result_type () const +{ + return (current_thd->variables.new_mode) ? STRING_RESULT : INT_RESULT; +} + + Item_varbinary::Item_varbinary(const char *str, uint str_length) { name=(char*) str-2; // Lex makes this start with 0x diff --git a/sql/item.h b/sql/item.h index 5e2c2ccc05659aba9944dfea7a6055ec4dee6342..09d428509d053073bb3a0a3fdbc359a3ce3333cb 100644 --- a/sql/item.h +++ b/sql/item.h @@ -353,7 +353,7 @@ class Item_varbinary :public Item String *val_str(String*) { return &str_value; } bool save_in_field(Field *field, bool no_conversions); void make_field(Send_field *field); - enum Item_result result_type () const { return INT_RESULT; } + enum Item_result result_type () const; unsigned int size_of() { return sizeof(*this);} }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fc2baf5784c5763563a747342eab6dd1b7924c07..2799bdf9f541cfb5a910377266502abfae52765b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -204,12 +204,12 @@ static char **opt_argv; #ifdef __WIN__ #undef MYSQL_SERVER_SUFFIX #ifdef __NT__ -#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) +#if defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max-nt" #else #define MYSQL_SERVER_SUFFIX "-nt" #endif /* ...DB */ -#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB) +#elif defined(HAVE_BERKELEY_DB) #define MYSQL_SERVER_SUFFIX "-max" #else #define MYSQL_SERVER_SUFFIX "" diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 5d3f9a0595cc7eb8b282360295430372302976ce..d6abe6497dfb860a312f76b7a9c1a72605598760 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -284,7 +284,6 @@ void field_str::add() char buff[MAX_FIELD_WIDTH], *ptr; String s(buff, sizeof(buff)), *res; ulong length; - TREE_ELEMENT *element; if (!(res = item->val_str(&s))) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0379c1de287c536fdc3aece0c620212e1c9ff29e..e02f457fd773e455173a19a645ea7577a2d90f95 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1029,7 +1029,7 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) #else error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime); #ifdef EXTRA_DEBUG - if (error && error != EINTR) + if (error && error != EINTR && error != ETIMEDOUT) { fprintf(stderr, "Got error %d from pthread_cond_timedwait\n",error); DBUG_PRINT("error",("Got error %d from pthread_cond_timedwait", diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index d670c673b4acd327a98c966c98fcd8d419a5477c..283dd20a56c128e573a64afe5496014097cdb813 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1042,6 +1042,9 @@ int show_binlog_events(THD* thd) } send_eof(&thd->net); + pthread_mutex_lock(&LOCK_thread_count); + thd->current_linfo = 0; + pthread_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(0); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f870f8f5178064c5a3718ad1f125faf87b7621dd..79ba13a3339d621450867489bbbf8c6bef8c02f0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2631,6 +2631,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) join->thd->select_limit)) < 0) DBUG_RETURN(1); // Impossible range sel->cond=orig_cond; + /* Fix for EXPLAIN */ + if (sel->quick) + join->best_positions[i].records_read= sel->quick->records; } else { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0fbb5807c57a8cbe347234e15a81b259d6373805..1b1b5112e0bb903ff398e6e5bd407b779d232dab 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -23,6 +23,7 @@ #endif #include <hash.h> #include <myisam.h> +#include <my_dir.h> #include <assert.h> #ifdef __WIN__ @@ -1046,12 +1047,31 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table, } else { + /* + User gave us USE_FRM which means that the header in the index file is + trashed. + In this case we will try to fix the table the following way: + - Rename the data file to a temporary name + - Truncate the table + - Replace the new data file with the old one + - Run a normal repair using the new index file and the old data file + */ - char from[FN_REFLEN],tmp[FN_REFLEN]; - char* db = thd->db ? thd->db : table->db; + char from[FN_REFLEN],tmp[FN_REFLEN+32]; + const char **ext= table->table->file->bas_ext(); + MY_STAT stat_info; + + /* + Check if this is a table type that stores index and data separately, + like ISAM or MyISAM + */ + if (!ext[0] || !ext[1]) + DBUG_RETURN(0); // No data file + + strxmov(from, table->table->path, ext[1], NullS); // Name of data file + if (!my_stat(from, &stat_info, MYF(0))) + DBUG_RETURN(0); // Can't use USE_FRM flag - sprintf(from, "%s/%s/%s", mysql_real_data_home, db, table->real_name); - fn_format(from, from, "", MI_NAME_DEXT, 4); sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); pthread_mutex_lock(&LOCK_open); @@ -1067,7 +1087,7 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table, unlock_table_name(thd, table); pthread_mutex_unlock(&LOCK_open); DBUG_RETURN(send_check_errmsg(thd, table, "repair", - "Failed renaming .MYD file")); + "Failed renaming data file")); } if (mysql_truncate(thd, table, 1)) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d7a0c15e9b965f044cf79821789d44af607ba26b..f895c809366c541b94cd067dd428e299593b3934 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2310,16 +2310,12 @@ olap_opt: | WITH CUBE_SYM { LEX *lex=Lex; - lex->olap = true; - lex->select->olap= CUBE_TYPE; net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "CUBE"); YYABORT; /* To be deleted in 4.1 */ } | WITH ROLLUP_SYM { LEX *lex=Lex; - lex->olap = true; - lex->select->olap= ROLLUP_TYPE; net_printf(&lex->thd->net, ER_NOT_SUPPORTED_YET, "ROLLUP"); YYABORT; /* To be deleted in 4.1 */ } @@ -2407,7 +2403,7 @@ delete_limit_clause: ULONG_NUM: NUM { $$= strtoul($1.str,NULL,10); } - | LONG_NUM { $$= (ulonglong) strtoll($1.str,NULL,10); } + | LONG_NUM { $$= (ulong) strtoll($1.str,NULL,10); } | ULONGLONG_NUM { $$= (ulong) strtoull($1.str,NULL,10); } | REAL_NUM { $$= strtoul($1.str,NULL,10); } | FLOAT_NUM { $$= strtoul($1.str,NULL,10); };