diff options
author | hf@bisonxp.(none) <> | 2002-07-09 10:42:24 +0500 |
---|---|---|
committer | hf@bisonxp.(none) <> | 2002-07-09 10:42:24 +0500 |
commit | d8c94e942b35a95611eeee8b9c18291d519f46a1 (patch) | |
tree | b21a32ca85bae8d5e16f2b05a4cee9a8c74df6e1 | |
parent | bc7e8b09159ba6cf2554c1e5a735167b3c3d373d (diff) | |
parent | 984c84c2347395e5364100a2039b588bab0136f3 (diff) | |
download | mariadb-git-d8c94e942b35a95611eeee8b9c18291d519f46a1.tar.gz |
Merge abotchkov@work.mysql.com:/home/bk/mysql-4.1
into bisonxp.(none):/home/hf/work/mysql-4.1
43 files changed, 2487 insertions, 435 deletions
diff --git a/.bzrignore b/.bzrignore index 4683dcd2fb7..3b9576a47f0 100644 --- a/.bzrignore +++ b/.bzrignore @@ -478,3 +478,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +tests/client_test diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 77fb78694c2..c299ad93cc3 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -14,6 +14,7 @@ davida@isil.mysql.com heikki@donna.mysql.fi heikki@hundin.mysql.fi hf@bison.(none) +hf@bisonxp.(none) jani@dsl-jkl1657.dial.inet.fi jani@hynda.(none) jani@hynda.mysql.fi @@ -66,7 +67,7 @@ tonu@x153.internalnet tonu@x3.internalnet venu@myvenu.com venu@work.mysql.com +walrus@mysql.com worm@altair.is.lan zak@balfor.local zak@linux.local -hf@bisonxp.(none) diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c index 629523ec69a..7afaabfe75b 100644 --- a/myisam/mi_unique.c +++ b/myisam/mi_unique.c @@ -99,11 +99,20 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record) end= pos+length; if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) { - uchar *sort_order=keyseg->charset->sort_order; - while (pos != end) - crc=((crc << 8) + - (((uchar) sort_order[*(uchar*) pos++]))) + - (crc >> (8*sizeof(ha_checksum)-8)); + if (keyseg->charset->hash_sort) + { + ulong nr=1, nr2=4; + keyseg->charset->hash_sort(keyseg->charset,(const uchar*)pos,length,&nr, &nr2); + crc=nr; + } + else + { + uchar *sort_order=keyseg->charset->sort_order; + while (pos != end) + crc=((crc << 8) + + (((uchar) sort_order[*(uchar*) pos++]))) + + (crc >> (8*sizeof(ha_checksum)-8)); + } } else while (pos != end) @@ -173,11 +182,19 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b, end= pos_a+length; if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT) { - uchar *sort_order=keyseg->charset->sort_order; - while (pos_a != end) - if (sort_order[*(uchar*) pos_a++] != - sort_order[*(uchar*) pos_b++]) + if (use_strcoll(keyseg->charset)) + { + if (my_strnncoll(keyseg->charset,pos_a,length,pos_b,length)) return 1; + } + else + { + uchar *sort_order=keyseg->charset->sort_order; + while (pos_a != end) + if (sort_order[*(uchar*) pos_a++] != + sort_order[*(uchar*) pos_b++]) + return 1; + } } else while (pos_a != end) diff --git a/mysql-test/create-test-result b/mysql-test/create-test-result index bfd64f32fc5..a50b4c87641 100755 --- a/mysql-test/create-test-result +++ b/mysql-test/create-test-result @@ -32,7 +32,7 @@ result_file=$RESULT_DIR/$test_name.result touch $result_file echo "Running the test case against empty file, will fail, but don't worry" -./mysql-test-run --do-test=$test_name +./mysql-test-run --local $test_name reject_file=$result_file.reject diff --git a/mysql-test/r/ctype_many.result b/mysql-test/r/ctype_many.result new file mode 100644 index 00000000000..b6c0f25853d --- /dev/null +++ b/mysql-test/r/ctype_many.result @@ -0,0 +1,1334 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( +comment CHAR(32) CHARACTER SET latin1 NOT NULL, +koi8_ru_f CHAR(32) CHARACTER SET koi8_ru NOT NULL +) CHARSET=latin5; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin1 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '' +) TYPE=MyISAM CHARSET=latin5 +ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '' +) TYPE=MyISAM CHARSET=latin5 +ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '', + `latin5_f` char(32) character set latin5 NOT NULL default '' +) TYPE=MyISAM CHARSET=latin5 +ALTER TABLE t1 CHARSET=latin2; +ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '', + `latin5_f` char(32) character set latin5 NOT NULL default '', + `latin2_f` char(32) character set latin2 NOT NULL default '' +) TYPE=MyISAM CHARSET=latin2 +ALTER TABLE t1 DROP latin2_f, DROP latin5_f; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `comment` char(32) character set latin2 NOT NULL default '', + `koi8_ru_f` char(32) character set koi8_ru NOT NULL default '' +) TYPE=MyISAM CHARSET=latin2 +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('d','LAT SMALL D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('f','LAT SMALL F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('h','LAT SMALL H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('j','LAT SMALL J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('l','LAT SMALL L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('n','LAT SMALL N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('p','LAT SMALL P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('r','LAT SMALL R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('t','LAT SMALL T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('v','LAT SMALL V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('x','LAT SMALL X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('z','LAT SMALL Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('B','LAT CAPIT B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('D','LAT CAPIT D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('F','LAT CAPIT F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('H','LAT CAPIT H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('J','LAT CAPIT J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('L','LAT CAPIT L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('N','LAT CAPIT N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('P','LAT CAPIT P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('R','LAT CAPIT R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('T','LAT CAPIT T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('V','LAT CAPIT V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('X','LAT CAPIT X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Z','LAT CAPIT Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Á','CYR SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Â','CYR SMALL BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('×','CYR SMALL VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ç','CYR SMALL GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ä','CYR SMALL DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Å','CYR SMALL IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('£','CYR SMALL IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ö','CYR SMALL ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ú','CYR SMALL ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('É','CYR SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ë','CYR SMALL KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ì','CYR SMALL EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Í','CYR SMALL EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Î','CYR SMALL EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ï','CYR SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ð','CYR SMALL PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ò','CYR SMALL ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ó','CYR SMALL ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ô','CYR SMALL TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Õ','CYR SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Æ','CYR SMALL EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('È','CYR SMALL HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ã','CYR SMALL TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Þ','CYR SMALL CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Û','CYR SMALL SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ý','CYR SMALL SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ß','CYR SMALL HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ù','CYR SMALL YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ø','CYR SMALL SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ü','CYR SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('À','CYR SMALL YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ñ','CYR SMALL YA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('á','CYR CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('â','CYR CAPIT BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('÷','CYR CAPIT VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ç','CYR CAPIT GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ä','CYR CAPIT DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('å','CYR CAPIT IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('³','CYR CAPIT IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ö','CYR CAPIT ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ú','CYR CAPIT ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('é','CYR CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ë','CYR CAPIT KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ì','CYR CAPIT EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('í','CYR CAPIT EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('î','CYR CAPIT EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ï','CYR CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ð','CYR CAPIT PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ò','CYR CAPIT ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ó','CYR CAPIT ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ô','CYR CAPIT TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('õ','CYR CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('æ','CYR CAPIT EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('è','CYR CAPIT HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ã','CYR CAPIT TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('þ','CYR CAPIT CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('û','CYR CAPIT SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ý','CYR CAPIT SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ÿ','CYR CAPIT HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ù','CYR CAPIT YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ø','CYR CAPIT SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ü','CYR CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('à','CYR CAPIT YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ñ','CYR CAPIT YA'); +ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL; +UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8); +SELECT * FROM t1; +comment koi8_ru_f utf8_f +LAT SMALL A a a +LAT SMALL B b b +LAT SMALL C c c +LAT SMALL D d d +LAT SMALL E e e +LAT SMALL F f f +LAT SMALL G g g +LAT SMALL H h h +LAT SMALL I i i +LAT SMALL J j j +LAT SMALL K k k +LAT SMALL L l l +LAT SMALL M m m +LAT SMALL N n n +LAT SMALL O o o +LAT SMALL P p p +LAT SMALL Q q q +LAT SMALL R r r +LAT SMALL S s s +LAT SMALL T t t +LAT SMALL U u u +LAT SMALL V v v +LAT SMALL W w w +LAT SMALL X x x +LAT SMALL Y y y +LAT SMALL Z z z +LAT CAPIT A A A +LAT CAPIT B B B +LAT CAPIT C C C +LAT CAPIT D D D +LAT CAPIT E E E +LAT CAPIT F F F +LAT CAPIT G G G +LAT CAPIT H H H +LAT CAPIT I I I +LAT CAPIT J J J +LAT CAPIT K K K +LAT CAPIT L L L +LAT CAPIT M M M +LAT CAPIT N N N +LAT CAPIT O O O +LAT CAPIT P P P +LAT CAPIT Q Q Q +LAT CAPIT R R R +LAT CAPIT S S S +LAT CAPIT T T T +LAT CAPIT U U U +LAT CAPIT V V V +LAT CAPIT W W W +LAT CAPIT X X X +LAT CAPIT Y Y Y +LAT CAPIT Z Z Z +CYR SMALL A Á а +CYR SMALL BE  б +CYR SMALL VE × Ð² +CYR SMALL GE Ç Ð³ +CYR SMALL DE Ä Ð´ +CYR SMALL IE Šе +CYR SMALL IO £ Ñ‘ +CYR SMALL ZHE Ö Ð¶ +CYR SMALL ZE Ú Ð· +CYR SMALL I É Ð¸ +CYR SMALL KA Ë Ðº +CYR SMALL EL Ì Ð» +CYR SMALL EM Í Ð¼ +CYR SMALL EN Πн +CYR SMALL O Ï Ð¾ +CYR SMALL PE Рп +CYR SMALL ER Ò Ñ€ +CYR SMALL ES Ó Ñ +CYR SMALL TE Ô Ñ‚ +CYR SMALL U Õ Ñƒ +CYR SMALL EF Æ Ñ„ +CYR SMALL HA È Ñ… +CYR SMALL TSE à ц +CYR SMALL CHE Þ Ñ‡ +CYR SMALL SHA Û Ñˆ +CYR SMALL SCHA Ý Ñ‰ +CYR SMALL HARD SIGN ß ÑŠ +CYR SMALL YERU Ù Ñ‹ +CYR SMALL SOFT SIGN Ø ÑŒ +CYR SMALL E Ü Ñ +CYR SMALL YU À ÑŽ +CYR SMALL YA Ñ Ñ +CYR CAPIT A á Ð +CYR CAPIT BE â Б +CYR CAPIT VE ÷ Ð’ +CYR CAPIT GE ç Г +CYR CAPIT DE ä Д +CYR CAPIT IE å Е +CYR CAPIT IO ³ Ð +CYR CAPIT ZHE ö Ж +CYR CAPIT ZE ú З +CYR CAPIT I é И +CYR CAPIT KA ë К +CYR CAPIT EL ì Л +CYR CAPIT EM í Ðœ +CYR CAPIT EN î Ð +CYR CAPIT O ï О +CYR CAPIT PE ð П +CYR CAPIT ER ò Ð +CYR CAPIT ES ó С +CYR CAPIT TE ô Т +CYR CAPIT U õ У +CYR CAPIT EF æ Ф +CYR CAPIT HA è Ð¥ +CYR CAPIT TSE ã Ц +CYR CAPIT CHE þ Ч +CYR CAPIT SHA û Ш +CYR CAPIT SCHA ý Щ +CYR CAPIT HARD SIGN ÿ Ъ +CYR CAPIT YERU ù Ы +CYR CAPIT SOFT SIGN ø Ь +CYR CAPIT E ü Ð +CYR CAPIT YU à Ю +CYR CAPIT YA ñ Я +SELECT koi8_ru_f,MIN(comment) FROM t1 GROUP BY 1; +koi8_ru_f MIN(comment) +a LAT CAPIT A +b LAT CAPIT B +c LAT CAPIT C +d LAT CAPIT D +e LAT CAPIT E +f LAT CAPIT F +g LAT CAPIT G +h LAT CAPIT H +i LAT CAPIT I +j LAT CAPIT J +k LAT CAPIT K +l LAT CAPIT L +m LAT CAPIT M +n LAT CAPIT N +o LAT CAPIT O +p LAT CAPIT P +q LAT CAPIT Q +r LAT CAPIT R +s LAT CAPIT S +t LAT CAPIT T +u LAT CAPIT U +v LAT CAPIT V +w LAT CAPIT W +x LAT CAPIT X +y LAT CAPIT Y +z LAT CAPIT Z +Á CYR CAPIT A + CYR CAPIT BE +× CYR CAPIT VE +Ç CYR CAPIT GE +Ä CYR CAPIT DE +Å CYR CAPIT IE +£ CYR CAPIT IO +Ö CYR CAPIT ZHE +Ú CYR CAPIT ZE +É CYR CAPIT I +Ë CYR CAPIT KA +Ì CYR CAPIT EL +Í CYR CAPIT EM +Î CYR CAPIT EN +Ï CYR CAPIT O +Ð CYR CAPIT PE +Ò CYR CAPIT ER +Ó CYR CAPIT ES +Ô CYR CAPIT TE +Õ CYR CAPIT U +Æ CYR CAPIT EF +È CYR CAPIT HA +à CYR CAPIT TSE +Þ CYR CAPIT CHE +Û CYR CAPIT SHA +Ý CYR CAPIT SCHA +ß CYR CAPIT HARD SIGN +Ù CYR CAPIT YERU +Ø CYR CAPIT SOFT SIGN +Ü CYR CAPIT E +À CYR CAPIT YU +Ñ CYR CAPIT YA +SELECT utf8_f,MIN(comment) FROM t1 GROUP BY 1; +utf8_f MIN(comment) +a LAT CAPIT A +b LAT CAPIT B +c LAT CAPIT C +d LAT CAPIT D +e LAT CAPIT E +f LAT CAPIT F +g LAT CAPIT G +h LAT CAPIT H +i LAT CAPIT I +j LAT CAPIT J +k LAT CAPIT K +l LAT CAPIT L +m LAT CAPIT M +n LAT CAPIT N +o LAT CAPIT O +p LAT CAPIT P +q LAT CAPIT Q +r LAT CAPIT R +s LAT CAPIT S +t LAT CAPIT T +u LAT CAPIT U +v LAT CAPIT V +w LAT CAPIT W +x LAT CAPIT X +y LAT CAPIT Y +z LAT CAPIT Z +а CYR CAPIT A +б CYR CAPIT BE +в CYR CAPIT VE +г CYR CAPIT GE +д CYR CAPIT DE +е CYR CAPIT IE +ж CYR CAPIT ZHE +з CYR CAPIT ZE +и CYR CAPIT I +к CYR CAPIT KA +л CYR CAPIT EL +м CYR CAPIT EM +н CYR CAPIT EN +о CYR CAPIT O +п CYR CAPIT PE +Ñ€ CYR CAPIT ER +Ñ CYR CAPIT ES +Ñ‚ CYR CAPIT TE +у CYR CAPIT U +Ñ„ CYR CAPIT EF +Ñ… CYR CAPIT HA +ц CYR CAPIT TSE +ч CYR CAPIT CHE +ш CYR CAPIT SHA +щ CYR CAPIT SCHA +ÑŠ CYR CAPIT HARD SIGN +Ñ‹ CYR CAPIT YERU +ÑŒ CYR CAPIT SOFT SIGN +Ñ CYR CAPIT E +ÑŽ CYR CAPIT YU +Ñ CYR CAPIT YA +SELECT DISTINCT koi8_ru_f FROM t1; +koi8_ru_f +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +Á + +× +Ç +Ä +Å +£ +Ö +Ú +É +Ë +Ì +Í +Î +Ï +Ð +Ò +Ó +Ô +Õ +Æ +È +à +Þ +Û +Ý +ß +Ù +Ø +Ü +À +Ñ +SELECT DISTINCT utf8_f FROM t1; +utf8_f +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +а +б +в +г +д +е +ж +з +и +к +л +м +н +о +п +Ñ€ +Ñ +Ñ‚ +у +Ñ„ +Ñ… +ц +ч +ш +щ +ÑŠ +Ñ‹ +ÑŒ +Ñ +ÑŽ +Ñ +SELECT lower(koi8_ru_f) FROM t1 ORDER BY 1 DESC; +lower(koi8_ru_f) +Ñ +Ñ +À +À +Ü +Ü +Ø +Ø +Ù +Ù +ß +ß +Ý +Ý +Û +Û +Þ +Þ +à +à +È +È +Æ +Æ +Õ +Õ +Ô +Ô +Ó +Ó +Ò +Ò +Ð +Ð +Ï +Ï +Î +Î +Í +Í +Ì +Ì +Ë +Ë +É +É +Ú +Ú +Ö +Ö +£ +£ +Å +Å +Ä +Ä +Ç +Ç +× +× + + +Á +Á +z +z +y +y +x +x +w +w +v +v +u +u +t +t +s +s +r +r +q +q +p +p +o +o +n +n +m +m +l +l +k +k +j +j +i +i +h +h +g +g +f +f +e +e +d +d +c +c +b +b +a +a +SELECT lower(utf8_f) FROM t1 ORDER BY 1 DESC; +lower(utf8_f) +Ñ +Ñ +ÑŽ +ÑŽ +Ñ +Ñ +ÑŒ +ÑŒ +Ñ‹ +Ñ‹ +ÑŠ +ÑŠ +щ +щ +ш +ш +ч +ч +ц +ц +Ñ… +Ñ… +Ñ„ +Ñ„ +у +у +Ñ‚ +Ñ‚ +Ñ +Ñ +Ñ€ +Ñ€ +п +п +о +о +н +н +м +м +л +л +к +к +и +и +з +з +ж +ж +е +Ñ‘ +е +Ñ‘ +д +д +г +г +в +в +б +б +а +а +z +z +y +y +x +x +w +w +v +v +u +u +t +t +s +s +r +r +q +q +p +p +o +o +n +n +m +m +l +l +k +k +j +j +i +i +h +h +g +g +f +f +e +e +d +d +c +c +b +b +a +a +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 WHERE CONVERT(t11.koi8_ru_f USING utf8)=t12.utf8_f +ORDER BY t11.koi8_ru_f; +comment comment +LAT SMALL A LAT SMALL A +LAT SMALL A LAT CAPIT A +LAT CAPIT A LAT SMALL A +LAT CAPIT A LAT CAPIT A +LAT SMALL B LAT CAPIT B +LAT CAPIT B LAT SMALL B +LAT CAPIT B LAT CAPIT B +LAT SMALL B LAT SMALL B +LAT CAPIT C LAT SMALL C +LAT CAPIT C LAT CAPIT C +LAT SMALL C LAT SMALL C +LAT SMALL C LAT CAPIT C +LAT CAPIT D LAT CAPIT D +LAT SMALL D LAT SMALL D +LAT SMALL D LAT CAPIT D +LAT CAPIT D LAT SMALL D +LAT SMALL E LAT SMALL E +LAT SMALL E LAT CAPIT E +LAT CAPIT E LAT SMALL E +LAT CAPIT E LAT CAPIT E +LAT SMALL F LAT SMALL F +LAT SMALL F LAT CAPIT F +LAT CAPIT F LAT SMALL F +LAT CAPIT F LAT CAPIT F +LAT SMALL G LAT CAPIT G +LAT CAPIT G LAT SMALL G +LAT CAPIT G LAT CAPIT G +LAT SMALL G LAT SMALL G +LAT CAPIT H LAT CAPIT H +LAT SMALL H LAT SMALL H +LAT SMALL H LAT CAPIT H +LAT CAPIT H LAT SMALL H +LAT CAPIT I LAT CAPIT I +LAT SMALL I LAT SMALL I +LAT SMALL I LAT CAPIT I +LAT CAPIT I LAT SMALL I +LAT SMALL J LAT SMALL J +LAT SMALL J LAT CAPIT J +LAT CAPIT J LAT SMALL J +LAT CAPIT J LAT CAPIT J +LAT SMALL K LAT CAPIT K +LAT CAPIT K LAT SMALL K +LAT CAPIT K LAT CAPIT K +LAT SMALL K LAT SMALL K +LAT SMALL L LAT CAPIT L +LAT CAPIT L LAT SMALL L +LAT CAPIT L LAT CAPIT L +LAT SMALL L LAT SMALL L +LAT CAPIT M LAT CAPIT M +LAT SMALL M LAT SMALL M +LAT SMALL M LAT CAPIT M +LAT CAPIT M LAT SMALL M +LAT SMALL N LAT SMALL N +LAT SMALL N LAT CAPIT N +LAT CAPIT N LAT SMALL N +LAT CAPIT N LAT CAPIT N +LAT SMALL O LAT SMALL O +LAT SMALL O LAT CAPIT O +LAT CAPIT O LAT SMALL O +LAT CAPIT O LAT CAPIT O +LAT SMALL P LAT CAPIT P +LAT CAPIT P LAT SMALL P +LAT CAPIT P LAT CAPIT P +LAT SMALL P LAT SMALL P +LAT CAPIT Q LAT SMALL Q +LAT CAPIT Q LAT CAPIT Q +LAT SMALL Q LAT SMALL Q +LAT SMALL Q LAT CAPIT Q +LAT CAPIT R LAT CAPIT R +LAT SMALL R LAT SMALL R +LAT SMALL R LAT CAPIT R +LAT CAPIT R LAT SMALL R +LAT SMALL S LAT SMALL S +LAT SMALL S LAT CAPIT S +LAT CAPIT S LAT SMALL S +LAT CAPIT S LAT CAPIT S +LAT SMALL T LAT CAPIT T +LAT CAPIT T LAT SMALL T +LAT CAPIT T LAT CAPIT T +LAT SMALL T LAT SMALL T +LAT SMALL U LAT CAPIT U +LAT CAPIT U LAT SMALL U +LAT CAPIT U LAT CAPIT U +LAT SMALL U LAT SMALL U +LAT CAPIT V LAT CAPIT V +LAT SMALL V LAT SMALL V +LAT SMALL V LAT CAPIT V +LAT CAPIT V LAT SMALL V +LAT CAPIT W LAT CAPIT W +LAT SMALL W LAT SMALL W +LAT SMALL W LAT CAPIT W +LAT CAPIT W LAT SMALL W +LAT SMALL X LAT SMALL X +LAT SMALL X LAT CAPIT X +LAT CAPIT X LAT SMALL X +LAT CAPIT X LAT CAPIT X +LAT SMALL Y LAT CAPIT Y +LAT CAPIT Y LAT SMALL Y +LAT CAPIT Y LAT CAPIT Y +LAT SMALL Y LAT SMALL Y +LAT CAPIT Z LAT SMALL Z +LAT CAPIT Z LAT CAPIT Z +LAT SMALL Z LAT SMALL Z +LAT SMALL Z LAT CAPIT Z +CYR CAPIT A CYR SMALL A +CYR SMALL A CYR CAPIT A +CYR CAPIT A CYR CAPIT A +CYR SMALL A CYR SMALL A +CYR SMALL BE CYR CAPIT BE +CYR CAPIT BE CYR CAPIT BE +CYR SMALL BE CYR SMALL BE +CYR CAPIT BE CYR SMALL BE +CYR CAPIT VE CYR CAPIT VE +CYR SMALL VE CYR SMALL VE +CYR CAPIT VE CYR SMALL VE +CYR SMALL VE CYR CAPIT VE +CYR CAPIT GE CYR CAPIT GE +CYR SMALL GE CYR SMALL GE +CYR CAPIT GE CYR SMALL GE +CYR SMALL GE CYR CAPIT GE +CYR CAPIT DE CYR SMALL DE +CYR SMALL DE CYR CAPIT DE +CYR CAPIT DE CYR CAPIT DE +CYR SMALL DE CYR SMALL DE +CYR SMALL IE CYR SMALL IO +CYR SMALL IE CYR CAPIT IE +CYR CAPIT IE CYR SMALL IE +CYR CAPIT IE CYR CAPIT IO +CYR SMALL IE CYR SMALL IE +CYR SMALL IE CYR CAPIT IO +CYR CAPIT IE CYR SMALL IO +CYR CAPIT IE CYR CAPIT IE +CYR SMALL IO CYR SMALL IE +CYR SMALL IO CYR CAPIT IO +CYR CAPIT IO CYR SMALL IO +CYR CAPIT IO CYR CAPIT IE +CYR SMALL IO CYR SMALL IO +CYR SMALL IO CYR CAPIT IE +CYR CAPIT IO CYR SMALL IE +CYR CAPIT IO CYR CAPIT IO +CYR CAPIT ZHE CYR SMALL ZHE +CYR SMALL ZHE CYR CAPIT ZHE +CYR CAPIT ZHE CYR CAPIT ZHE +CYR SMALL ZHE CYR SMALL ZHE +CYR SMALL ZE CYR CAPIT ZE +CYR CAPIT ZE CYR CAPIT ZE +CYR SMALL ZE CYR SMALL ZE +CYR CAPIT ZE CYR SMALL ZE +CYR CAPIT I CYR CAPIT I +CYR SMALL I CYR SMALL I +CYR CAPIT I CYR SMALL I +CYR SMALL I CYR CAPIT I +CYR CAPIT KA CYR CAPIT KA +CYR SMALL KA CYR SMALL KA +CYR CAPIT KA CYR SMALL KA +CYR SMALL KA CYR CAPIT KA +CYR CAPIT EL CYR SMALL EL +CYR SMALL EL CYR CAPIT EL +CYR CAPIT EL CYR CAPIT EL +CYR SMALL EL CYR SMALL EL +CYR CAPIT EM CYR SMALL EM +CYR SMALL EM CYR CAPIT EM +CYR CAPIT EM CYR CAPIT EM +CYR SMALL EM CYR SMALL EM +CYR SMALL EN CYR CAPIT EN +CYR CAPIT EN CYR CAPIT EN +CYR SMALL EN CYR SMALL EN +CYR CAPIT EN CYR SMALL EN +CYR CAPIT O CYR CAPIT O +CYR SMALL O CYR SMALL O +CYR CAPIT O CYR SMALL O +CYR SMALL O CYR CAPIT O +CYR SMALL PE CYR SMALL PE +CYR CAPIT PE CYR SMALL PE +CYR SMALL PE CYR CAPIT PE +CYR CAPIT PE CYR CAPIT PE +CYR CAPIT ER CYR SMALL ER +CYR SMALL ER CYR CAPIT ER +CYR CAPIT ER CYR CAPIT ER +CYR SMALL ER CYR SMALL ER +CYR SMALL ES CYR CAPIT ES +CYR CAPIT ES CYR CAPIT ES +CYR SMALL ES CYR SMALL ES +CYR CAPIT ES CYR SMALL ES +CYR CAPIT TE CYR CAPIT TE +CYR SMALL TE CYR SMALL TE +CYR CAPIT TE CYR SMALL TE +CYR SMALL TE CYR CAPIT TE +CYR CAPIT U CYR CAPIT U +CYR SMALL U CYR SMALL U +CYR CAPIT U CYR SMALL U +CYR SMALL U CYR CAPIT U +CYR CAPIT EF CYR SMALL EF +CYR SMALL EF CYR CAPIT EF +CYR CAPIT EF CYR CAPIT EF +CYR SMALL EF CYR SMALL EF +CYR CAPIT HA CYR SMALL HA +CYR SMALL HA CYR CAPIT HA +CYR CAPIT HA CYR CAPIT HA +CYR SMALL HA CYR SMALL HA +CYR SMALL TSE CYR CAPIT TSE +CYR CAPIT TSE CYR CAPIT TSE +CYR SMALL TSE CYR SMALL TSE +CYR CAPIT TSE CYR SMALL TSE +CYR CAPIT CHE CYR CAPIT CHE +CYR SMALL CHE CYR SMALL CHE +CYR CAPIT CHE CYR SMALL CHE +CYR SMALL CHE CYR CAPIT CHE +CYR CAPIT SHA CYR CAPIT SHA +CYR SMALL SHA CYR SMALL SHA +CYR CAPIT SHA CYR SMALL SHA +CYR SMALL SHA CYR CAPIT SHA +CYR CAPIT SCHA CYR SMALL SCHA +CYR SMALL SCHA CYR CAPIT SCHA +CYR CAPIT SCHA CYR CAPIT SCHA +CYR SMALL SCHA CYR SMALL SCHA +CYR CAPIT HARD SIGN CYR SMALL HARD SIGN +CYR SMALL HARD SIGN CYR CAPIT HARD SIGN +CYR CAPIT HARD SIGN CYR CAPIT HARD SIGN +CYR SMALL HARD SIGN CYR SMALL HARD SIGN +CYR CAPIT YERU CYR CAPIT YERU +CYR SMALL YERU CYR SMALL YERU +CYR CAPIT YERU CYR SMALL YERU +CYR SMALL YERU CYR CAPIT YERU +CYR CAPIT SOFT SIGN CYR CAPIT SOFT SIGN +CYR SMALL SOFT SIGN CYR SMALL SOFT SIGN +CYR CAPIT SOFT SIGN CYR SMALL SOFT SIGN +CYR SMALL SOFT SIGN CYR CAPIT SOFT SIGN +CYR CAPIT E CYR SMALL E +CYR SMALL E CYR CAPIT E +CYR CAPIT E CYR CAPIT E +CYR SMALL E CYR SMALL E +CYR CAPIT YU CYR SMALL YU +CYR SMALL YU CYR CAPIT YU +CYR CAPIT YU CYR CAPIT YU +CYR SMALL YU CYR SMALL YU +CYR SMALL YA CYR CAPIT YA +CYR CAPIT YA CYR CAPIT YA +CYR SMALL YA CYR SMALL YA +CYR CAPIT YA CYR SMALL YA +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 +WHERE t11.koi8_ru_f=CONVERT(t12.utf8_f USING koi8_ru) +ORDER BY t12.utf8_f; +comment comment +LAT SMALL A LAT SMALL A +LAT SMALL A LAT CAPIT A +LAT CAPIT A LAT SMALL A +LAT CAPIT A LAT CAPIT A +LAT SMALL B LAT CAPIT B +LAT CAPIT B LAT SMALL B +LAT CAPIT B LAT CAPIT B +LAT SMALL B LAT SMALL B +LAT CAPIT C LAT SMALL C +LAT CAPIT C LAT CAPIT C +LAT SMALL C LAT SMALL C +LAT SMALL C LAT CAPIT C +LAT CAPIT D LAT CAPIT D +LAT SMALL D LAT SMALL D +LAT SMALL D LAT CAPIT D +LAT CAPIT D LAT SMALL D +LAT SMALL E LAT SMALL E +LAT SMALL E LAT CAPIT E +LAT CAPIT E LAT SMALL E +LAT CAPIT E LAT CAPIT E +LAT SMALL F LAT SMALL F +LAT SMALL F LAT CAPIT F +LAT CAPIT F LAT SMALL F +LAT CAPIT F LAT CAPIT F +LAT SMALL G LAT CAPIT G +LAT CAPIT G LAT SMALL G +LAT CAPIT G LAT CAPIT G +LAT SMALL G LAT SMALL G +LAT CAPIT H LAT CAPIT H +LAT SMALL H LAT SMALL H +LAT SMALL H LAT CAPIT H +LAT CAPIT H LAT SMALL H +LAT CAPIT I LAT CAPIT I +LAT SMALL I LAT SMALL I +LAT SMALL I LAT CAPIT I +LAT CAPIT I LAT SMALL I +LAT SMALL J LAT SMALL J +LAT SMALL J LAT CAPIT J +LAT CAPIT J LAT SMALL J +LAT CAPIT J LAT CAPIT J +LAT SMALL K LAT CAPIT K +LAT CAPIT K LAT SMALL K +LAT CAPIT K LAT CAPIT K +LAT SMALL K LAT SMALL K +LAT SMALL L LAT CAPIT L +LAT CAPIT L LAT SMALL L +LAT CAPIT L LAT CAPIT L +LAT SMALL L LAT SMALL L +LAT CAPIT M LAT CAPIT M +LAT SMALL M LAT SMALL M +LAT SMALL M LAT CAPIT M +LAT CAPIT M LAT SMALL M +LAT SMALL N LAT SMALL N +LAT SMALL N LAT CAPIT N +LAT CAPIT N LAT SMALL N +LAT CAPIT N LAT CAPIT N +LAT SMALL O LAT SMALL O +LAT SMALL O LAT CAPIT O +LAT CAPIT O LAT SMALL O +LAT CAPIT O LAT CAPIT O +LAT SMALL P LAT CAPIT P +LAT CAPIT P LAT SMALL P +LAT CAPIT P LAT CAPIT P +LAT SMALL P LAT SMALL P +LAT CAPIT Q LAT SMALL Q +LAT CAPIT Q LAT CAPIT Q +LAT SMALL Q LAT SMALL Q +LAT SMALL Q LAT CAPIT Q +LAT CAPIT R LAT CAPIT R +LAT SMALL R LAT SMALL R +LAT SMALL R LAT CAPIT R +LAT CAPIT R LAT SMALL R +LAT SMALL S LAT SMALL S +LAT SMALL S LAT CAPIT S +LAT CAPIT S LAT SMALL S +LAT CAPIT S LAT CAPIT S +LAT SMALL T LAT CAPIT T +LAT CAPIT T LAT SMALL T +LAT CAPIT T LAT CAPIT T +LAT SMALL T LAT SMALL T +LAT SMALL U LAT CAPIT U +LAT CAPIT U LAT SMALL U +LAT CAPIT U LAT CAPIT U +LAT SMALL U LAT SMALL U +LAT CAPIT V LAT CAPIT V +LAT SMALL V LAT SMALL V +LAT SMALL V LAT CAPIT V +LAT CAPIT V LAT SMALL V +LAT CAPIT W LAT CAPIT W +LAT SMALL W LAT SMALL W +LAT SMALL W LAT CAPIT W +LAT CAPIT W LAT SMALL W +LAT SMALL X LAT SMALL X +LAT SMALL X LAT CAPIT X +LAT CAPIT X LAT SMALL X +LAT CAPIT X LAT CAPIT X +LAT SMALL Y LAT CAPIT Y +LAT CAPIT Y LAT SMALL Y +LAT CAPIT Y LAT CAPIT Y +LAT SMALL Y LAT SMALL Y +LAT CAPIT Z LAT SMALL Z +LAT CAPIT Z LAT CAPIT Z +LAT SMALL Z LAT SMALL Z +LAT SMALL Z LAT CAPIT Z +CYR CAPIT A CYR SMALL A +CYR CAPIT A CYR CAPIT A +CYR SMALL A CYR SMALL A +CYR SMALL A CYR CAPIT A +CYR SMALL BE CYR SMALL BE +CYR SMALL BE CYR CAPIT BE +CYR CAPIT BE CYR SMALL BE +CYR CAPIT BE CYR CAPIT BE +CYR SMALL VE CYR SMALL VE +CYR SMALL VE CYR CAPIT VE +CYR CAPIT VE CYR SMALL VE +CYR CAPIT VE CYR CAPIT VE +CYR SMALL GE CYR SMALL GE +CYR SMALL GE CYR CAPIT GE +CYR CAPIT GE CYR SMALL GE +CYR CAPIT GE CYR CAPIT GE +CYR CAPIT DE CYR SMALL DE +CYR CAPIT DE CYR CAPIT DE +CYR SMALL DE CYR SMALL DE +CYR SMALL DE CYR CAPIT DE +CYR CAPIT IE CYR SMALL IE +CYR CAPIT IE CYR CAPIT IE +CYR SMALL IO CYR SMALL IO +CYR SMALL IO CYR CAPIT IO +CYR SMALL IE CYR SMALL IE +CYR SMALL IE CYR CAPIT IE +CYR CAPIT IO CYR SMALL IO +CYR CAPIT IO CYR CAPIT IO +CYR SMALL ZHE CYR SMALL ZHE +CYR SMALL ZHE CYR CAPIT ZHE +CYR CAPIT ZHE CYR SMALL ZHE +CYR CAPIT ZHE CYR CAPIT ZHE +CYR CAPIT ZE CYR SMALL ZE +CYR CAPIT ZE CYR CAPIT ZE +CYR SMALL ZE CYR SMALL ZE +CYR SMALL ZE CYR CAPIT ZE +CYR CAPIT I CYR SMALL I +CYR CAPIT I CYR CAPIT I +CYR SMALL I CYR SMALL I +CYR SMALL I CYR CAPIT I +CYR SMALL KA CYR SMALL KA +CYR SMALL KA CYR CAPIT KA +CYR CAPIT KA CYR SMALL KA +CYR CAPIT KA CYR CAPIT KA +CYR SMALL EL CYR SMALL EL +CYR SMALL EL CYR CAPIT EL +CYR CAPIT EL CYR SMALL EL +CYR CAPIT EL CYR CAPIT EL +CYR SMALL EM CYR SMALL EM +CYR SMALL EM CYR CAPIT EM +CYR CAPIT EM CYR SMALL EM +CYR CAPIT EM CYR CAPIT EM +CYR CAPIT EN CYR SMALL EN +CYR CAPIT EN CYR CAPIT EN +CYR SMALL EN CYR SMALL EN +CYR SMALL EN CYR CAPIT EN +CYR CAPIT O CYR SMALL O +CYR CAPIT O CYR CAPIT O +CYR SMALL O CYR SMALL O +CYR SMALL O CYR CAPIT O +CYR SMALL PE CYR SMALL PE +CYR SMALL PE CYR CAPIT PE +CYR CAPIT PE CYR SMALL PE +CYR CAPIT PE CYR CAPIT PE +CYR SMALL ER CYR SMALL ER +CYR SMALL ER CYR CAPIT ER +CYR CAPIT ER CYR SMALL ER +CYR CAPIT ER CYR CAPIT ER +CYR SMALL ES CYR SMALL ES +CYR SMALL ES CYR CAPIT ES +CYR CAPIT ES CYR SMALL ES +CYR CAPIT ES CYR CAPIT ES +CYR CAPIT TE CYR SMALL TE +CYR CAPIT TE CYR CAPIT TE +CYR SMALL TE CYR SMALL TE +CYR SMALL TE CYR CAPIT TE +CYR SMALL U CYR SMALL U +CYR SMALL U CYR CAPIT U +CYR CAPIT U CYR SMALL U +CYR CAPIT U CYR CAPIT U +CYR SMALL EF CYR SMALL EF +CYR SMALL EF CYR CAPIT EF +CYR CAPIT EF CYR SMALL EF +CYR CAPIT EF CYR CAPIT EF +CYR SMALL HA CYR SMALL HA +CYR SMALL HA CYR CAPIT HA +CYR CAPIT HA CYR SMALL HA +CYR CAPIT HA CYR CAPIT HA +CYR CAPIT TSE CYR SMALL TSE +CYR CAPIT TSE CYR CAPIT TSE +CYR SMALL TSE CYR SMALL TSE +CYR SMALL TSE CYR CAPIT TSE +CYR CAPIT CHE CYR SMALL CHE +CYR CAPIT CHE CYR CAPIT CHE +CYR SMALL CHE CYR SMALL CHE +CYR SMALL CHE CYR CAPIT CHE +CYR SMALL SHA CYR SMALL SHA +CYR SMALL SHA CYR CAPIT SHA +CYR CAPIT SHA CYR SMALL SHA +CYR CAPIT SHA CYR CAPIT SHA +CYR SMALL SCHA CYR SMALL SCHA +CYR SMALL SCHA CYR CAPIT SCHA +CYR CAPIT SCHA CYR SMALL SCHA +CYR CAPIT SCHA CYR CAPIT SCHA +CYR SMALL HARD SIGN CYR SMALL HARD SIGN +CYR SMALL HARD SIGN CYR CAPIT HARD SIGN +CYR CAPIT HARD SIGN CYR SMALL HARD SIGN +CYR CAPIT HARD SIGN CYR CAPIT HARD SIGN +CYR CAPIT YERU CYR SMALL YERU +CYR CAPIT YERU CYR CAPIT YERU +CYR SMALL YERU CYR SMALL YERU +CYR SMALL YERU CYR CAPIT YERU +CYR CAPIT SOFT SIGN CYR SMALL SOFT SIGN +CYR CAPIT SOFT SIGN CYR CAPIT SOFT SIGN +CYR SMALL SOFT SIGN CYR SMALL SOFT SIGN +CYR SMALL SOFT SIGN CYR CAPIT SOFT SIGN +CYR SMALL E CYR SMALL E +CYR SMALL E CYR CAPIT E +CYR CAPIT E CYR SMALL E +CYR CAPIT E CYR CAPIT E +CYR SMALL YU CYR SMALL YU +CYR SMALL YU CYR CAPIT YU +CYR CAPIT YU CYR SMALL YU +CYR CAPIT YU CYR CAPIT YU +CYR CAPIT YA CYR SMALL YA +CYR CAPIT YA CYR CAPIT YA +CYR SMALL YA CYR SMALL YA +CYR SMALL YA CYR CAPIT YA +ALTER TABLE t1 ADD ucs2_f CHAR(32) CHARACTER SET ucs2 NOT NULL; +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0391,'GREEK CAPIT ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0392,'GREEK CAPIT BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0393,'GREEK CAPIT GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0394,'GREEK CAPIT DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0395,'GREEK CAPIT EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B1,'GREEK SMALL ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B2,'GREEK SMALL BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B3,'GREEK SMALL GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B4,'GREEK SMALL DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B5,'GREEK SMALL EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0531,'ARMENIAN CAPIT AYB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0532,'ARMENIAN CAPIT BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0533,'ARMENIAN CAPIT GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0534,'ARMENIAN CAPIT DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0535,'ARMENIAN CAPIT ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0536,'ARMENIAN CAPIT ZA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0561,'ARMENIAN SMALL YAB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0562,'ARMENIAN SMALL BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0563,'ARMENIAN SMALL GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0564,'ARMENIAN SMALL DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0565,'ARMENIAN SMALL ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0566,'ARMENIAN SMALL ZA'); +ALTER TABLE t1 ADD armscii8_f CHAR(32) CHARACTER SET armscii8 NOT NULL; +ALTER TABLE t1 ADD greek_f CHAR(32) CHARACTER SET greek NOT NULL; +UPDATE t1 SET greek_f=CONVERT(ucs2_f USING greek) WHERE comment LIKE 'GRE%'; +UPDATE t1 SET armscii8_f=CONVERT(ucs2_f USING armscii8) WHERE comment LIKE 'ARM%'; +UPDATE t1 SET utf8_f=CONVERT(ucs2_f USING utf8) WHERE utf8_f=''; +UPDATE t1 SET ucs2_f=CONVERT(utf8_f USING ucs2) WHERE ucs2_f=''; +SELECT min(comment),count(*) FROM t1 GROUP BY ucs2_f; +min(comment) count(*) +LAT CAPIT A 2 +LAT CAPIT B 2 +LAT CAPIT C 2 +LAT CAPIT D 2 +LAT CAPIT E 2 +LAT CAPIT F 2 +LAT CAPIT G 2 +LAT CAPIT H 2 +LAT CAPIT I 2 +LAT CAPIT J 2 +LAT CAPIT K 2 +LAT CAPIT L 2 +LAT CAPIT M 2 +LAT CAPIT N 2 +LAT CAPIT O 2 +LAT CAPIT P 2 +LAT CAPIT Q 2 +LAT CAPIT R 2 +LAT CAPIT S 2 +LAT CAPIT T 2 +LAT CAPIT U 2 +LAT CAPIT V 2 +LAT CAPIT W 2 +LAT CAPIT X 2 +LAT CAPIT Y 2 +LAT CAPIT Z 2 +GREEK CAPIT ALPHA 2 +GREEK CAPIT BETA 2 +GREEK CAPIT GAMMA 2 +GREEK CAPIT DELTA 2 +GREEK CAPIT EPSILON 2 +CYR CAPIT A 2 +CYR CAPIT BE 2 +CYR CAPIT VE 2 +CYR CAPIT GE 2 +CYR CAPIT DE 2 +CYR CAPIT IE 4 +CYR CAPIT ZHE 2 +CYR CAPIT ZE 2 +CYR CAPIT I 2 +CYR CAPIT KA 2 +CYR CAPIT EL 2 +CYR CAPIT EM 2 +CYR CAPIT EN 2 +CYR CAPIT O 2 +CYR CAPIT PE 2 +CYR CAPIT ER 2 +CYR CAPIT ES 2 +CYR CAPIT TE 2 +CYR CAPIT U 2 +CYR CAPIT EF 2 +CYR CAPIT HA 2 +CYR CAPIT TSE 2 +CYR CAPIT CHE 2 +CYR CAPIT SHA 2 +CYR CAPIT SCHA 2 +CYR CAPIT HARD SIGN 2 +CYR CAPIT YERU 2 +CYR CAPIT SOFT SIGN 2 +CYR CAPIT E 2 +CYR CAPIT YU 2 +CYR CAPIT YA 2 +ARMENIAN CAPIT AYB 2 +ARMENIAN CAPIT BEN 2 +ARMENIAN CAPIT GIM 2 +ARMENIAN CAPIT DA 2 +ARMENIAN CAPIT ECH 2 +ARMENIAN CAPIT ZA 2 +DROP TABLE t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 2e40d0a92d8..bd92c496f29 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -65,6 +65,21 @@ a select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) 8 7.5000 -8 6.0000 -9 5.5000 +8 4.5000 +9 7.5000 +select * from t3 where exists (select * from t2 where t2.b=t3.a); +a +7 +select * from t3 where not exists (select * from t2 where t2.b=t3.a); +a +6 +3 +insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); +select b,max(a) as ma from t4 group by b having b < (select max(t2.a) +from t2 where t2.b=t4.b); +b ma +select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) +from t2 where t2.b=t4.b); +b ma +7 12 drop table t1,t2,t3,t4; diff --git a/mysql-test/t/ctype_many.test b/mysql-test/t/ctype_many.test new file mode 100644 index 00000000000..7db8f49919b --- /dev/null +++ b/mysql-test/t/ctype_many.test @@ -0,0 +1,189 @@ +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 ( + comment CHAR(32) CHARACTER SET latin1 NOT NULL, + koi8_ru_f CHAR(32) CHARACTER SET koi8_ru NOT NULL +) CHARSET=latin5; + +SHOW CREATE TABLE t1; +ALTER TABLE t1 CHANGE comment comment CHAR(32) CHARACTER SET latin2 NOT NULL; +SHOW CREATE TABLE t1; +ALTER TABLE t1 ADD latin5_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +ALTER TABLE t1 CHARSET=latin2; +ALTER TABLE t1 ADD latin2_f CHAR(32) NOT NULL; +SHOW CREATE TABLE t1; +ALTER TABLE t1 DROP latin2_f, DROP latin5_f; +SHOW CREATE TABLE t1; + +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('a','LAT SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('b','LAT SMALL B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('c','LAT SMALL C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('d','LAT SMALL D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('e','LAT SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('f','LAT SMALL F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('g','LAT SMALL G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('h','LAT SMALL H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('i','LAT SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('j','LAT SMALL J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('k','LAT SMALL K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('l','LAT SMALL L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('m','LAT SMALL M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('n','LAT SMALL N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('o','LAT SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('p','LAT SMALL P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('q','LAT SMALL Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('r','LAT SMALL R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('s','LAT SMALL S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('t','LAT SMALL T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('u','LAT SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('v','LAT SMALL V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('w','LAT SMALL W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('x','LAT SMALL X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('y','LAT SMALL Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('z','LAT SMALL Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('A','LAT CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('B','LAT CAPIT B'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('C','LAT CAPIT C'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('D','LAT CAPIT D'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('E','LAT CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('F','LAT CAPIT F'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('G','LAT CAPIT G'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('H','LAT CAPIT H'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('I','LAT CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('J','LAT CAPIT J'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('K','LAT CAPIT K'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('L','LAT CAPIT L'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('M','LAT CAPIT M'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('N','LAT CAPIT N'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('O','LAT CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('P','LAT CAPIT P'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Q','LAT CAPIT Q'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('R','LAT CAPIT R'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('S','LAT CAPIT S'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('T','LAT CAPIT T'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('U','LAT CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('V','LAT CAPIT V'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('W','LAT CAPIT W'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('X','LAT CAPIT X'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Y','LAT CAPIT Y'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Z','LAT CAPIT Z'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Á','CYR SMALL A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Â','CYR SMALL BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('×','CYR SMALL VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ç','CYR SMALL GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ä','CYR SMALL DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Å','CYR SMALL IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('£','CYR SMALL IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ö','CYR SMALL ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ú','CYR SMALL ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('É','CYR SMALL I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ë','CYR SMALL KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ì','CYR SMALL EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Í','CYR SMALL EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Î','CYR SMALL EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ï','CYR SMALL O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ð','CYR SMALL PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ò','CYR SMALL ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ó','CYR SMALL ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ô','CYR SMALL TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Õ','CYR SMALL U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Æ','CYR SMALL EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('È','CYR SMALL HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ã','CYR SMALL TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Þ','CYR SMALL CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Û','CYR SMALL SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ý','CYR SMALL SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ß','CYR SMALL HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ù','CYR SMALL YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ø','CYR SMALL SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ü','CYR SMALL E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('À','CYR SMALL YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('Ñ','CYR SMALL YA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('á','CYR CAPIT A'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('â','CYR CAPIT BE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('÷','CYR CAPIT VE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ç','CYR CAPIT GE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ä','CYR CAPIT DE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('å','CYR CAPIT IE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('³','CYR CAPIT IO'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ö','CYR CAPIT ZHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ú','CYR CAPIT ZE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('é','CYR CAPIT I'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ë','CYR CAPIT KA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ì','CYR CAPIT EL'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('í','CYR CAPIT EM'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('î','CYR CAPIT EN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ï','CYR CAPIT O'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ð','CYR CAPIT PE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ò','CYR CAPIT ER'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ó','CYR CAPIT ES'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ô','CYR CAPIT TE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('õ','CYR CAPIT U'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('æ','CYR CAPIT EF'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('è','CYR CAPIT HA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ã','CYR CAPIT TSE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('þ','CYR CAPIT CHE'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('û','CYR CAPIT SHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ý','CYR CAPIT SCHA'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ÿ','CYR CAPIT HARD SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ù','CYR CAPIT YERU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ø','CYR CAPIT SOFT SIGN'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ü','CYR CAPIT E'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('à','CYR CAPIT YU'); +INSERT INTO t1 (koi8_ru_f,comment) VALUES ('ñ','CYR CAPIT YA'); + +ALTER TABLE t1 ADD utf8_f CHAR(32) CHARACTER SET utf8 NOT NULL; +UPDATE t1 SET utf8_f=CONVERT(koi8_ru_f USING utf8); + +SELECT * FROM t1; + +SELECT koi8_ru_f,MIN(comment) FROM t1 GROUP BY 1; +SELECT utf8_f,MIN(comment) FROM t1 GROUP BY 1; +SELECT DISTINCT koi8_ru_f FROM t1; +SELECT DISTINCT utf8_f FROM t1; +SELECT lower(koi8_ru_f) FROM t1 ORDER BY 1 DESC; +SELECT lower(utf8_f) FROM t1 ORDER BY 1 DESC; + +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 WHERE CONVERT(t11.koi8_ru_f USING utf8)=t12.utf8_f +ORDER BY t11.koi8_ru_f; + +SELECT t11.comment,t12.comment +FROM t1 t11,t1 t12 +WHERE t11.koi8_ru_f=CONVERT(t12.utf8_f USING koi8_ru) +ORDER BY t12.utf8_f; + +ALTER TABLE t1 ADD ucs2_f CHAR(32) CHARACTER SET ucs2 NOT NULL; + +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0391,'GREEK CAPIT ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0392,'GREEK CAPIT BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0393,'GREEK CAPIT GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0394,'GREEK CAPIT DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0395,'GREEK CAPIT EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B1,'GREEK SMALL ALPHA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B2,'GREEK SMALL BETA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B3,'GREEK SMALL GAMMA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B4,'GREEK SMALL DELTA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x03B5,'GREEK SMALL EPSILON'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0531,'ARMENIAN CAPIT AYB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0532,'ARMENIAN CAPIT BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0533,'ARMENIAN CAPIT GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0534,'ARMENIAN CAPIT DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0535,'ARMENIAN CAPIT ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0536,'ARMENIAN CAPIT ZA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0561,'ARMENIAN SMALL YAB'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0562,'ARMENIAN SMALL BEN'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0563,'ARMENIAN SMALL GIM'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0564,'ARMENIAN SMALL DA'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0565,'ARMENIAN SMALL ECH'); +INSERT INTO t1 (ucs2_f,comment) VALUES (0x0566,'ARMENIAN SMALL ZA'); + +ALTER TABLE t1 ADD armscii8_f CHAR(32) CHARACTER SET armscii8 NOT NULL; +ALTER TABLE t1 ADD greek_f CHAR(32) CHARACTER SET greek NOT NULL; +UPDATE t1 SET greek_f=CONVERT(ucs2_f USING greek) WHERE comment LIKE 'GRE%'; +UPDATE t1 SET armscii8_f=CONVERT(ucs2_f USING armscii8) WHERE comment LIKE 'ARM%'; +UPDATE t1 SET utf8_f=CONVERT(ucs2_f USING utf8) WHERE utf8_f=''; +UPDATE t1 SET ucs2_f=CONVERT(utf8_f USING ucs2) WHERE ucs2_f=''; +SELECT min(comment),count(*) FROM t1 GROUP BY ucs2_f; +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c94522fde8f..7b1ebdcbc27 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -26,4 +26,11 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1); select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1); select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4; +select * from t3 where exists (select * from t2 where t2.b=t3.a); +select * from t3 where not exists (select * from t2 where t2.b=t3.a); +insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9); +select b,max(a) as ma from t4 group by b having b < (select max(t2.a) +from t2 where t2.b=t4.b); +select b,max(a) as ma from t4 group by b having b >= (select max(t2.a) +from t2 where t2.b=t4.b); drop table t1,t2,t3,t4; diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh index a4e74fcb4f9..e82fd5d5907 100644 --- a/sql-bench/server-cfg.sh +++ b/sql-bench/server-cfg.sh @@ -115,7 +115,6 @@ sub new $self->{'data_source'} = "DBI:mysql:database=$database;host=$host"; $self->{'data_source'} .= ";mysql_socket=$socket" if($socket); $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "blob"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -168,25 +167,6 @@ sub new $limits{'working_all_fields'} = 1; $limits{'working_blobs'} = 1; # If big varchar/blobs works - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; - # Some fixes that depends on the environment if (defined($main::opt_create_options) && $main::opt_create_options =~ /type=heap/i) @@ -200,6 +180,11 @@ sub new $self->{'transactions'} = 1; # Transactions enabled } if (defined($main::opt_create_options) && + $main::opt_create_options =~ /type=bdb/i) + { + $self->{'transactions'} = 1; # Transactions enabled + } + if (defined($main::opt_create_options) && $main::opt_create_options =~ /type=gemini/i) { $limits{'working_blobs'} = 0; # Blobs not implemented yet @@ -266,7 +251,6 @@ sub create { $field =~ s/ decimal/ double(10,2)/i; $field =~ s/ big_decimal/ double(10,2)/i; - $field =~ s/ date/ int/i; # Because of tcp ? $query.= $field . ','; } foreach $index (@$index) @@ -575,7 +559,6 @@ sub new $self->{'cmp_name'} = "pg"; $self->{'data_source'} = "DBI:Pg:dbname=$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; @@ -626,27 +609,6 @@ sub new $limits{'working_all_fields'} = 1; $limits{'working_blobs'} = 1; # If big varchar/blobs works - # the different cases per query ... - $smds{'q1'} = 'b'; # with time - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time - $smds{'q4'} = 'c'; # with time - $smds{'q5'} = 'b'; # with time - $smds{'q6'} = 'c'; # strange error .... - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; # needs 128M to execute - can't do insert ...group by - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; # can't do float8 * int4 - create operator - $smds{'q12'} = 'd'; # strange error??? - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; # strange error??? - $smds{'q15'} = 'd'; # strange error??? - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; - $smds{'time'} = 1; # the use of the time table -> 1 is on. - # when 0 then the date field must be a - # date field not a int field!!! return $self; } @@ -871,7 +833,6 @@ sub new $self->{'cmp_name'} = "solid"; $self->{'data_source'} = "DBI:Solid:"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "long varchar"; $self->{'text'} = "long varchar"; $self->{'double_quotes'} = 1; @@ -922,28 +883,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - # for the smds small benchmark test .... - # the different cases per query ... - $smds{'q1'} = 'a'; - $smds{'q2'} = ''; - $smds{'q3'} = 'b'; #doesn't work -> strange error about column -fixed - $smds{'q4'} = 'a'; - $smds{'q5'} = 'b'; - $smds{'q6'} = 'c'; - $smds{'q7'} = 'b'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'b'; - $smds{'q10'} = 'b'; - $smds{'q11'} = ''; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'b'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = ''; - $smds{'q17'} = ''; - $smds{'time'} = 1; # the use of the time table -> 1 is on. - # when 0 then the date field must be a - # date field not a int field!!! return $self; } @@ -1119,7 +1058,6 @@ sub new $self->{'cmp_name'} = "empress"; $self->{'data_source'} = "DBI:EmpressNet:SERVER=$host;Database=/usr/local/empress/rdbms/bin/$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -1172,28 +1110,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - # for the smds small benchmark test .... - # the different cases per query ... EMPRESS - $smds{'q1'} = 'a'; - $smds{'q2'} = ''; - $smds{'q3'} = 'a'; - $smds{'q4'} = 'a'; - $smds{'q5'} = 'a'; - $smds{'q6'} = 'a'; - $smds{'q7'} = 'b'; - $smds{'q8'} = 'd'; - $smds{'q9'} = 'b'; - $smds{'q10'} = 'a'; - $smds{'q11'} = ''; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'b'; - $smds{'q14'} = 'b'; - $smds{'q15'} = 'a'; - $smds{'q16'} = ''; - $smds{'q17'} = ''; - $smds{'time'} = 1; # the use of the time table -> 1 is on. - # when 0 then the date field must be a - # date field not a int field!!! return $self; } @@ -1410,7 +1326,6 @@ sub new $self->{'cmp_name'} = "Oracle"; $self->{'data_source'} = "DBI:Oracle:$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "long"; $self->{'text'} = "long"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -1464,24 +1379,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -1675,7 +1572,6 @@ sub new $self->{'cmp_name'} = "Informix"; $self->{'data_source'} = "DBI:Informix:$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "byte in table"; $self->{'text'} = "byte in table"; $self->{'double_quotes'} = 0; # Can handle: 'Walker''s' @@ -1888,7 +1784,6 @@ sub new $self->{'data_source'} .= ":$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "blob"; $self->{'text'} = "blob"; # text ? $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2071,7 +1966,6 @@ sub new $self->{'data_source'} .= ":$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2264,7 +2158,6 @@ sub new $self->{'data_source'} .= ";hostname=$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "text"; $self->{'text'} = "text"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2497,7 +2390,6 @@ sub new $self->{'cmp_name'} = "Adabas"; $self->{'data_source'} = "DBI:Adabas:$database"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "long"; $self->{'text'} = "long"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2549,24 +2441,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -2718,7 +2592,6 @@ sub new $self->{'data_source'} .= ":$host"; } $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "varchar(255)"; $self->{'text'} = "varchar(255)"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2894,7 +2767,6 @@ sub new $self->{'cmp_name'} = "mimer"; $self->{'data_source'} = "DBI:mimer:$database:$host"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "binary varying(15000)"; $self->{'text'} = "character varying(15000)"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -2950,24 +2822,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -3112,7 +2966,6 @@ sub new $self->{'cmp_name'} = "interbase"; $self->{'data_source'} = "DBI:InterBase:database=$database:ib_dialect=3"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "blob"; $self->{'text'} = ""; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' @@ -3166,24 +3019,6 @@ sub new $limits{'order_by_unused'} = 1; $limits{'working_all_fields'} = 1; - $smds{'time'} = 1; - $smds{'q1'} = 'b'; # with time not supp by mysql ('') - $smds{'q2'} = 'b'; - $smds{'q3'} = 'b'; # with time ('') - $smds{'q4'} = 'c'; # with time not supp by mysql (d) - $smds{'q5'} = 'b'; # with time not supp by mysql ('') - $smds{'q6'} = 'c'; # with time not supp by mysql ('') - $smds{'q7'} = 'c'; - $smds{'q8'} = 'f'; - $smds{'q9'} = 'c'; - $smds{'q10'} = 'b'; - $smds{'q11'} = 'b'; - $smds{'q12'} = 'd'; - $smds{'q13'} = 'c'; - $smds{'q14'} = 'd'; - $smds{'q15'} = 'd'; - $smds{'q16'} = 'a'; - $smds{'q17'} = 'c'; return $self; } @@ -3331,7 +3166,6 @@ sub new $self->{'cmp_name'} = "FrontBase"; $self->{'data_source'} = "DBI:FB:dbname=$database;host=$host"; $self->{'limits'} = \%limits; - $self->{'smds'} = \%smds; $self->{'blob'} = "varchar(8000000)"; $self->{'text'} = "varchar(8000000)"; $self->{'double_quotes'} = 1; # Can handle: 'Walker''s' diff --git a/sql/field.cc b/sql/field.cc index 8b1073d32f3..a475612fbb0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3782,10 +3782,10 @@ uint Field_varstring::max_packed_col_length(uint max_length) Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint blob_pack_length, - bool binary_arg) + bool binary_arg, CHARSET_INFO *cs) :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L, null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg, - table_arg, default_charset_info), + table_arg, cs), packlength(blob_pack_length),binary_flag(binary_arg), geom_flag(true) { flags|= BLOB_FLAG; @@ -3967,9 +3967,9 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)), char *blob; memcpy_fixed(&blob,ptr+packlength,sizeof(char*)); if (!blob) - val_ptr->set("",0,default_charset_info); // A bit safer than ->length(0) + val_ptr->set("",0,field_charset); // A bit safer than ->length(0) else - val_ptr->set((const char*) blob,get_length(ptr),default_charset_info); + val_ptr->set((const char*) blob,get_length(ptr),field_charset); return val_ptr; } @@ -4782,7 +4782,8 @@ Field *make_field(char *ptr, uint32 field_length, if (f_is_blob(pack_flag)) return new Field_blob(ptr,null_pos,null_bit, unireg_check, field_name, table, - pack_length,f_is_binary(pack_flag) != 0); + pack_length,f_is_binary(pack_flag) != 0, + default_charset_info); if (f_is_geom(pack_flag)) return new Field_geom(ptr,null_pos,null_bit, unireg_check, field_name, table, diff --git a/sql/field.h b/sql/field.h index 5b9723654d9..5bc463af48d 100644 --- a/sql/field.h +++ b/sql/field.h @@ -842,11 +842,11 @@ public: Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg,uint blob_pack_length, - bool binary_arg); + bool binary_arg, CHARSET_INFO *cs); Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg, bool binary_arg) + struct st_table *table_arg, bool binary_arg, CHARSET_INFO *cs) :Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0, - NONE, field_name_arg, table_arg, default_charset_info), + NONE, field_name_arg, table_arg, cs), packlength(3),binary_flag(binary_arg), geom_flag(true) { flags|= BLOB_FLAG; @@ -930,11 +930,12 @@ public: struct st_table *table_arg,uint blob_pack_length, bool binary_arg) :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, table_arg, blob_pack_length,binary_arg) {} + field_name_arg, table_arg, blob_pack_length,binary_arg, + default_charset_info) {} Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, struct st_table *table_arg, bool binary_arg) :Field_blob(len_arg, maybe_null_arg, field_name_arg, - table_arg, binary_arg) {} + table_arg, binary_arg, default_charset_info) {} enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; } void get_key_image(char *buff,uint length, imagetype type); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 3b6de1383e2..da7a1187a47 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -508,7 +508,8 @@ void field_conv(Field *to,Field *from) if (!blob->value.is_alloced() && from->real_type() != FIELD_TYPE_STRING) blob->value.copy(); - blob->store(blob->value.ptr(),blob->value.length(),default_charset_info); + blob->store(blob->value.ptr(),blob->value.length(), + to->binary()?default_charset_info:((Field_str*)to)->charset()); return; } if ((from->result_type() == STRING_RESULT && @@ -520,7 +521,9 @@ void field_conv(Field *to,Field *from) char buff[MAX_FIELD_WIDTH]; String result(buff,sizeof(buff),default_charset_info); from->val_str(&result,&result); - to->store(result.c_ptr_quick(),result.length(),default_charset_info); + to->store(result.c_ptr_quick(),result.length(), + to->binary()?default_charset_info:((Field_str*)to)->charset()); + // QQ: what to do if "from" and "to" are of dirrent charsets? } else if (from->result_type() == REAL_RESULT) to->store(from->val_real()); diff --git a/sql/handler.h b/sql/handler.h index 45865c39154..7260e8f2f8c 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -137,6 +137,7 @@ enum row_type { ROW_TYPE_NOT_USED=-1, ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, #define HA_CREATE_USED_MAX_ROWS 32 #define HA_CREATE_USED_AVG_ROW_LENGTH 64 #define HA_CREATE_USED_PACK_KEYS 128 +#define HA_CREATE_USED_CHARSET 256 typedef struct st_thd_trans { void *bdb_tid; diff --git a/sql/item.cc b/sql/item.cc index d01a06e5eba..81c5168b72d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -133,6 +133,9 @@ void Item_field::set_field(Field *field_par) field_name=field_par->field_name; binary=field_par->binary(); unsigned_flag=test(field_par->flags & UNSIGNED_FLAG); + /* For string fields copy character set from original field */ + if (!field_par->binary()) + str_value.set_charset(((Field_str*)field_par)->charset()); } const char *Item_ident::full_name() const @@ -443,12 +446,13 @@ String *Item_copy_string::val_str(String *str) /* ARGSUSED */ bool Item::fix_fields(THD *thd, - struct st_table_list *list) + struct st_table_list *list, + Item ** ref) { return 0; } -bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (!field) // If field is not checked { @@ -464,7 +468,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) mention of table name, but if we join tables in one list it will cause error ER_NON_UNIQ_ERROR in find_field_in_tables. */ - SELECT_LEX *last; + SELECT_LEX *last= 0; for (SELECT_LEX *sl= thd->lex.select->outer_select(); sl && !tmp; sl= sl->outer_select()) @@ -473,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) if (!tmp) return 1; else + { + depended_from= last; /* Mark all selects from resolved to 1 before select where was found table as depended (of select where was found table) @@ -490,6 +496,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) tbl= tbl->next) tbl->shared= 1; } + } } set_field(tmp); } @@ -501,6 +508,14 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables) table->used_fields++; table->used_keys&=field->part_of_key; } + if (depended_from != 0 && depended_from->having_fix_field) + { + *ref= new Item_ref((char *)db_name, (char *)table_name, + (char *)field_name); + if (!*ref) + return 1; + return (*ref)->fix_fields(thd, tables, ref); + } return 0; } @@ -784,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet) Find field in select list having the same name */ -bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) { if (!ref) { - if (!(ref=find_item_in_list(this,thd->lex.select->item_list))) - return 1; + if (!(ref= find_item_in_list(this,thd->lex.select->item_list))) + { + /* + We can't find table field in table list of current select, + consequently we have to find it in outer subselect(s). + We can't join lists of outer & current select, because of scope + of view rules. For example if both tables (outer & current) have + field 'field' it is not mistake to refer to this field without + mention of table name, but if we join tables in one list it will + cause error ER_NON_UNIQ_ERROR in find_field_in_tables. + */ + SELECT_LEX *last=0; + for (SELECT_LEX *sl= thd->lex.select->outer_select(); + sl && !ref; + sl= sl->outer_select()) + ref= find_item_in_list(this, (last= sl)->item_list); + if (!ref) + return 1; + else + { + depended_from= last; + /* + Mark all selects from resolved to 1 before select where was + found table as depended (of select where was found table) + */ + for (SELECT_LEX *s= thd->lex.select; + s &&s != last; + s= s->outer_select()) + if( !s->depended ) + { + s->depended= 1; //Select is depended of outer select + //Tables will be reopened many times + for (TABLE_LIST *tbl= + (TABLE_LIST*)s->table_list.first; + tbl; + tbl= tbl->next) + tbl->shared= 1; + } + } + } max_length= (*ref)->max_length; maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; diff --git a/sql/item.h b/sql/item.h index e6debdf2afc..187e3903b84 100644 --- a/sql/item.h +++ b/sql/item.h @@ -52,7 +52,7 @@ public: virtual ~Item() { name=0; } /*lint -e1509 */ void set_name(char* str,uint length=0); void init_make_field(Send_field *tmp_field,enum enum_field_types type); - virtual bool fix_fields(THD *,struct st_table_list *); + virtual bool fix_fields(THD *, struct st_table_list *, Item **); virtual bool save_in_field(Field *field); virtual void save_org_in_field(Field *field) { (void) save_in_field(field); } @@ -85,15 +85,18 @@ public: }; +class st_select_lex; class Item_ident :public Item { public: const char *db_name; const char *table_name; const char *field_name; + st_select_lex *depended_from; Item_ident(const char *db_name_par,const char *table_name_par, const char *field_name_par) - :db_name(db_name_par),table_name(table_name_par),field_name(field_name_par) + :db_name(db_name_par),table_name(table_name_par), + field_name(field_name_par), depended_from(0) { name = (char*) field_name_par; } const char *full_name() const; }; @@ -120,7 +123,7 @@ public: String *str_result(String* tmp); bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); } void make_field(Send_field *field); - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, struct st_table_list *, Item **); bool save_in_field(Field *field); void save_org_in_field(Field *field); table_map used_tables() const; @@ -390,7 +393,7 @@ public: } bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } void make_field(Send_field *field) { (*ref)->make_field(field); } - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, struct st_table_list *, Item **); bool save_in_field(Field *field) { return (*ref)->save_in_field(field); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } enum Item_result result_type () const { return (*ref)->result_type(); } diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 8433ae5bfba..0fc9a1f0e4c 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -727,12 +727,12 @@ double Item_func_case::val() bool -Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables) +Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (first_expr && first_expr->fix_fields(thd,tables) || - else_expr && else_expr->fix_fields(thd,tables)) + if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) || + else_expr && else_expr->fix_fields(thd, tables, &else_expr)) return 1; - if (Item_func::fix_fields(thd,tables)) + if (Item_func::fix_fields(thd, tables, ref)) return 1; if (first_expr) { @@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int() bool -Item_cond::fix_fields(THD *thd,TABLE_LIST *tables) +Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { List_iterator<Item> li(list); Item *item; @@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables) #endif item= *li.ref(); // new current item } - if (item->fix_fields(thd,tables)) + if (item->fix_fields(thd, tables, li.ref())) return 1; /* purecov: inspected */ used_tables_cache|=item->used_tables(); with_sum_func= with_sum_func || item->with_sum_func; @@ -1272,9 +1272,9 @@ Item_func::optimize_type Item_func_like::select_optimize() const return OPTIMIZE_NONE; } -bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist) +bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) { - if (Item_bool_func2::fix_fields(thd, tlist)) + if (Item_bool_func2::fix_fields(thd, tlist, ref)) return 1; /* @@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist) #ifdef USE_REGEX bool -Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables) +Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (args[0]->fix_fields(thd,tables) || args[1]->fix_fields(thd,tables)) + if (args[0]->fix_fields(thd, tables, args) || + args[1]->fix_fields(thd,tables, args + 1)) return 1; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; max_length=1; decimals=0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 302ad88905e..08c5a30c57c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -177,9 +177,10 @@ public: Item_func_interval(Item *a,List<Item> &list) :Item_int_func(list),item(a),intervals(0) {} longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); ~Item_func_interval() { delete item; } @@ -259,7 +260,7 @@ public: enum Item_result result_type () const { return cached_result_type; } const char *func_name() const { return "case"; } void print(String *str); - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); Item *find_item(String *str); }; @@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func Item_func_in(Item *a,List<Item> &list) :Item_int_func(list),item(a),array(0),in_item(0) {} longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); ~Item_func_in() { delete item; delete array; delete in_item; } @@ -505,7 +507,7 @@ public: cond_result eq_cmp_result() const { return COND_TRUE; } const char *func_name() const { return "like"; } void fix_length_and_dec(); - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); }; #ifdef USE_REGEX @@ -523,7 +525,7 @@ public: regex_compiled(0),regex_is_const(0) {} ~Item_func_regex(); longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); const char *func_name() const { return "regex"; } }; @@ -552,7 +554,7 @@ public: { list.push_back(i1); list.push_back(i2); } ~Item_cond() { list.delete_elements(); } bool add(Item *item) { return list.push_back(item); } - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, struct st_table_list *, Item **ref); enum Type type() const { return COND_ITEM; } List<Item>* argument_list() { return &list; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 0675bf81dab..ae3fc7cb8f0 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list) } bool -Item_func::fix_fields(THD *thd,TABLE_LIST *tables) +Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { Item **arg,**arg_end; char buff[STACK_BUFF_ALLOC]; // Max argument in function @@ -72,12 +72,23 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables) { // Print purify happy for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - if ((*arg)->fix_fields(thd,tables)) + if ((*arg)->fix_fields(thd, tables, arg)) return 1; /* purecov: inspected */ if ((*arg)->maybe_null) maybe_null=1; if ((*arg)->binary) binary=1; + /* + Change charset to arg charset if it is not equal to + default_charset_info. This will work for many cases, + but generally this should be done more carefull. Each string + function should have it's own fix_fields() method to correctly + setup it's result's character set taking in account arguments. + For example: left(a,b) should take in account only first argument, + but ignore the second one. + */ + if ((*arg)->str_value.charset() != default_charset_info) + str_value.set_charset((*arg)->str_value.charset()); with_sum_func= with_sum_func || (*arg)->with_sum_func; used_tables_cache|=(*arg)->used_tables(); const_item_cache&= (*arg)->const_item(); @@ -1091,7 +1102,7 @@ udf_handler::~udf_handler() bool -udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, +udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, uint arg_count, Item **arguments) { char buff[STACK_BUFF_ALLOC]; // Max argument in function @@ -1135,7 +1146,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func, arg != arg_end ; arg++,i++) { - if ((*arg)->fix_fields(thd,tables)) + if ((*arg)->fix_fields(thd, tables, arg)) return 1; if ((*arg)->binary) func->binary=1; @@ -1754,11 +1765,12 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, } -bool Item_func_set_user_var::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables, + Item **ref) { if (!thd) thd=current_thd; - if (Item_func::fix_fields(thd,tables) || + if (Item_func::fix_fields(thd, tables, ref) || !(entry= get_variable(&thd->user_vars, name, 1))) return 1; entry->update_query_id=thd->query_id; @@ -2084,7 +2096,7 @@ void Item_func_match::init_search(bool no_order) } } -bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) +bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { List_iterator<Item> li(fields); Item *item; @@ -2097,7 +2109,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) modifications to find_best and auto_close as complement to auto_init code above. */ - if (Item_func::fix_fields(thd,tlist) || !const_item()) + if (Item_func::fix_fields(thd, tlist, ref) || !const_item()) { my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST"); return 1; @@ -2105,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist) while ((item=li++)) { - if (item->fix_fields(thd,tlist)) + if (item->fix_fields(thd, tlist, li.ref())) return 1; if (item->type() == Item::REF_ITEM) li.replace(item= *((Item_ref *)item)->ref); diff --git a/sql/item_func.h b/sql/item_func.h index 0056126d50e..86b2a17931d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -99,7 +99,7 @@ public: } Item_func(List<Item> &list); ~Item_func() {} /* Nothing to do; Items are freed automaticly */ - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *,struct st_table_list *, Item **ref); void make_field(Send_field *field); table_map used_tables() const; void update_used_tables(); @@ -567,9 +567,10 @@ public: Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {} ~Item_func_field() { delete item; } longlong val_int(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void update_used_tables() { @@ -708,11 +709,11 @@ public: :Item_func(list), udf(udf_arg) {} ~Item_udf_func() {} const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd,struct st_table_list *tables) + bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref) { - bool res=udf.fix_fields(thd,tables,this,arg_count,args); - used_tables_cache=udf.used_tables_cache; - const_item_cache=udf.const_item_cache; + bool res= udf.fix_fields(thd, tables, this, arg_count, args); + used_tables_cache= udf.used_tables_cache; + const_item_cache= udf.const_item_cache; return res; } Item_result result_type () const { return udf.result_type(); } @@ -867,7 +868,7 @@ public: void update_hash(void *ptr, uint length, enum Item_result type); bool update(); enum Item_result result_type () const { return cached_result_type; } - bool fix_fields(THD *thd,struct st_table_list *tables); + bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref); void fix_length_and_dec(); void print(String *str); const char *func_name() const { return "set_user_var"; } @@ -941,7 +942,7 @@ public: } enum Functype functype() const { return FT_FUNC; } void update_used_tables() {} - bool fix_fields(THD *thd,struct st_table_list *tlist); + bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); bool eq(const Item *, bool binary_cmp) const; longlong val_int() { return val()!=0.0; } double val(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 5275da95b6e..1aee4e7d553 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -759,6 +759,7 @@ String *Item_func_left::val_str(String *str) if (!res->alloced_length()) { // Don't change const str str_value= *res; // Not malloced string + str_value.set_charset(res->charset()); res= &str_value; } res->length((uint) length); @@ -1791,6 +1792,7 @@ String *Item_func_conv_charset::val_str(String *str) null_value=1; return 0; } + null_value=0; from=arg->charset(); to=conv_charset; @@ -1798,7 +1800,7 @@ String *Item_func_conv_charset::val_str(String *str) s=(const uchar*)arg->ptr(); se=s+arg->length(); - dmaxlen=arg->length()*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1)+1; + dmaxlen=arg->length()*(to->mbmaxlen?to->mbmaxlen:1)+1; str->alloc(dmaxlen); d0=d=(unsigned char*)str->ptr(); de=d+dmaxlen; @@ -1840,7 +1842,7 @@ outp: void Item_func_conv_charset::fix_length_and_dec() { - /* BAR TODO: What to do here??? */ + max_length = args[0]->max_length*(conv_charset->mbmaxlen?conv_charset->mbmaxlen:1); } @@ -1910,9 +1912,41 @@ outp: return str; } + +bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables) +{ + char buff[STACK_BUFF_ALLOC]; // Max argument in function + binary=0; + used_tables_cache=0; + const_item_cache=1; + + if (thd && check_stack_overrun(thd,buff)) + return 0; // Fatal error if flag is set! + if (args[0]->fix_fields(thd, tables, args)) + return 1; + maybe_null=args[0]->maybe_null; + binary=args[0]->binary; + const_item_cache=args[0]->const_item(); + str_value.set_charset(conv_charset); + fix_length_and_dec(); + return 0; +} + + void Item_func_conv_charset3::fix_length_and_dec() { - /* BAR TODO: What to do here??? */ + max_length = args[0]->max_length; +} + + +String *Item_func_charset::val_str(String *str) +{ + String *res = args[0]->val_str(str); + + if ((null_value=(args[0]->null_value || !res->charset()))) + return 0; + str->copy(res->charset()->name,strlen(res->charset()->name)); + return str; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 03ef65c352a..7b5bd7ae90b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -40,9 +40,10 @@ public: if (!t_arg) return result_field; return (max_length > 255) ? - (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary) : + (Field *)new Field_blob(max_length,maybe_null, name,t_arg, binary, + str_value.charset()) : (Field *) new Field_string(max_length,maybe_null, name,t_arg, binary, - default_charset_info); + str_value.charset()); } }; @@ -79,10 +80,10 @@ public: String *val_str(String *); void fix_length_and_dec(); void update_used_tables(); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (separator->fix_fields(thd,tlist) - || Item_func::fix_fields(thd,tlist)); + return (separator->fix_fields(thd, tlist, &separator) + || Item_func::fix_fields(thd, tlist, ref)); } const char *func_name() const { return "concat_ws"; } }; @@ -325,9 +326,10 @@ public: double val(); longlong val_int(); String *val_str(String *str); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); void update_used_tables(); @@ -344,9 +346,10 @@ public: Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {} ~Item_func_make_set() { delete item; } String *val_str(String *str); - bool fix_fields(THD *thd,struct st_table_list *tlist) + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); + return (item->fix_fields(thd, tlist, &item) || + Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); void update_used_tables(); @@ -488,6 +491,7 @@ public: { conv_charset=cs; } + bool fix_fields(THD *thd,struct st_table_list *tables); String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "conv_charset"; } @@ -503,6 +507,18 @@ public: const char *func_name() const { return "conv_charset3"; } }; +class Item_func_charset :public Item_str_func +{ +public: + Item_func_charset(Item *a) :Item_str_func(a) {} + String *val_str(String *); + const char *func_name() const { return "charset"; } + void fix_length_and_dec() + { + max_length=20; // should be enough + }; +}; + /******************************************************* Spatial functions diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c2349ed414c..2bff2af45e4 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -35,12 +35,13 @@ SUBSELECT TODO: #include "mysql_priv.h" #include "sql_select.h" -Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex): +Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex, + select_subselect *result): assigned(0), executed(0), optimized(0), error(0) { DBUG_ENTER("Item_subselect::Item_subselect"); DBUG_PRINT("subs", ("select_lex 0x%xl", (long) select_lex)); - result= new select_subselect(this); + this->result= result; SELECT_LEX_UNIT *unit= select_lex->master_unit(); unit->offset_limit_cnt= unit->global_parameters->offset_limit; unit->select_limit_cnt= unit->global_parameters->select_limit+ @@ -51,41 +52,15 @@ Item_subselect::Item_subselect(THD *thd, st_select_lex *select_lex): select_lex->options&= ~OPTION_FOUND_ROWS; join= new JOIN(thd, select_lex->item_list, select_lex->options, result); this->select_lex= select_lex; - maybe_null= 1; + assign_null(); /* item value is NULL if select_subselect not changed this value (i.e. some rows will be found returned) */ - assign_null(); + null_value= 1; DBUG_VOID_RETURN; } -Item::Type Item_subselect::type() const -{ - return SUBSELECT_ITEM; -} - -double Item_subselect::val () -{ - if (exec()) - return 0; - return real_value; -} - -longlong Item_subselect::val_int () -{ - if (exec()) - return 0; - return int_value; -} - -String *Item_subselect::val_str (String *str) -{ - if (exec() || null_value) - return 0; - return &str_value; -} - void Item_subselect::make_field (Send_field *tmp_field) { if (null_value) @@ -100,17 +75,10 @@ void Item_subselect::make_field (Send_field *tmp_field) } } -bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - - if (thd->having_fix_field) - { - //TODO: subselects in having do not suported now - my_printf_error(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0)); - return 1; - } // Is it one field subselect? - if (select_lex->item_list.elements != 1) + if (select_lex->item_list.elements > max_columns) { my_printf_error(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); return 1; @@ -131,13 +99,14 @@ bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables) int Item_subselect::exec() { + DBUG_ENTER("Item_subselect::exec"); if (!optimized) { optimized=1; if (join->optimize()) { executed= 1; - return (join->error?join->error:1); + DBUG_RETURN(join->error?join->error:1); } } if (join->select_lex->depended && executed) @@ -145,7 +114,7 @@ int Item_subselect::exec() if (join->reinit()) { error= 1; - return 1; + DBUG_RETURN(1); } assign_null(); executed= assigned= 0; @@ -157,7 +126,80 @@ int Item_subselect::exec() join->exec(); join->thd->lex.select= save_select; executed= 1; - return join->error; + DBUG_RETURN(join->error); } - return 0; + DBUG_RETURN(0); } + +inline table_map Item_subselect::used_tables() const +{ + return (table_map) select_lex->depended ? 1L : 0L; +} + +Item_singleval_subselect::Item_singleval_subselect(THD *thd, + st_select_lex *select_lex): + Item_subselect(thd, select_lex, new select_singleval_subselect(this)) +{ + max_columns= 1; + maybe_null= 1; +} + +Item::Type Item_subselect::type() const +{ + return SUBSELECT_ITEM; +} + +double Item_singleval_subselect::val () +{ + if (exec()) + return 0; + return real_value; +} + +longlong Item_singleval_subselect::val_int () +{ + if (exec()) + return 0; + return int_value; +} + +String *Item_singleval_subselect::val_str (String *str) +{ + if (exec() || null_value) + return 0; + return &str_value; +} + +Item_exists_subselect::Item_exists_subselect(THD *thd, + st_select_lex *select_lex): + Item_subselect(thd, select_lex, new select_singleval_subselect(this)) +{ + max_columns= UINT_MAX; + null_value= 0; //can't be NULL + maybe_null= 0; //can't be NULL + value= 0; + select_lex->select_limit= 1; // we need only 1 row to determinate existence +} + +double Item_exists_subselect::val () +{ + if (exec()) + return 0; + return (double) value; +} + +longlong Item_exists_subselect::val_int () +{ + if (exec()) + return 0; + return value; +} + +String *Item_exists_subselect::val_str(String *str) +{ + if (exec()) + return 0; + str->set(value); + return str; +} + diff --git a/sql/item_subselect.h b/sql/item_subselect.h index c6963df2d53..88ea01f9c68 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -20,46 +20,38 @@ #pragma interface /* gcc class implementation */ #endif -struct st_select_lex; +class st_select_lex; class JOIN; class select_subselect; -/* simple (not depended of covered select ) subselect */ +/* base class for subselects */ class Item_subselect :public Item { protected: - longlong int_value; - double real_value; + uint max_columns; my_bool assigned; /* value already assigned to subselect */ my_bool executed; /* simple subselect is executed */ my_bool optimized; /* simple subselect is optimized */ my_bool error; /* error in query */ - enum Item_result res_type; int exec(); - void assign_null() + virtual void assign_null() { null_value= 1; - int_value= 0; - real_value= 0; - max_length= 4; - res_type= STRING_RESULT; } public: st_select_lex *select_lex; JOIN *join; select_subselect *result; - Item_subselect(THD *thd, st_select_lex *select_lex); + Item_subselect(THD *thd, st_select_lex *select_lex, + select_subselect* result); Item_subselect(Item_subselect *item) { null_value= item->null_value; - int_value= item->int_value; - real_value= item->real_value; - max_length= item->max_length; decimals= item->decimals; - res_type= item->res_type; + max_columns= item->max_columns; assigned= item->assigned; executed= item->executed; select_lex= item->select_lex; @@ -69,16 +61,75 @@ public: error= item->error; } enum Type type() const; + bool is_null() { return null_value; } + void make_field (Send_field *); + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + table_map used_tables() const; + + friend class select_subselect; +}; + + +/* single value subselect */ + +class Item_singleval_subselect :public Item_subselect +{ +protected: + longlong int_value; + double real_value; + enum Item_result res_type; + + virtual void assign_null() + { + null_value= 1; + int_value= 0; + real_value= 0; + max_length= 4; + res_type= STRING_RESULT; + } +public: + Item_singleval_subselect(THD *thd, st_select_lex *select_lex); + Item_singleval_subselect(Item_singleval_subselect *item): + Item_subselect(item) + { + int_value= item->int_value; + real_value= item->real_value; + max_length= item->max_length; + decimals= item->decimals; + res_type= item->res_type; + } double val (); longlong val_int (); String *val_str (String *); - bool is_null() { return null_value; } - void make_field (Send_field *); - bool fix_fields(THD *thd, TABLE_LIST *tables); - Item *new_item() { return new Item_subselect(this); } + Item *new_item() { return new Item_singleval_subselect(this); } enum Item_result result_type() const { return res_type; } - friend class select_subselect; + friend class select_singleval_subselect; }; +/* exists subselect */ +class Item_exists_subselect :public Item_subselect +{ +protected: + longlong value; + + virtual void assign_null() + { + value= 0; + } +public: + Item_exists_subselect(THD *thd, st_select_lex *select_lex); + Item_exists_subselect(Item_exists_subselect *item): + Item_subselect(item) + { + value= item->value; + } + Item *new_item() { return new Item_exists_subselect(this); } + enum Item_result result_type() const { return INT_RESULT;} + longlong val_int(); + double val(); + String *val_str(String*); + + friend class select_exists_subselect; +}; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 6ef968c33f7..809dd65d52b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -112,7 +112,7 @@ Item_sum_int::val_str(String *str) bool -Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) +Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { if (!thd->allow_sum_func) { @@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) maybe_null=0; for (uint i=0 ; i < arg_count ; i++) { - if (args[i]->fix_fields(thd,tables)) + if (args[i]->fix_fields(thd, tables, args + i)) return 1; if (decimals < args[i]->decimals) decimals=args[i]->decimals; @@ -140,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables) bool -Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables) +Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { Item *item=args[0]; if (!thd->allow_sum_func) @@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables) return 1; } thd->allow_sum_func=0; // No included group funcs - if (item->fix_fields(thd,tables)) + if (item->fix_fields(thd, tables, args)) return 1; hybrid_type=item->result_type(); if (hybrid_type == INT_RESULT) @@ -930,9 +930,10 @@ Item_sum_count_distinct::~Item_sum_count_distinct() } -bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables) +bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables, + Item **ref) { - if (Item_sum_num::fix_fields(thd,tables) || + if (Item_sum_num::fix_fields(thd, tables, ref) || !(tmp_table_param= new TMP_TABLE_PARAM)) return 1; return 0; diff --git a/sql/item_sum.h b/sql/item_sum.h index a963799b6a7..3e67f1e3624 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -80,7 +80,7 @@ public: Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(List<Item> &list) :Item_sum(list) {} - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, TABLE_LIST *, Item **); longlong val_int() { return (longlong) val(); } /* Real as default */ String *val_str(String*str); void reset_field(); @@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int { TABLE *table; table_map used_table_cache; - bool fix_fields(THD *thd,TABLE_LIST *tables); + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); uint32 *field_lengths; TMP_TABLE_PARAM *tmp_table_param; TREE tree; @@ -283,7 +283,7 @@ class Item_sum_hybrid :public Item_sum Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign), used_table_cache(~(table_map) 0) {} - bool fix_fields(THD *,struct st_table_list *); + bool fix_fields(THD *, TABLE_LIST *, Item **); table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } @@ -382,7 +382,7 @@ public: { quick_group=0;} ~Item_udf_sum() {} const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd,struct st_table_list *tables) + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { return udf.fix_fields(thd,tables,this,this->arg_count,this->args); } diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 4be64ecc74a..e56632e7289 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -42,5 +42,5 @@ public: bool add() { return 0; } void reset_field() {} void update_field(int offset) {} - bool fix_fields(THD *thd,struct st_table_list *tlist) { return 0;} + bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { return 0;} }; diff --git a/sql/lex.h b/sql/lex.h index da0a71a135e..4af36df58af 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -82,6 +82,7 @@ static SYMBOL symbols[] = { { "CASE", SYM(CASE_SYM),0,0}, { "CHAR", SYM(CHAR_SYM),0,0}, { "CHARACTER", SYM(CHAR_SYM),0,0}, + { "CHARSET", SYM(CHARSET),0,0}, { "CHANGE", SYM(CHANGE),0,0}, { "CHANGED", SYM(CHANGED),0,0}, { "CHECK", SYM(CHECK_SYM),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5013224b52c..3b4518afe30 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -289,7 +289,8 @@ inline THD *_current_thd(void) #define prepare_execute(A) ((A)->command == COM_EXECUTE) -int mysql_create_db(THD *thd, char *db, uint create_info, bool silent); +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); +int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags); int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists); @@ -471,6 +472,7 @@ int mysqld_show_logs(THD *thd); void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1); int mysqld_show_create(THD *thd, TABLE_LIST *table_list); +int mysqld_show_create_db(THD *thd, const char *dbname); void mysqld_list_processes(THD *thd,const char *user,bool verbose); int mysqld_show_status(THD *thd); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7f843fee7b3..eb3555b4fe6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1876,7 +1876,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, } else { - if (item->fix_fields(thd,tables)) + if (item->fix_fields(thd, tables, it.ref())) DBUG_RETURN(-1); /* purecov: inspected */ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && sum_func_list) @@ -2027,7 +2027,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) if (*conds) { thd->where="where clause"; - if ((*conds)->fix_fields(thd,tables)) + if ((*conds)->fix_fields(thd, tables, conds)) DBUG_RETURN(1); } @@ -2038,7 +2038,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) { /* Make a join an a expression */ thd->where="on clause"; - if (table->on_expr->fix_fields(thd,tables)) + if (table->on_expr->fix_fields(thd, tables, &table->on_expr)) DBUG_RETURN(1); thd->cond_count++; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a386fac4589..07f29eacf29 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -81,7 +81,7 @@ static void free_var(user_var_entry *entry) THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), insert_id_used(0), in_lock_tables(0), - global_read_lock(0), bootstrap(0), having_fix_field(0) + global_read_lock(0), bootstrap(0) { host=user=priv_user=db=query=ip=0; host_or_ip="unknown ip"; @@ -103,6 +103,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), file_id = 0; cond_count=0; convert_set=0; + db_charset=default_charset_info; mysys_var=0; #ifndef DBUG_OFF dbug_sentry=THD_SENTRY_MAGIC; @@ -769,7 +770,6 @@ void select_dump::send_error(uint errcode,const char *err) file= -1; } - bool select_dump::send_eof() { int error=test(end_io_cache(&cache)); @@ -788,10 +788,11 @@ select_subselect::select_subselect(Item_subselect *item) this->item=item; } -bool select_subselect::send_data(List<Item> &items) +bool select_singleval_subselect::send_data(List<Item> &items) { - DBUG_ENTER("select_subselect::send_data"); - if (item->assigned){ + DBUG_ENTER("select_singleval_subselect::send_data"); + Item_singleval_subselect *it= (Item_singleval_subselect *)item; + if (it->assigned){ my_printf_error(ER_SUBSELECT_NO_1_ROW, ER(ER_SUBSELECT_NO_1_ROW), MYF(0)); DBUG_RETURN(1); } @@ -806,18 +807,33 @@ bool select_subselect::send_data(List<Item> &items) Following val() call have to be first, because function AVG() & STD() calculate value on it & determinate "is it NULL?". */ - item->real_value= val_item->val(); - if ((item->null_value= val_item->is_null())) + it->real_value= val_item->val(); + if ((it->null_value= val_item->is_null())) { - item->assign_null(); + it->assign_null(); } else { - item->max_length= val_item->max_length; - item->decimals= val_item->decimals; - item->binary= val_item->binary; - val_item->val_str(&item->str_value); - item->int_value= val_item->val_int(); - item->res_type= val_item->result_type(); + it->max_length= val_item->max_length; + it->decimals= val_item->decimals; + it->binary= val_item->binary; + val_item->val_str(&it->str_value); + it->int_value= val_item->val_int(); + it->res_type= val_item->result_type(); } - item->assigned= 1; + it->assigned= 1; DBUG_RETURN(0); } + +bool select_exists_subselect::send_data(List<Item> &items) +{ + DBUG_ENTER("select_exists_subselect::send_data"); + Item_exists_subselect *it= (Item_exists_subselect *)item; + if (unit->offset_limit_cnt) + { // Using limit offset,count + unit->offset_limit_cnt--; + DBUG_RETURN(0); + } + it->value= 1; + it->assigned= 1; + DBUG_RETURN(0); +} + diff --git a/sql/sql_class.h b/sql/sql_class.h index da21b911dd7..9658c084ec7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -460,7 +460,6 @@ public: bool query_error, bootstrap, cleanup_done; bool safe_to_cache_query; bool volatile killed; - bool having_fix_field; //TRUE when having fix field called bool prepare_command; ulong param_count,current_param_number; Error<mysql_st_error> err_list; @@ -480,7 +479,8 @@ public: ulong slave_proxy_id; NET* slave_net; // network connection from slave -> m. my_off_t log_pos; - + CHARSET_INFO *db_charset; + THD(); ~THD(); void cleanup(void); @@ -749,19 +749,36 @@ class select_union :public select_result { bool flush(); }; -/* Single value subselect interface class */ +/* Base subselect interface class */ class select_subselect :public select_result { +protected: Item_subselect *item; public: select_subselect(Item_subselect *item); bool send_fields(List<Item> &list, uint flag) { return 0; }; - bool send_data(List<Item> &items); + bool send_data(List<Item> &items)=0; bool send_eof() { return 0; }; - + friend class Ttem_subselect; }; +/* Single value subselect interface class */ +class select_singleval_subselect :public select_subselect +{ +public: + select_singleval_subselect(Item_subselect *item):select_subselect(item){} + bool send_data(List<Item> &items); +}; + +/* EXISTS subselect interface class */ +class select_exists_subselect :public select_subselect +{ +public: + select_exists_subselect(Item_subselect *item):select_subselect(item){} + bool send_data(List<Item> &items); +}; + /* Structs used when sorting */ typedef struct st_sort_field { diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 3f619b70244..7e82e1433b9 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -25,20 +25,114 @@ #include <direct.h> #endif +#define MY_DB_OPT_FILE ".db.opt" + static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, uint level); +/* + Create database options file: + Currently databse default charset is only stored there. +*/ + +static int write_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn) +{ + register File file; + char buf[256]; // Should be enough + int error=0; + + if ((file=my_create(fn,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + { + sprintf(buf,"default-character-set=%s\n", + (create && create->table_charset) ? + create->table_charset->name : "DEFAULT"); + + if (my_write(file,(byte*)buf,strlen(buf),MYF(MY_NABP+MY_WME))) + { + // QQ : should we send more suitable error message? + my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); + error = -1; + goto exit; + } + my_close(file,MYF(0)); + } + else + { + // QQ : should we send more suitable error message? + my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno); + error = -1; + goto exit; + } +exit: + return error; +} + + + /* + Load database options file: + */ +static int load_db_opt(THD *thd,const char *db,HA_CREATE_INFO *create,char *fn) +{ + register File file; + char buf[256]=""; + + if ((file=my_open(fn,O_RDWR|O_BINARY,MYF(MY_WME))) >= 0) + { + int nbytes=my_read(file,(byte*)buf,sizeof(buf)-1,MYF(0)); + if ( nbytes >= 0 ) + { + char *ln=buf; + char *pe=buf+nbytes; + + buf[nbytes]='\0'; + + for ( ln=buf; ln<pe; ) + { + char *le,*val; + for ( le=ln, val=0 ; le<pe ; le++ ) + { + switch(le[0]) + { + case '=': + le[0]='\0'; + val=le+1; + le++; + break; + case '\r': + case '\n': + le[0]='\0'; + le++; + for( ; (le[0]=='\r' || le[0]=='\n') ; le++); + if (!strcmp(ln,"default-character-set") && val && val[0]) + { + create->table_charset=get_charset_by_name(val, MYF(0)); + } + goto cnt; + break; + } + } +cnt: + ln=le; + } + } + my_close(file,MYF(0)); + } + return 0; +} + /* db-name is already validated when we come here */ -int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) +int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) { char path[FN_REFLEN+16]; MY_DIR *dirp; long result=1; int error = 0; + uint create_options = create_info ? create_info->options : 0; + DBUG_ENTER("mysql_create_db"); - + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); // do not create database if another thread is holding read lock @@ -73,6 +167,12 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) } } + strcat(path,"/"); + unpack_dirname(path,path); + strcat(path,MY_DB_OPT_FILE); + if ((error=write_db_opt(thd,db,create_info,path))) + goto exit; + if (!silent) { if (!thd->query) @@ -104,7 +204,81 @@ exit2: DBUG_RETURN(error); } -const char *del_exts[]= {".frm", ".BAK", ".TMD", NullS}; + +/* db-name is already validated when we come here */ + +int mysql_alter_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent) +{ + char path[FN_REFLEN+16]; + MY_DIR *dirp; + long result=1; + int error = 0; + DBUG_ENTER("mysql_create_db"); + register File file; + uint create_options = create_info ? create_info->options : 0; + + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); + + // do not alter database if another thread is holding read lock + if (wait_if_global_read_lock(thd,0)) + { + error= -1; + goto exit2; + } + + /* Check directory */ + (void)sprintf(path,"%s/%s", mysql_data_home, db); + strcat(path,"/"); + unpack_dirname(path,path); // Convert if not unix + strcat(path,MY_DB_OPT_FILE); + if ((error=write_db_opt(thd,db,create_info,path))) + goto exit; + + /* + Change options if current + database is being altered + */ + if (thd->db && !strcmp(thd->db,db)) + { + thd->db_charset= create_info ? create_info->table_charset : NULL; + } + + if (!silent) + { + if (!thd->query) + { + thd->query = path; + thd->query_length = (uint) (strxmov(path,"alter database ", db, NullS)- + path); + } + { + mysql_update_log.write(thd,thd->query, thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query); + mysql_bin_log.write(&qinfo); + } + } + if (thd->query == path) + { + thd->query = 0; // just in case + thd->query_length = 0; + } + send_ok(&thd->net, result); + } + +exit: + start_waiting_global_read_lock(thd); +exit2: + VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + DBUG_RETURN(error); +} + + + + + +const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS}; static TYPELIB deletable_extentions= {array_elements(del_exts)-1,"del_exts", del_exts}; @@ -332,6 +506,8 @@ bool mysql_change_db(THD *thd,const char *name) char *dbname=my_strdup((char*) name,MYF(MY_WME)); char path[FN_REFLEN]; uint db_access; + HA_CREATE_INFO create; + DBUG_ENTER("mysql_change_db"); if (!dbname || !(db_length=strip_sp(dbname))) @@ -382,5 +558,102 @@ bool mysql_change_db(THD *thd,const char *name) thd->db=dbname; thd->db_length=db_length; thd->db_access=db_access; + + strcat(path,"/"); + unpack_dirname(path,path); + strcat(path,MY_DB_OPT_FILE); + bzero(&create,sizeof(create)); + load_db_opt(thd,name,&create,path); + thd->db_charset=create.table_charset; + + DBUG_RETURN(0); +} + + +int mysqld_show_create_db(THD *thd,const char *name) +{ + int length, db_length; + char *dbname=my_strdup((char*) name,MYF(MY_WME)); + char path[FN_REFLEN]; + uint db_access; + HA_CREATE_INFO create; + CONVERT *convert=thd->convert_set; + + DBUG_ENTER("mysql_show_create_db"); + + if (!dbname || !(db_length=strip_sp(dbname))) + { + x_free(dbname); /* purecov: inspected */ + send_error(&thd->net,ER_NO_DB_ERROR); /* purecov: inspected */ + DBUG_RETURN(1); /* purecov: inspected */ + } + + if ((db_length > NAME_LEN) || check_db_name(dbname)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, dbname); + x_free(dbname); + DBUG_RETURN(1); + } + + if (test_all_bits(thd->master_access,DB_ACLS)) + db_access=DB_ACLS; + else + db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, + thd->priv_user,dbname) | + thd->master_access); + if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) + { + net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, + thd->priv_user, + thd->host_or_ip, + dbname); + mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), + thd->priv_user, + thd->host_or_ip, + dbname); + my_free(dbname,MYF(0)); + DBUG_RETURN(1); + } + + (void) sprintf(path,"%s/%s",mysql_data_home,dbname); + length=unpack_dirname(path,path); // Convert if not unix + if (length && path[length-1] == FN_LIBCHAR) + path[length-1]=0; // remove ending '\' + if (access(path,F_OK)) + { + net_printf(&thd->net,ER_BAD_DB_ERROR,dbname); + my_free(dbname,MYF(0)); + DBUG_RETURN(1); + } + + strcat(path,"/"); + unpack_dirname(path,path); + strcat(path,MY_DB_OPT_FILE); + bzero(&create,sizeof(create)); + load_db_opt(thd,name,&create,path); + + List<Item> field_list; + field_list.push_back(new Item_empty_string("Database",NAME_LEN)); + field_list.push_back(new Item_empty_string("Create Database",1024)); + + if (send_fields(thd,field_list,1)) + DBUG_RETURN(1); + + String *packet = &thd->packet; + packet->length(0); + net_store_data(packet, convert, name); + sprintf(path, "CREATE DATABASE %s", name); + if (create.table_charset) + { + strcat(path," DEFAULT CHARACTER SET "); + strcat(path,create.table_charset->name); + } + net_store_data(packet, convert, path); + + if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) + DBUG_RETURN(1); + + send_eof(&thd->net); + DBUG_RETURN(0); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 1b7b181a26f..e65dfc8935f 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; - if (cond && cond->fix_fields(thd,tables)) + if (cond && cond->fix_fields(thd, tables, &cond)) return -1; if (keyname) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 008ef44d83a..9ae5cdeeb15 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -525,7 +525,19 @@ int yylex(void *arg) yylval->lex_str=get_token(lex,length); if (lex->convert_set) lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); - return(IDENT); + + /* + Note: "SELECT _bla AS 'alias'" + _bla should be considered as a IDENT if charset haven't been found. + So we don't use MYF(MY_WME) with get_charset_by_name to avoid + producing an error. + */ + + if ((yylval->lex_str.str[0]=='_') && + (lex->charset=get_charset_by_name(yylval->lex_str.str+1,MYF(0)))) + return(UNDERSCORE_CHARSET); + else + return(IDENT); case STATE_IDENT_SEP: // Found ident and now '.' lex->next_state=STATE_IDENT_START;// Next is an ident (not a keyword) @@ -930,8 +942,8 @@ void st_select_lex::init_select() interval_list.empty(); use_index.empty(); ftfunc_list.empty(); - linkage=UNSPECIFIED_TYPE; - depended= 0; + linkage= UNSPECIFIED_TYPE; + depended= having_fix_field= 0; } /* diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ca824b3eab8..af80b175cd3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -42,9 +42,11 @@ enum enum_sql_command { SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, + SQLCOM_SHOW_CREATE_DB, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, - SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, + SQLCOM_GRANT, + SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, @@ -234,11 +236,12 @@ private: bool create_total_list_n_last_return(THD *thd, st_lex *lex, TABLE_LIST ***result); }; -typedef struct st_select_lex_unit SELECT_LEX_UNIT; +typedef class st_select_lex_unit SELECT_LEX_UNIT; /* SELECT_LEX - store information of parsed SELECT_LEX statment */ +class JOIN; class st_select_lex: public st_select_lex_node { public: char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */ @@ -250,10 +253,14 @@ public: List<String> interval_list, use_index, *use_index_ptr, ignore_index, *ignore_index_ptr; List<Item_func_match> ftfunc_list; + JOIN *join; /* after JOIN::prepare it is pointer to corresponding JOIN */ uint in_sum_expr; bool create_refs, braces, /* SELECT ... UNION (SELECT ... ) <- this braces */ - depended; /* depended from outer select subselect */ + depended, /* depended from outer select subselect */ + /* TRUE when having fix field called in processing of this SELECT */ + having_fix_field; + void init_query(); void init_select(); st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } @@ -277,7 +284,7 @@ public: friend void mysql_init_query(THD *thd); }; -typedef struct st_select_lex SELECT_LEX; +typedef class st_select_lex SELECT_LEX; class Set_option :public Sql_alloc { public: diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 67390c7921d..5a3fbe3236a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2310,7 +2310,7 @@ mysql_execute_command(void) } if (check_access(thd,CREATE_ACL,lex->name,0,1)) break; - res=mysql_create_db(thd,lex->name,lex->create_info.options,0); + res=mysql_create_db(thd,lex->name,&lex->create_info,0); break; } case SQLCOM_DROP_DB: @@ -2330,6 +2330,40 @@ mysql_execute_command(void) res=mysql_rm_db(thd,lex->name,lex->drop_if_exists,0); break; } + case SQLCOM_ALTER_DB: + { + if (!strip_sp(lex->name) || check_db_name(lex->name)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + break; + } + if (check_access(thd,ALTER_ACL,lex->name,0,1)) + break; + if (thd->locked_tables || thd->active_transaction()) + { + send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + goto error; + } + res=mysql_alter_db(thd,lex->name,&lex->create_info,0); + break; + } + case SQLCOM_SHOW_CREATE_DB: + { + if (!strip_sp(lex->name) || check_db_name(lex->name)) + { + net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); + break; + } + if (check_access(thd,DROP_ACL,lex->name,0,1)) + break; + if (thd->locked_tables || thd->active_transaction()) + { + send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION); + goto error; + } + res=mysqld_show_create_db(thd,lex->name); + break; + } case SQLCOM_CREATE_FUNCTION: if (check_access(thd,INSERT_ACL,"mysql",0,1)) break; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d5896901935..d41aca21fb8 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -448,7 +448,7 @@ static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list, static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, List<Item> &values, COND *conds, ORDER *order, ORDER *group, - Item *having,thr_lock_type lock_type) + Item *having, thr_lock_type lock_type) { TABLE *table; bool hidden_group_fields; @@ -470,7 +470,7 @@ static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables, { thd->where="having clause"; thd->allow_sum_func=1; - if (having->fix_fields(thd,tables) || thd->fatal_error) + if (having->fix_fields(thd, tables, &having) || thd->fatal_error) DBUG_RETURN(1); if (having->with_sum_func) having->split_sum_func(all_fields); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4a2a792bc75..b39779141b6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -211,6 +211,7 @@ JOIN::prepare(TABLE_LIST *tables_init, proc_param= proc_param_init; tables_list= tables_init; select_lex= select; + select->join= this; union_part= (unit->first_select()->next_select() != 0); /* Check that all tables, fields, conds and order are ok */ @@ -227,10 +228,9 @@ JOIN::prepare(TABLE_LIST *tables_init, { thd->where="having clause"; thd->allow_sum_func=1; - bool having_fix_field_store= thd->having_fix_field; - thd->having_fix_field= 1; - bool having_fix_rc= having->fix_fields(thd,tables_list); - thd->having_fix_field= having_fix_field_store; + select_lex->having_fix_field= 1; + bool having_fix_rc= having->fix_fields(thd, tables_list, &having); + select_lex->having_fix_field= 0; if (having_fix_rc || thd->fatal_error) DBUG_RETURN(-1); /* purecov: inspected */ if (having->with_sum_func) @@ -349,7 +349,7 @@ JOIN::optimize() } else if ((conds=new Item_cond_and(conds,having))) { - conds->fix_fields(thd, tables_list); + conds->fix_fields(thd, tables_list, &conds); conds->change_ref_to_fields(thd, tables_list); having= 0; } @@ -612,6 +612,15 @@ JOIN::reinit() if (setup_tables(tables_list)) DBUG_RETURN(1); + + // Reset of sum functions + first_record= 0; + if (sum_funcs) + { + Item_sum *func, **func_ptr= sum_funcs; + while ((func= *(func_ptr++))) + func->null_value= 1; + } DBUG_RETURN(0); } @@ -966,6 +975,21 @@ JOIN::cleanup(THD *thd) delete select; delete_dynamic(&keyuse); delete procedure; + for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); + unit != 0; + unit= unit->next_unit()) + for (SELECT_LEX *sl= unit->first_select(); + sl != 0; + sl= sl->next_select()) + { + if (sl->join) + { + int err= sl->join->cleanup(thd); + if (err) + error= err; + sl->join= 0; + } + } return error; } @@ -3381,7 +3405,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value) 21)))) { cond=new_cond; - cond->fix_fields(thd,0); + cond->fix_fields(thd, 0, &cond); } thd->insert_id(0); // Clear for next request } @@ -3395,7 +3419,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value) if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2)))) { cond=new_cond; - cond->fix_fields(thd,0); + cond->fix_fields(thd, 0, &cond); } } } @@ -3523,7 +3547,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case STRING_RESULT: if (item_sum->max_length > 255) return new Field_blob(item_sum->max_length,maybe_null, - item->name,table,item->binary); + item->name,table,item->binary,default_charset_info); return new Field_string(item_sum->max_length,maybe_null, item->name,table,item->binary,default_charset_info); } @@ -3576,10 +3600,12 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case STRING_RESULT: if (item->max_length > 255) new_field= new Field_blob(item->max_length,maybe_null, - item->name,table,item->binary); + item->name,table,item->binary, + item->str_value.charset()); else new_field= new Field_string(item->max_length,maybe_null, - item->name,table,item->binary,default_charset_info); + item->name,table,item->binary, + item->str_value.charset()); break; } if (copy_func) @@ -4103,7 +4129,9 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, { Field *field=keyinfo->key_part[i].field; seg->flag= 0; - seg->language= MY_CHARSET_CURRENT; + seg->language= field->binary() ? MY_CHARSET_CURRENT : + ((Field_str*)field)->charset()->number; + seg->length= keyinfo->key_part[i].length; seg->start= keyinfo->key_part[i].offset; if (field->flags & BLOB_FLAG) @@ -6428,7 +6456,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields, return 0; } order->in_field_list=0; - if ((*order->item)->fix_fields(thd,tables) || thd->fatal_error) + if ((*order->item)->fix_fields(thd, tables, order->item) || thd->fatal_error) return 1; // Wrong field all_fields.push_front(*order->item); // Add new field to field list order->item=(Item**) all_fields.head_ref(); @@ -6526,7 +6554,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields, else { thd->where="procedure list"; - if ((*new_field->item)->fix_fields(thd,tables)) + if ((*new_field->item)->fix_fields(thd, tables, new_field->item)) DBUG_RETURN(1); /* purecov: inspected */ thd->where=0; all_fields.push_front(*new_field->item); @@ -7091,7 +7119,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) Here we pass 0 as the first argument to fix_fields that don't need to do any stack checking (This is already done in the initial fix_fields). */ - cond->fix_fields((THD *) 0,(TABLE_LIST *) 0); + cond->fix_fields((THD *) 0,(TABLE_LIST *) 0, (Item**)&cond); if (join_tab->select) { error=(int) cond->add(join_tab->select->cond); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 08234e96c98..ffd78fddaad 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1158,6 +1158,12 @@ store_create_info(THD *thd, TABLE *table, String *packet) char buff[128]; char* p; + if (table->table_charset) + { + packet->append(" CHARSET="); + packet->append(table->table_charset->name); + } + if (table->min_rows) { packet->append(" MIN_ROWS="); @@ -1389,7 +1395,7 @@ int mysqld_show_charsets(THD *thd, const char *wild) net_store_data(&packet2,(uint32) cs->mbmaxlen); if (my_net_write(&thd->net, (char*) packet2.ptr(),packet2.length())) - goto err; /* purecov: inspected */ + goto err; } } send_eof(&thd->net); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 04069e1081e..f06713c836e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -375,6 +375,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, sql_field->offset= pos; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) auto_increment++; + if(!sql_field->charset) + sql_field->charset = create_info->table_charset ? + create_info->table_charset : + thd->db_charset? thd->db_charset : + default_charset_info; pos+=sql_field->pack_length; } if (auto_increment > 1) @@ -1648,6 +1653,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, create_info->max_rows=table->max_rows; if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH)) create_info->avg_row_length=table->avg_row_length; + if (!(used_fields & HA_CREATE_USED_CHARSET)) + create_info->table_charset=table->table_charset; table->file->update_create_info(create_info); if ((create_info->table_options & diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d140cd4dcdd..160bc253dc9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -162,6 +162,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CACHE_SYM %token CASCADE %token CAST_SYM +%token CHARSET %token CHECKSUM_SYM %token CHECK_SYM %token CIPHER @@ -333,6 +334,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token UDF_SONAME_SYM %token UDF_SYM %token UNCOMMITTED_SYM +%token UNDERSCORE_CHARSET %token UNION_SYM %token UNIQUE_SYM %token USAGE @@ -524,7 +526,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <lex_str> IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME - ULONGLONG_NUM field_ident select_alias ident ident_or_text + ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET %type <lex_str_ptr> opt_table_alias @@ -554,7 +556,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); literal text_literal insert_ident order_ident simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr table_wild opt_pad no_in_expr expr_expr simple_expr no_and_expr - using_list param_marker subselect subselect_init + using_list param_marker singleval_subselect singleval_subselect_init + exists_subselect exists_subselect_init %type <item_list> expr_list udf_expr_list when_list ident_list ident_list_arg @@ -767,7 +770,7 @@ create: bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.options=$2 | $4; lex->create_info.db_type= default_table_type; - lex->create_info.table_charset=default_charset_info; + lex->create_info.table_charset=NULL; } create2 @@ -795,6 +798,7 @@ create: lex->sql_command=SQLCOM_CREATE_DB; lex->name=$4.str; lex->create_info.options=$3; + lex->create_info.table_charset=lex->charset; } | CREATE udf_func_type UDF_SYM ident { @@ -881,6 +885,11 @@ create_table_option: table_list->next=0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } + | CHARSET EQ charset_or_nocharset + { + Lex->create_info.table_charset=Lex->charset; + Lex->create_info.used_fields|= HA_CREATE_USED_CHARSET; + } | INSERT_METHOD EQ merge_insert_types { Lex->create_info.merge_insert_method= $3; Lex->create_info.used_fields|= HA_CREATE_USED_INSERT_METHOD;} | DATA_SYM DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.data_file_name= $4.str; } | INDEX DIRECTORY_SYM EQ TEXT_STRING { Lex->create_info.index_file_name= $4.str; }; @@ -965,7 +974,7 @@ field_spec: LEX *lex=Lex; lex->length=lex->dec=0; lex->type=0; lex->interval=0; lex->default_value=lex->comment=0; - lex->charset=default_charset_info; + lex->charset=NULL; } type opt_attribute { @@ -1115,32 +1124,28 @@ attribute: | UNIQUE_SYM KEY_SYM { Lex->type|= UNIQUE_KEY_FLAG; } | COMMENT_SYM text_literal { Lex->comment= $2; }; -opt_binary: - /* empty */ { Lex->charset=default_charset_info; } - | BINARY { Lex->type|=BINARY_FLAG; Lex->charset=default_charset_info; } - | CHAR_SYM SET ident +charset: + ident + { + if (!(Lex->charset=get_charset_by_name($1.str,MYF(0)))) { - CHARSET_INFO *cs=get_charset_by_name($3.str,MYF(MY_WME)); - if (!cs) - { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$3); - YYABORT; - } - Lex->charset=cs; - }; + net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$1); + YYABORT; + } + }; + +charset_or_nocharset: + charset + | DEFAULT {Lex->charset=NULL; } + +opt_binary: + /* empty */ { Lex->charset=NULL; } + | BINARY { Lex->type|=BINARY_FLAG; Lex->charset=NULL; } + | CHAR_SYM SET charset {/* charset is already in Lex->charset */} ; default_charset: - /* empty */ { Lex->charset-default_charset_info; } - | DEFAULT CHAR_SYM SET ident - { - CHARSET_INFO *cs=get_charset_by_name($4.str,MYF(MY_WME)); - if (!cs) - { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$4); - YYABORT; - } - Lex->charset=cs; - }; + /* empty */ { Lex->charset=NULL; } + | DEFAULT CHAR_SYM SET charset_or_nocharset ; references: REFERENCES table_ident @@ -1259,12 +1264,21 @@ alter: bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= DB_TYPE_DEFAULT; lex->create_info.row_type= ROW_TYPE_NOT_USED; - lex->create_info.table_charset=default_charset_info; + lex->create_info.table_charset=NULL; lex->alter_keys_onoff=LEAVE_AS_IS; lex->simple_alter=1; } alter_list; - + + | ALTER DATABASE ident default_charset + { + LEX *lex=Lex; + lex->sql_command=SQLCOM_ALTER_DB; + lex->name=$3.str; + lex->create_info.table_charset=lex->charset; + } + + alter_list: | alter_list_item | alter_list ',' alter_list_item; @@ -1745,7 +1759,8 @@ simple_expr: | NOT expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); } | '(' expr ')' { $$= $2; } - | subselect { $$= $1; } + | EXISTS exists_subselect { $$= $2; } + | singleval_subselect { $$= $1; } | '{' ident expr '}' { $$= $3; } | MATCH ident_list_arg AGAINST '(' expr ')' { Select->ftfunc_list.push_back((Item_func_match *) @@ -1758,16 +1773,8 @@ simple_expr: | CASE_SYM opt_expr WHEN_SYM when_list opt_else END { $$= new Item_func_case(* $4, $2, $5 ); } | CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5); } - | CONVERT_SYM '(' expr USING IDENT ')' - { - CHARSET_INFO *cs=get_charset_by_name($5.str,MYF(MY_WME)); - if (!cs) - { - net_printf(¤t_thd->net,ER_UNKNOWN_CHARACTER_SET,$5); - YYABORT; - } - $$= new Item_func_conv_charset($3,cs); - } + | CONVERT_SYM '(' expr USING charset ')' + { $$= new Item_func_conv_charset($3,Lex->charset); } | CONVERT_SYM '(' expr ',' expr ',' expr ')' { $$= new Item_func_conv_charset3($3,$7,$5); @@ -1786,6 +1793,8 @@ simple_expr: { $$= new Item_func_atan($3,$5); } | CHAR_SYM '(' expr_list ')' { $$= new Item_func_char(*$3); } + | CHARSET '(' expr ')' + { $$= new Item_func_charset($3); } | COALESCE '(' expr_list ')' { $$= new Item_func_coalesce(* $3); } | CONCAT '(' expr_list ')' @@ -2842,6 +2851,11 @@ show_param: lex->grant_user=$3; lex->grant_user->password.str=NullS; } + | CREATE DATABASE ident + { + Lex->sql_command=SQLCOM_SHOW_CREATE_DB; + Lex->name=$3.str; + } | CREATE TABLE_SYM table_ident { Lex->sql_command = SQLCOM_SHOW_CREATE; @@ -2972,7 +2986,7 @@ kill: KILL_SYM expr { LEX *lex=Lex; - if ($2->fix_fields(lex->thd,0)) + if ($2->fix_fields(lex->thd, 0, &$2)) { send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY); YYABORT; @@ -3075,6 +3089,7 @@ opt_ignore_lines: text_literal: TEXT_STRING { $$ = new Item_string($1.str,$1.length,default_charset_info); } + | UNDERSCORE_CHARSET TEXT_STRING { $$ = new Item_string($2.str,$2.length,Lex->charset); } | text_literal TEXT_STRING { ((Item_string*) $1)->append($2.str,$2.length); }; @@ -3467,7 +3482,8 @@ option_value: | '@' ident_or_text equal expr { Item_func_set_user_var *item = new Item_func_set_user_var($2,$4); - if (item->fix_fields(current_thd,0) || item->update()) + if (item->fix_fields(current_thd, 0, (Item**) &item) || + item->update()) { send_error(¤t_thd->net, ER_SET_CONSTANTS_ONLY); YYABORT; @@ -3499,7 +3515,7 @@ option_value: { THD *thd=current_thd; Item *item= $3; - if (item->fix_fields(current_thd,0)) + if (item->fix_fields(current_thd, 0, &item)) { send_error(&thd->net, ER_SET_CONSTANTS_ONLY); YYABORT; @@ -3973,17 +3989,30 @@ union_option: /* empty */ {} | ALL {Lex->union_option=1;}; -subselect: - subselect_start subselect_init +singleval_subselect: + subselect_start singleval_subselect_init + subselect_end + { + $$= $2; + }; + +singleval_subselect_init: + select_init + { + $$= new Item_singleval_subselect(current_thd, Lex->select); + }; + +exists_subselect: + subselect_start exists_subselect_init subselect_end { $$= $2; }; -subselect_init: +exists_subselect_init: select_init { - $$= new Item_subselect(current_thd, Lex->select); + $$= new Item_exists_subselect(current_thd, Lex->select); }; subselect_start: diff --git a/sql/table.cc b/sql/table.cc index 201b67032bf..8a7604687e7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -118,7 +118,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, outparam->raid_chunks= head[42]; outparam->raid_chunksize= uint4korr(head+43); if (!(outparam->table_charset=get_charset((uint) head[38],MYF(0)))) - outparam->table_charset=default_charset_info; + outparam->table_charset=NULL; // QQ display error message? null_field_first=1; } outparam->db_record_offset=1; @@ -358,7 +358,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, uint comment_length=uint2korr(strpos+13); field_type=(enum_field_types) (uint) strpos[11]; if (!(charset=get_charset((uint) strpos[12], MYF(0)))) - charset=outparam->table_charset; + charset=outparam->table_charset?outparam->table_charset:default_charset_info; if (!comment_length) { comment.str= (char*) ""; @@ -375,7 +375,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, { /* old frm file */ field_type= (enum_field_types) f_packtype(pack_flag); - charset=outparam->table_charset; + charset=outparam->table_charset?outparam->table_charset:default_charset_info; bzero((char*) &comment, sizeof(comment)); } *field_ptr=reg_field= @@ -1041,7 +1041,7 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo, int2store(fileinfo+30,create_info->table_options); fileinfo[32]=0; // No filename anymore int4store(fileinfo+34,create_info->avg_row_length); - fileinfo[38]= create_info->table_charset->number; + fileinfo[38]= create_info->table_charset?create_info->table_charset->number:0; fileinfo[40]= (uchar) create_info->row_type; fileinfo[41]= (uchar) create_info->raid_type; fileinfo[42]= (uchar) create_info->raid_chunks; @@ -1072,6 +1072,7 @@ void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) create_info->raid_type=table->raid_type; create_info->raid_chunks=table->raid_chunks; create_info->raid_chunksize=table->raid_chunksize; + create_info->table_charset=table->table_charset; DBUG_VOID_RETURN; } @@ -1094,7 +1095,7 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr) { Field *field=table->field[fieldnr]; char buff[MAX_FIELD_WIDTH]; - String str(buff,sizeof(buff),table->table_charset); + String str(buff,sizeof(buff),default_charset_info); field->val_str(&str,&str); uint length=str.length(); if (!length) diff --git a/sql/unireg.cc b/sql/unireg.cc index 863f71d1cce..f2d8d6532a9 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -459,8 +459,7 @@ static bool pack_fields(File file,List<create_field> &create_fields) int2store(buff+8,field->unireg_check); buff[10]= (uchar) field->interval_id; buff[11]= (uchar) field->sql_type; - buff[12]= (uchar) (field->charset ? field->charset->number : - default_charset_info->number); + buff[12]= (uchar) field->charset->number; int2store(buff+13, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); |