summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhf@bisonxp.(none) <>2002-07-09 10:42:24 +0500
committerhf@bisonxp.(none) <>2002-07-09 10:42:24 +0500
commitd8c94e942b35a95611eeee8b9c18291d519f46a1 (patch)
treeb21a32ca85bae8d5e16f2b05a4cee9a8c74df6e1
parentbc7e8b09159ba6cf2554c1e5a735167b3c3d373d (diff)
parent984c84c2347395e5364100a2039b588bab0136f3 (diff)
downloadmariadb-git-d8c94e942b35a95611eeee8b9c18291d519f46a1.tar.gz
Merge abotchkov@work.mysql.com:/home/bk/mysql-4.1
into bisonxp.(none):/home/hf/work/mysql-4.1
-rw-r--r--.bzrignore1
-rw-r--r--BitKeeper/etc/logging_ok3
-rw-r--r--myisam/mi_unique.c35
-rwxr-xr-xmysql-test/create-test-result2
-rw-r--r--mysql-test/r/ctype_many.result1334
-rw-r--r--mysql-test/r/subselect.result19
-rw-r--r--mysql-test/t/ctype_many.test189
-rw-r--r--mysql-test/t/subselect.test7
-rw-r--r--sql-bench/server-cfg.sh176
-rw-r--r--sql/field.cc11
-rw-r--r--sql/field.h11
-rw-r--r--sql/field_conv.cc7
-rw-r--r--sql/handler.h1
-rw-r--r--sql/item.cc65
-rw-r--r--sql/item.h11
-rw-r--r--sql/item_cmpfunc.cc21
-rw-r--r--sql/item_cmpfunc.h18
-rw-r--r--sql/item_func.cc30
-rw-r--r--sql/item_func.h19
-rw-r--r--sql/item_strfunc.cc40
-rw-r--r--sql/item_strfunc.h34
-rw-r--r--sql/item_subselect.cc128
-rw-r--r--sql/item_subselect.h91
-rw-r--r--sql/item_sum.cc13
-rw-r--r--sql/item_sum.h8
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/lex.h1
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/sql_base.cc6
-rw-r--r--sql/sql_class.cc46
-rw-r--r--sql/sql_class.h27
-rw-r--r--sql/sql_db.cc279
-rw-r--r--sql/sql_handler.cc2
-rw-r--r--sql/sql_lex.cc18
-rw-r--r--sql/sql_lex.h15
-rw-r--r--sql/sql_parse.cc36
-rw-r--r--sql/sql_prepare.cc4
-rw-r--r--sql/sql_select.cc56
-rw-r--r--sql/sql_show.cc8
-rw-r--r--sql/sql_table.cc7
-rw-r--r--sql/sql_yacc.yy123
-rw-r--r--sql/table.cc11
-rw-r--r--sql/unireg.cc3
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(&current_thd->net,ER_UNKNOWN_CHARACTER_SET,$3);
- YYABORT;
- }
- Lex->charset=cs;
- };
+ net_printf(&current_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(&current_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(&current_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(&current_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);