summaryrefslogtreecommitdiff
path: root/libmysqld
diff options
context:
space:
mode:
authorunknown <hf@deer.(none)>2004-12-21 10:05:58 +0400
committerunknown <hf@deer.(none)>2004-12-21 10:05:58 +0400
commitfee2e57b675ba2e07bb9833ffbe18996fbf97ccb (patch)
tree5b4be1d54e8bacb1475e40f727a51cf4a942721e /libmysqld
parent4630d406d11a8e7c0e8dc4b8601fc8dd94e8a343 (diff)
downloadmariadb-git-fee2e57b675ba2e07bb9833ffbe18996fbf97ccb.tar.gz
Fix to perform correctly with charsets in embedded server
BitKeeper/deleted/.del-ctype_recoding.result.es~45c6fe567949af: Delete: mysql-test/r/ctype_recoding.result.es BitKeeper/deleted/.del-func_test.result.es~4de135264090aa14: Delete: mysql-test/r/func_test.result.es BitKeeper/deleted/.del-ps_2myisam.result.es~5132bde9c07c41e8: Delete: mysql-test/r/ps_2myisam.result.es BitKeeper/deleted/.del-ps_3innodb.result.es~a3613f0e86132472: Delete: mysql-test/r/ps_3innodb.result.es BitKeeper/deleted/.del-ps_4heap.result.es~956ae2c46b66b6ed: Delete: mysql-test/r/ps_4heap.result.es BitKeeper/deleted/.del-ps_5merge.result.es~6093a834fec21efe: Delete: mysql-test/r/ps_5merge.result.es BitKeeper/deleted/.del-ps_6bdb.result.es~57b94c3756e3d093: Delete: mysql-test/r/ps_6bdb.result.es libmysqld/lib_sql.cc: Charset conversion implemented mysql-test/r/query_cache.result.es: correct test result provided tests/client_test.c: now it works
Diffstat (limited to 'libmysqld')
-rw-r--r--libmysqld/lib_sql.cc78
1 files changed, 52 insertions, 26 deletions
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 8092d87b97c..a9503c644a8 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -591,6 +591,32 @@ err:
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)
{
List_iterator_fast<Item> it(*list);
@@ -598,6 +624,8 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
MYSQL_FIELD *client_field;
MYSQL *mysql= thd->mysql;
MEM_ROOT *field_alloc;
+ CHARSET_INFO *thd_cs= thd->variables.character_set_results;
+ CHARSET_INFO *cs= system_charset_info;
DBUG_ENTER("send_fields");
@@ -616,12 +644,29 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
Send_field server_field;
item->make_field(&server_field);
- client_field->db= strdup_root(field_alloc, server_field.db_name);
- client_field->table= strdup_root(field_alloc, server_field.table_name);
- client_field->name= strdup_root(field_alloc, server_field.col_name);
- client_field->org_table= strdup_root(field_alloc, server_field.org_table_name);
- client_field->org_name= strdup_root(field_alloc, server_field.org_col_name);
- client_field->length= server_field.length;
+ client_field->db= dup_str_aux(field_alloc, server_field.db_name,
+ strlen(server_field.db_name), cs, thd_cs);
+ client_field->table= dup_str_aux(field_alloc, server_field.table_name,
+ strlen(server_field.table_name), cs, thd_cs);
+ 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;
+ }
+ 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->flags= server_field.flags;
client_field->decimals= server_field.decimals;
@@ -630,9 +675,8 @@ bool Protocol::send_fields(List<Item> *list, uint flag)
client_field->name_length= strlen(client_field->name);
client_field->org_name_length= strlen(client_field->org_name);
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;
if (INTERNAL_NUM_FIELD(client_field))
@@ -804,21 +848,3 @@ bool Protocol::net_store_data(const char *from, uint length)
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
-