diff --git a/Build-tools/mysql-copyright b/Build-tools/mysql-copyright index 70b65d3f2cf..a798ee7ab65 100755 --- a/Build-tools/mysql-copyright +++ b/Build-tools/mysql-copyright @@ -3,8 +3,11 @@ # Untar a MySQL distribution, change the copyright texts, # pack it up again to a given directory -$VER="1.2"; +$VER="1.3"; +use Cwd; +use File::Basename; +use File::Copy; use Getopt::Long; $opt_help = 0; @@ -17,8 +20,7 @@ GetOptions("help","version","target=s") || error(); # fix the directory prefix for target dir -$WD= `pwd`; -chop $WD; +$WD= cwd(); $opt_target= $WD . '/' . $opt_target; &main(); @@ -73,11 +75,11 @@ sub main $newdistname= $1."com".$2.$3; } # find out the extract path (should be same as distname!) - $destdir= `tar tvzf ../$distfile | head -1`; - # remove leading crab - $destdir =~ s/.*\d+:\d+:\d+[ ]//; - # remove newline and slash from the end - $destdir= substr($destdir, 0, -2); + chomp($destdir= `tar ztf ../$distfile | head -1`); + # remove slash from the end + $destdir= substr($destdir, 0, -1); + print "destdir: $destdir\n"; + print "distname: $distname\n"; if ("$destdir" ne "$distname") { @@ -96,15 +98,18 @@ sub main # remove the 'PUBLIC' file from distribution and copy MySQLEULA.txt # on the toplevel of the directory instead. file 'PUBLIC' shouldn't # exist in the new mysql distributions, but let's be sure.. - `rm -f $destdir/PUBLIC $destdir/README`; - `cp -p $WD/Docs/MySQLEULA.txt $destdir/`; + unlink("$destdir/PUBLIC", "$destdir/README"); + copy("$WD/Docs/MySQLEULA.txt", "$destdir"); + # remove readline subdir + `rm -rf $destdir/cmd-line-utils/readline`; + # fix file copyrights &fix_usage_copyright(); &add_copyright(); # rename the directory with new distribution name - `mv -f $destdir $newdistname`; + rename($destdir, $newdistname); # tar the new distribution `tar cz -f $opt_target/$newdistname.tar.gz *`; diff --git a/include/my_pthread.h b/include/my_pthread.h index f4976abee10..424452a9298 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -1,4 +1,3 @@ - /* Copyright (C) 2000 MySQL AB This program is free software; you can redistribute it and/or modify diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index ee71ffff2f0..2a0b17df043 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -13,6 +13,133 @@ hex(word) 0420 2004 DROP TABLE t1; +SET NAMES koi8r; +SET character_set_connection=ucs2; +create table t1 (a varchar(10) character set ucs2, key(a)); +insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test"); +explain select * from t1 where a like 'abc%'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 21 NULL 1 Using where; Using index +explain select * from t1 where a like concat('abc','%'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a a 21 NULL 1 Using where; Using index +select * from t1 where a like "abc%"; +a +abc +abcd +select * from t1 where a like concat("abc","%"); +a +abc +abcd +select * from t1 where a like "ABC%"; +a +abc +abcd +select * from t1 where a like "test%"; +a +test +select * from t1 where a like "te_t"; +a +test +select * from t1 where a like "%a%"; +a +select * from t1 where a like "%abcd%"; +a +abcd +select * from t1 where a like "%abc\d%"; +a +abcd +drop table t1; +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ucs2); +INSERT INTO t1 VALUES ('����'),('����'),('����'),('����'),('����'),('����'); +INSERT INTO t1 VALUES ('����������'),('����������'),('����������'),('����������'); +INSERT INTO t1 VALUES ('����������'),('����������'),('����������'),('����������'); +INSERT INTO t1 VALUES ('����������'),('����������'),('����������'),('����������'); +SELECT * FROM t1 WHERE a LIKE '%����%'; +a +���� +���� +���� +���� +���� +���� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +SELECT * FROM t1 WHERE a LIKE '%���%'; +a +���� +���� +���� +���� +���� +���� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +SELECT * FROM t1 WHERE a LIKE '����%'; +a +���� +���� +���� +���� +���� +���� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +���������� +SELECT * FROM t1 WHERE a LIKE '����%' COLLATE ucs2_bin; +a +���� +���������� +DROP TABLE t1; +CREATE TABLE t1 (word varchar(64) NOT NULL, PRIMARY KEY (word)) +TYPE=MyISAM CHARACTER SET ucs2 COLLATE ucs2_general_ci; +INSERT INTO t1 (word) VALUES ("cat"); +SELECT * FROM t1 WHERE word LIKE "c%"; +word +cat +SELECT * FROM t1 WHERE word LIKE "ca_"; +word +cat +SELECT * FROM t1 WHERE word LIKE "cat"; +word +cat +SELECT * FROM t1 WHERE word LIKE _ucs2 x'00630025'; +word +cat +SELECT * FROM t1 WHERE word LIKE _ucs2 x'00630061005F'; +word +cat +DROP TABLE t1; +SET NAMES latin1; CREATE TABLE t1 ( word VARCHAR(64), bar INT(11) default 0, diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index ee30baed008..80ae70c0fe2 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -29,6 +29,51 @@ INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020'); SELECT hex(word) FROM t1 ORDER BY word; DROP TABLE t1; +###################################################### +# +# Test of like +# + +SET NAMES koi8r; +SET character_set_connection=ucs2; + +create table t1 (a varchar(10) character set ucs2, key(a)); +insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test"); +explain select * from t1 where a like 'abc%'; +explain select * from t1 where a like concat('abc','%'); +select * from t1 where a like "abc%"; +select * from t1 where a like concat("abc","%"); +select * from t1 where a like "ABC%"; +select * from t1 where a like "test%"; +select * from t1 where a like "te_t"; +select * from t1 where a like "%a%"; +select * from t1 where a like "%abcd%"; +select * from t1 where a like "%abc\d%"; +drop table t1; + +CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET ucs2); +INSERT INTO t1 VALUES ('����'),('����'),('����'),('����'),('����'),('����'); +INSERT INTO t1 VALUES ('����������'),('����������'),('����������'),('����������'); +INSERT INTO t1 VALUES ('����������'),('����������'),('����������'),('����������'); +INSERT INTO t1 VALUES ('����������'),('����������'),('����������'),('����������'); +SELECT * FROM t1 WHERE a LIKE '%����%'; +SELECT * FROM t1 WHERE a LIKE '%���%'; +SELECT * FROM t1 WHERE a LIKE '����%'; +SELECT * FROM t1 WHERE a LIKE '����%' COLLATE ucs2_bin; +DROP TABLE t1; + +# +# Bug 1181 +# +CREATE TABLE t1 (word varchar(64) NOT NULL, PRIMARY KEY (word)) +TYPE=MyISAM CHARACTER SET ucs2 COLLATE ucs2_general_ci; +INSERT INTO t1 (word) VALUES ("cat"); +SELECT * FROM t1 WHERE word LIKE "c%"; +SELECT * FROM t1 WHERE word LIKE "ca_"; +SELECT * FROM t1 WHERE word LIKE "cat"; +SELECT * FROM t1 WHERE word LIKE _ucs2 x'00630025'; +SELECT * FROM t1 WHERE word LIKE _ucs2 x'00630061005F'; +DROP TABLE t1; ###################################################### @@ -53,6 +98,7 @@ DROP TABLE t1; # are not part of the index sorted on, it does a filesort, which fails. # Using a straight index yields correct results. +SET NAMES latin1; # # Two fields, index diff --git a/mysys/charset.c b/mysys/charset.c index a485835b636..7d0516ac81b 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -307,9 +307,23 @@ static int add_collation(CHARSET_INFO *cs) } else { + /* + We need the below to make get_charset_name() + and get_charset_number() working even if a + character set has not been really incompiled. + The above functions are used for example + in error message compiler extra/comp_err.c. + If a character set was compiled, this information + will get lost and overwritten in add_compiled_collation(). + */ CHARSET_INFO *dst= all_charsets[cs->number]; + dst->number= cs->number; if (cs->comment) dst->comment= my_once_strdup(cs->comment,MYF(MY_WME)); + if (cs->csname) + dst->csname= my_once_strdup(cs->csname,MYF(MY_WME)); + if (cs->name) + dst->name= my_once_strdup(cs->name,MYF(MY_WME)); } cs->number= 0; cs->primary_number= 0; diff --git a/sql/derror.cc b/sql/derror.cc index a35893be4fc..3eaa578d601 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -69,8 +69,8 @@ static void read_texts(const char *file_name,const char ***point, if (!head[30]) { - sql_print_error("No character set information in '%s'. \ -You probably haven't reinstalled the latest file version.",name); + sql_print_error("Character set information in not found in '%s'. \ +Please install the latest version of this file.",name); goto err1; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 13989bdae8f..1b481924690 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1,4 +1,3 @@ - /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB This program is free software; you can redistribute it and/or modify diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc index dc4f23db3b2..7126b7ee577 100644 --- a/sql/gen_lex_hash.cc +++ b/sql/gen_lex_hash.cc @@ -430,18 +430,9 @@ int main(int argc,char **argv) exit(1); printf("/* Copyright (C) 2001 MySQL AB\n\ - This program is free software; you can redistribute it and/or modify\n\ - it under the terms of the GNU General Public License as published by\n\ - the Free Software Foundation; either version 2 of the License, or\n\ - (at your option) any later version.\n\n\ - This program is distributed in the hope that it will be useful,\n\ - but WITHOUT ANY WARRANTY; without even the implied warranty of\n\ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\ - GNU General Public License for more details.\n\n\ - You should have received a copy of the GNU General Public License\n\ - along with this program; if not, write to the Free Software\n\ - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307\ - USA */\n\n"); + This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ + and you are welcome to modify and redistribute it under the GPL license\n\ + \n*/\n\n"); printf("/* This code is generated by gen_lex_hash.cc that seeks for\ a perfect\nhash function */\n\n"); diff --git a/sql/item.h b/sql/item.h index 9f767d502ba..b2d67a661a6 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 +/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2179ef1188e..e7dc3933c10 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 +/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/records.cc b/sql/records.cc index 72a6d480356..7ba9ff0f42f 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -1,4 +1,3 @@ - /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB This program is free software; you can redistribute it and/or modify diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 31c0f063529..cdcd91b2916 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -90,7 +90,7 @@ static uchar to_upper_ucs2[] = { }; -static int my_ucs2_uni (CHARSET_INFO *cs __attribute__((unused)) , +static int my_ucs2_uni (CHARSET_INFO *cs __attribute__((unused)), my_wc_t * pwc, const uchar *s, const uchar *e) { if (s+2 > e) /* Need 2 characters */ @@ -1018,21 +1018,268 @@ uint my_lengthsp_ucs2(CHARSET_INFO *cs __attribute__((unused)), return (uint) (end-ptr); } +/* +** Compare string against string with wildcard +** 0 if matched +** -1 if not matched with wildcard +** 1 if matched with wildcard +*/ + +static +int my_wildcmp_ucs2(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many, + MY_UNICASE_INFO **weights) +{ + int result= -1; /* Not found, using wildcards */ + my_wc_t s_wc, w_wc; + int scan, plane; + + while (wildstr != wildend) + { + + while (1) + { + scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend); + if (scan <= 0) + return 1; + wildstr+= scan; + + if (w_wc == (my_wc_t)escape) + { + scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend); + if (scan <= 0) + return 1; + wildstr+= scan; + } + + if (w_wc == (my_wc_t)w_many) + { + result= 1; /* Found an anchor char */ + break; + } + + scan= my_ucs2_uni(cs, &s_wc, (const uchar*)str, (const uchar*)str_end); + if (scan <=0) + return 1; + str+= scan; + + if (w_wc == (my_wc_t)w_one) + { + result= 1; /* Found an anchor char */ + } + else + { + if (weights) + { + plane=(s_wc>>8) & 0xFF; + s_wc = weights[plane] ? weights[plane][s_wc & 0xFF].sort : s_wc; + plane=(w_wc>>8) & 0xFF; + w_wc = weights[plane] ? weights[plane][w_wc & 0xFF].sort : w_wc; + } + if (s_wc != w_wc) + return 1; /* No match */ + } + if (wildstr == wildend) + return (str != str_end); /* Match if both are at end */ + } + + + if (w_wc == (my_wc_t)w_many) + { /* Found w_many */ + + /* Remove any '%' and '_' from the wild search string */ + for ( ; wildstr != wildend ; ) + { + scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend); + if (scan <= 0) + return 1; + wildstr+= scan; + + if (w_wc == (my_wc_t)w_many) + continue; + + if (w_wc == (my_wc_t)w_one) + { + scan= my_ucs2_uni(cs, &s_wc, (const uchar*)str, (const uchar*)str_end); + if (scan <=0) + return 1; + str+= scan; + continue; + } + break; /* Not a wild character */ + } + + if (wildstr == wildend) + return 0; /* Ok if w_many is last */ + + if (str == str_end) + return -1; + + scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend); + if (scan <= 0) + return 1; + wildstr+= scan; + + if (w_wc == (my_wc_t)escape) + { + scan= my_ucs2_uni(cs,&w_wc, (const uchar*)wildstr, (const uchar*)wildend); + if (scan <= 0) + return 1; + wildstr+= scan; + } + + do + { + /* Skip until the first character from wildstr is found */ + while (str != str_end) + { + scan= my_ucs2_uni(cs,&s_wc, (const uchar*)str, (const uchar*)str_end); + if (scan <= 0) + return 1; + str+= scan; + + if (weights) + { + plane=(s_wc>>8) & 0xFF; + s_wc = weights[plane] ? weights[plane][s_wc & 0xFF].sort : s_wc; + plane=(w_wc>>8) & 0xFF; + w_wc = weights[plane] ? weights[plane][w_wc & 0xFF].sort : w_wc; + } + + if (s_wc == w_wc) + break; + } + if (str == str_end) + return -1; + + result= my_wildcmp_ucs2(cs,str,str_end,wildstr,wildend,escape, + w_one,w_many,weights); + if (result <= 0) + return result; + + } while (str != str_end && w_wc != (my_wc_t)w_many); + return -1; + } + } + return (str != str_end ? 1 : 0); +} -static MY_COLLATION_HANDLER my_collation_ci_handler = +static +int my_wildcmp_ucs2_ci(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return my_wildcmp_ucs2(cs,str,str_end,wildstr,wildend, + escape,w_one,w_many,uni_plane); +} + +static +int my_wildcmp_ucs2_bin(CHARSET_INFO *cs, + const char *str,const char *str_end, + const char *wildstr,const char *wildend, + int escape, int w_one, int w_many) +{ + return my_wildcmp_ucs2(cs,str,str_end,wildstr,wildend, + escape,w_one,w_many,NULL); +} + + +static +int my_strnncoll_ucs2_bin(CHARSET_INFO *cs, + const uchar *s, uint slen, + const uchar *t, uint tlen) +{ + int s_res,t_res; + my_wc_t s_wc,t_wc; + const uchar *se=s+slen; + const uchar *te=t+tlen; + + while ( s < se && t < te ) + { + s_res=my_ucs2_uni(cs,&s_wc, s, se); + t_res=my_ucs2_uni(cs,&t_wc, t, te); + + if ( s_res <= 0 || t_res <= 0 ) + { + /* Incorrect string, compare by char value */ + return ((int)s[0]-(int)t[0]); + } + if ( s_wc != t_wc ) + { + return ((int) s_wc) - ((int) t_wc); + } + + s+=s_res; + t+=t_res; + } + return ( (se-s) - (te-t) ); +} + +static +int my_strcasecmp_ucs2_bin(CHARSET_INFO *cs, const char *s, const char *t) +{ + uint s_len=strlen(s); + uint t_len=strlen(t); + uint len = (s_len > t_len) ? s_len : t_len; + return my_strncasecmp_ucs2(cs, s, t, len); +} + +static +int my_strnxfrm_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), + uchar *dst, uint dstlen, + const uchar *src, uint srclen) +{ + if (dst != src) + memcpy(dst,src,srclen= min(dstlen,srclen)); + return srclen; +} + +static +void my_hash_sort_ucs2_bin(CHARSET_INFO *cs __attribute__((unused)), + const uchar *key, uint len,ulong *nr1, ulong *nr2) +{ + const uchar *pos = key; + + key+= len; + + for (; pos < (uchar*) key ; pos++) + { + nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) * + ((uint)*pos)) + (nr1[0] << 8); + nr2[0]+=3; + } +} + + +static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler = { my_strnncoll_ucs2, my_strnncoll_ucs2, my_strnxfrm_ucs2, my_like_range_simple, - my_wildcmp_mb, + my_wildcmp_ucs2_ci, my_strcasecmp_ucs2, my_instr_mb, my_hash_sort_ucs2 }; -static MY_CHARSET_HANDLER my_charset_handler= +static MY_COLLATION_HANDLER my_collation_ucs2_bin_handler = +{ + my_strnncoll_ucs2_bin, + my_strnncoll_ucs2_bin, + my_strnxfrm_ucs2_bin, + my_like_range_simple, + my_wildcmp_ucs2_bin, + my_strcasecmp_ucs2_bin, + my_instr_mb, + my_hash_sort_ucs2_bin +}; + +static MY_CHARSET_HANDLER my_charset_ucs2_handler= { my_ismbchar_ucs2, /* ismbchar */ my_mbcharlen_ucs2, /* mbcharlen */ @@ -1077,8 +1324,8 @@ CHARSET_INFO my_charset_ucs2_general_ci= 1, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, - &my_charset_handler, - &my_collation_ci_handler + &my_charset_ucs2_handler, + &my_collation_ucs2_general_ci_handler }; @@ -1100,8 +1347,8 @@ CHARSET_INFO my_charset_ucs2_bin= 1, /* strxfrm_multiply */ 2, /* mbmaxlen */ 0, - &my_charset_handler, - &my_collation_mb_bin_handler + &my_charset_ucs2_handler, + &my_collation_ucs2_bin_handler };