Commit e5125d3e authored by hf@deer.(none)'s avatar hf@deer.(none)

Fix to perform correctly with charsets in embedded server

parent 533b5dcc
...@@ -591,6 +591,32 @@ err: ...@@ -591,6 +591,32 @@ err:
C_MODE_END C_MODE_END
static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
uint32 dummy32;
uint dummy_err;
char *result;
/* 'tocs' is set 0 when client issues SET character_set_results=NULL */
if (tocs && String::needs_conversion(0, fromcs, tocs, &dummy32))
{
uint new_len= (tocs->mbmaxlen * length) / fromcs->mbminlen + 1;
result= (char *)alloc_root(root, new_len);
length= copy_and_convert(result, new_len,
tocs, from, length, fromcs, &dummy_err);
}
else
{
result= (char *)alloc_root(root, length + 1);
memcpy(result, from, length);
}
result[length]= 0;
return result;
}
bool Protocol::send_fields(List<Item> *list, uint flag) bool Protocol::send_fields(List<Item> *list, uint flag)
{ {
List_iterator_fast<Item> it(*list); List_iterator_fast<Item> it(*list);
...@@ -598,6 +624,8 @@ bool Protocol::send_fields(List<Item> *list, uint flag) ...@@ -598,6 +624,8 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
MYSQL_FIELD *client_field; MYSQL_FIELD *client_field;
MYSQL *mysql= thd->mysql; MYSQL *mysql= thd->mysql;
MEM_ROOT *field_alloc; MEM_ROOT *field_alloc;
CHARSET_INFO *thd_cs= thd->variables.character_set_results;
CHARSET_INFO *cs= system_charset_info;
DBUG_ENTER("send_fields"); DBUG_ENTER("send_fields");
...@@ -616,12 +644,29 @@ bool Protocol::send_fields(List<Item> *list, uint flag) ...@@ -616,12 +644,29 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
Send_field server_field; Send_field server_field;
item->make_field(&server_field); item->make_field(&server_field);
client_field->db= strdup_root(field_alloc, server_field.db_name); client_field->db= dup_str_aux(field_alloc, server_field.db_name,
client_field->table= strdup_root(field_alloc, server_field.table_name); strlen(server_field.db_name), cs, thd_cs);
client_field->name= strdup_root(field_alloc, server_field.col_name); client_field->table= dup_str_aux(field_alloc, server_field.table_name,
client_field->org_table= strdup_root(field_alloc, server_field.org_table_name); strlen(server_field.table_name), cs, thd_cs);
client_field->org_name= strdup_root(field_alloc, server_field.org_col_name); client_field->name= dup_str_aux(field_alloc, server_field.col_name,
strlen(server_field.col_name), cs, thd_cs);
client_field->org_table= dup_str_aux(field_alloc, server_field.org_table_name,
strlen(server_field.org_table_name), cs, thd_cs);
client_field->org_name= dup_str_aux(field_alloc, server_field.org_col_name,
strlen(server_field.org_col_name), cs, thd_cs);
if (item->collation.collation == &my_charset_bin || thd_cs == NULL)
{
/* No conversion */
client_field->charsetnr= server_field.charsetnr;
client_field->length= server_field.length; client_field->length= server_field.length;
}
else
{
/* With conversion */
client_field->charsetnr= thd_cs->number;
uint char_len= server_field.length / item->collation.collation->mbmaxlen;
client_field->length= char_len * thd_cs->mbmaxlen;
}
client_field->type= server_field.type; client_field->type= server_field.type;
client_field->flags= server_field.flags; client_field->flags= server_field.flags;
client_field->decimals= server_field.decimals; client_field->decimals= server_field.decimals;
...@@ -630,9 +675,8 @@ bool Protocol::send_fields(List<Item> *list, uint flag) ...@@ -630,9 +675,8 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
client_field->name_length= strlen(client_field->name); client_field->name_length= strlen(client_field->name);
client_field->org_name_length= strlen(client_field->org_name); client_field->org_name_length= strlen(client_field->org_name);
client_field->org_table_length= strlen(client_field->org_table); client_field->org_table_length= strlen(client_field->org_table);
client_field->charsetnr= server_field.charsetnr;
client_field->catalog= strdup_root(field_alloc, "def"); client_field->catalog= dup_str_aux(field_alloc, "def", 3, cs, thd_cs);
client_field->catalog_length= 3; client_field->catalog_length= 3;
if (INTERNAL_NUM_FIELD(client_field)) if (INTERNAL_NUM_FIELD(client_field))
...@@ -804,21 +848,3 @@ bool Protocol::net_store_data(const char *from, uint length) ...@@ -804,21 +848,3 @@ bool Protocol::net_store_data(const char *from, uint length)
return false; return false;
} }
#if 0
/* The same as Protocol::net_store_data but does the converstion
*/
bool Protocol::convert_str(const char *from, uint length)
{
if (!(*next_field=alloc_root(alloc, length + 1)))
return true;
convert->store_dest(*next_field, from, length);
(*next_field)[length]= 0;
if (next_mysql_field->max_length < length)
next_mysql_field->max_length=length;
++next_field;
++next_mysql_field;
return false;
}
#endif
SET CHARACTER SET koi8r;
DROP TABLE IF EXISTS , t1, t2;
SET CHARACTER SET koi8r;
CREATE TABLE t1 (a CHAR(10) CHARACTER SET cp1251) SELECT _koi8r'' AS a;
CREATE TABLE t2 (a CHAR(10) CHARACTER SET utf8);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(10) character set cp1251 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT a FROM t1;
a
SELECT HEX(a) FROM t1;
HEX(a)
EFF0EEE1E0
INSERT t2 SELECT * FROM t1;
SELECT HEX(a) FROM t2;
HEX(a)
D0BFD180D0BED0B1D0B0
DROP TABLE t1, t2;
CREATE TABLE t1 (description text character set cp1250 NOT NULL);
INSERT INTO t1 (description) VALUES (_latin2'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddde');
SELECT description FROM t1;
description
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddde
DROP TABLE t1;
CREATE TABLE t1 (a TEXT CHARACTER SET cp1251) SELECT _koi8r'' AS a;
CREATE TABLE t2 (a TEXT CHARACTER SET utf8);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` text character set cp1251
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT HEX(a) FROM t1;
HEX(a)
EFF0EEE1E0
INSERT t2 SELECT * FROM t1;
SELECT HEX(a) FROM t2;
HEX(a)
D0BFD180D0BED0B1D0B0
DROP TABLE t1, t2;
CREATE TABLE ``
(
CHAR(32) CHARACTER SET koi8r NOT NULL COMMENT " "
) COMMENT " ";
SHOW TABLES;
Tables_in_test
SHOW CREATE TABLE ;
Table Create Table
CREATE TABLE `` (
`` char(32) character set koi8r NOT NULL default '' COMMENT ' '
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT=' '
SHOW FIELDS FROM ;
Field Type Null Key Default Extra
char(32)
SET CHARACTER SET cp1251;
SHOW TABLES;
Tables_in_test
SHOW CREATE TABLE ;
Table Create Table
CREATE TABLE `` (
`` char(32) character set koi8r NOT NULL default '' COMMENT ' '
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT=' '
SHOW FIELDS FROM ;
Field Type Null Key Default Extra
char(32)
SET CHARACTER SET utf8;
SHOW TABLES;
Tables_in_test
таблица
SHOW CREATE TABLE таблица;
Table Create Table
таблица CREATE TABLE `таблица` (
`поле` char(32) character set koi8r NOT NULL default '' COMMENT 'комментарий поля'
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='комментарий таблицы'
SHOW FIELDS FROM таблица;
Field Type Null Key Default Extra
поле char(32)
SET CHARACTER SET koi8r;
DROP TABLE ;
SET CHARACTER SET default;
SET NAMES UTF8;
CREATE TABLE t1 (t text) DEFAULT CHARSET UTF8;
INSERT INTO t1 (t) VALUES ('x');
SELECT 1 FROM t1 WHERE CONCAT(_latin1'x') = t;
1
1
DROP TABLE t1;
SET CHARACTER SET koi8r;
CREATE DATABASE ;
USE ;
SHOW TABLES;
Tables_in_тест
SHOW TABLES IN ;
Tables_in_тест
SET CHARACTER SET cp1251;
SHOW TABLES;
Tables_in_тест
SHOW TABLES IN ;
Tables_in_тест
SET CHARACTER SET koi8r;
DROP DATABASE ;
SET NAMES koi8r;
SELECT hex('');
hex('тест')
D4C5D3D4
SET character_set_connection=cp1251;
SELECT hex('');
hex('тест')
F2E5F1F2
USE test;
SET NAMES binary;
CREATE TABLE `тест` (`тест` int);
SHOW CREATE TABLE `тест`;
Table Create Table
тест CREATE TABLE `тест` (
`тест` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SET NAMES utf8;
SHOW CREATE TABLE `тест`;
Table Create Table
тест CREATE TABLE `тест` (
`тест` int(11) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE `тест`;
SET NAMES binary;
SET character_set_connection=utf8;
SELECT 'тест' as s;
s
тест
SET NAMES utf8;
SET character_set_connection=binary;
SELECT 'тест' as s;
s
тест
SET NAMES latin1;
CREATE TABLE t1 (`` CHAR(128) DEFAULT '', `1` ENUM('1','2') DEFAULT '2');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`` char(128) default '',
`1` enum('1','2') default '2'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SHOW COLUMNS FROM t1;
Field Type Null Key Default Extra
char(128) YES
1 enum('1','2') YES 2
SET NAMES binary;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`ä` char(128) default 'ä',
`ä1` enum('ä1','ä2') default 'ä2'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SHOW COLUMNS FROM t1;
Field Type Null Key Default Extra
ä char(128) YES ä
ä1 enum('ä1','ä2') YES ä2
DROP TABLE t1;
SET NAMES binary;
CREATE TABLE `good` (a int);
ERROR HY000: Invalid utf8 character string: ''
SET NAMES utf8;
CREATE TABLE `good` (a int);
ERROR HY000: Invalid utf8 character string: '` (a int)'
set names latin1;
create table t1 (a char(10) character set koi8r, b text character set koi8r);
insert into t1 values ('test','test');
insert into t1 values ('','');
Warnings:
Warning 1265 Data truncated for column 'a' at row 1
Warning 1265 Data truncated for column 'b' at row 1
drop table t1;
set names koi8r;
create table t1 (a char(10) character set cp1251);
insert into t1 values (_koi8r'');
select * from t1 where a=_koi8r'';
a
select * from t1 where a=concat(_koi8r'');
ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation '='
select * from t1 where a=_latin1'';
ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '='
drop table t1;
set names latin1;
set names koi8r;
create table t1 (c1 char(10) character set cp1251);
insert into t1 values ('');
select c1 from t1 where c1 between '' and '';
c1
select ifnull(c1,''), ifnull(null,c1) from t1;
ifnull(c1,'ъ') ifnull(null,c1)
select if(1,c1,''), if(0,c1,'') from t1;
if(1,c1,'Ж') if(0,c1,'Ж')
select coalesce('',c1), coalesce(null,c1) from t1;
coalesce('Ж',c1) coalesce(null,c1)
select least(c1,''), greatest(c1,'') from t1;
least(c1,'Ж') greatest(c1,'Ж')
select locate(c1,''), locate('',c1) from t1;
locate(c1,'ъ') locate('ъ',c1)
1 1
select field(c1,''),field('',c1) from t1;
field(c1,'ъ') field('ъ',c1)
1 1
select concat(c1,''), concat('',c1) from t1;
concat(c1,'Ж') concat('Ж',c1)
select concat_ws(c1,'',''), concat_ws('',c1,'') from t1;
concat_ws(c1,'Ж','ъ') concat_ws('Ж',c1,'ъ')
select replace(c1,'',''), replace('',c1,'') from t1;
replace(c1,'ъ','Ж') replace('ъ',c1,'Ж')
select substring_index(c1,'',2) from t1;
substring_index(c1,'ЖЖъъ',2)
select elt(1,c1,''),elt(1,'',c1) from t1;
elt(1,c1,'Ж') elt(1,'Ж',c1)
select make_set(3,c1,''), make_set(3,'',c1) from t1;
make_set(3,c1,'Ж') make_set(3,'Ж',c1)
, ,
select insert(c1,1,2,''),insert('',1,2,c1) from t1;
insert(c1,1,2,'Ж') insert('Ж',1,2,c1)
select trim(c1 from ''),trim('' from c1) from t1;
trim(c1 from 'ъ') trim('ъ' from c1)
select lpad(c1,3,''), lpad('',3,c1) from t1;
lpad(c1,3,'Ж') lpad('Ж',3,c1)
select rpad(c1,3,''), rpad('',3,c1) from t1;
rpad(c1,3,'Ж') rpad('Ж',3,c1)
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -808,7 +808,7 @@ SET NAMES koi8r; ...@@ -808,7 +808,7 @@ SET NAMES koi8r;
CREATE TABLE t1 (a char(1) character set koi8r); CREATE TABLE t1 (a char(1) character set koi8r);
INSERT INTO t1 VALUES (_koi8r''),(_koi8r''); INSERT INTO t1 VALUES (_koi8r''),(_koi8r'');
SELECT a,'',''='' FROM t1; SELECT a,'',''='' FROM t1;
a б 'Б'='б' a ''=''
1 1
1 1
show status like "Qcache_hits"; show status like "Qcache_hits";
...@@ -819,7 +819,7 @@ Variable_name Value ...@@ -819,7 +819,7 @@ Variable_name Value
Qcache_queries_in_cache 1 Qcache_queries_in_cache 1
set collation_connection=koi8r_bin; set collation_connection=koi8r_bin;
SELECT a,'',''='' FROM t1; SELECT a,'',''='' FROM t1;
a б 'Б'='б' a ''=''
0 0
0 0
show status like "Qcache_hits"; show status like "Qcache_hits";
...@@ -830,7 +830,7 @@ Variable_name Value ...@@ -830,7 +830,7 @@ Variable_name Value
Qcache_queries_in_cache 2 Qcache_queries_in_cache 2
set character_set_client=cp1251; set character_set_client=cp1251;
SELECT a,'',''='' FROM t1; SELECT a,'',''='' FROM t1;
a В 'в'='В' a ''=''
0 0
0 0
show status like "Qcache_hits"; show status like "Qcache_hits";
...@@ -841,7 +841,7 @@ Variable_name Value ...@@ -841,7 +841,7 @@ Variable_name Value
Qcache_queries_in_cache 3 Qcache_queries_in_cache 3
set character_set_results=cp1251; set character_set_results=cp1251;
SELECT a,'',''='' FROM t1; SELECT a,'',''='' FROM t1;
a В 'в'='В' a ''=''
0 0
0 0
show status like "Qcache_hits"; show status like "Qcache_hits";
......
...@@ -683,9 +683,7 @@ static void verify_prepare_field(MYSQL_RES *result, ...@@ -683,9 +683,7 @@ static void verify_prepare_field(MYSQL_RES *result,
as utf8. Field length is calculated as number of characters * maximum as utf8. Field length is calculated as number of characters * maximum
number of bytes a character can occupy. number of bytes a character can occupy.
*/ */
#ifndef EMBEDDED_LIBRARY
DIE_UNLESS(field->length == length * cs->mbmaxlen); DIE_UNLESS(field->length == length * cs->mbmaxlen);
#endif
if (def) if (def)
DIE_UNLESS(strcmp(field->def, def) == 0); DIE_UNLESS(strcmp(field->def, def) == 0);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment