diff options
Diffstat (limited to 'sql/protocol.cc')
-rw-r--r-- | sql/protocol.cc | 99 |
1 files changed, 84 insertions, 15 deletions
diff --git a/sql/protocol.cc b/sql/protocol.cc index a74f6084df4..c0e30f8d7ee 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. + Copyright (c) 2008, 2012, Monty Program Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -59,6 +60,65 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length) } +/* + net_store_data() - extended version with character set conversion. + + It is optimized for short strings whose length after + conversion is garanteed to be less than 251, which accupies + exactly one byte to store length. It allows not to use + the "convert" member as a temporary buffer, conversion + is done directly to the "packet" member. + The limit 251 is good enough to optimize send_fields() + because column, table, database names fit into this limit. +*/ + +#ifndef EMBEDDED_LIBRARY +bool Protocol::net_store_data(const uchar *from, size_t length, + CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) +{ + uint dummy_errors; + /* Calculate maxumum possible result length */ + size_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen; + ulong packet_length, new_length; + char *length_pos, *to; + + if (conv_length > 250) + { + /* + For strings with conv_length greater than 250 bytes + we don't know how many bytes we will need to store length: one or two, + because we don't know result length until conversion is done. + For example, when converting from utf8 (mbmaxlen=3) to latin1, + conv_length=300 means that the result length can vary between 100 to 300. + length=100 needs one byte, length=300 needs to bytes. + + Thus conversion directly to "packet" is not worthy. + Let's use "convert" as a temporary buffer. + */ + return (convert->copy((const char*) from, length, from_cs, to_cs, + &dummy_errors) || + net_store_data((const uchar*) convert->ptr(), convert->length())); + } + + packet_length= packet->length(); + new_length= packet_length + conv_length + 1; + + if (new_length > packet->alloced_length() && packet->realloc(new_length)) + return 1; + + length_pos= (char*) packet->ptr() + packet_length; + to= length_pos + 1; + + to+= copy_and_convert(to, conv_length, to_cs, + (const char*) from, length, from_cs, &dummy_errors); + + net_store_length((uchar*) length_pos, to - length_pos - 1); + packet->length((uint) (to - packet->ptr())); + return 0; +} +#endif + + /** Send a error string to client. @@ -145,7 +205,7 @@ net_send_ok(THD *thd, NET *net= &thd->net; uchar buff[MYSQL_ERRMSG_SIZE+10],*pos; bool error= FALSE; - DBUG_ENTER("my_ok"); + DBUG_ENTER("net_send_ok"); if (! net->vio) // hack for re-parsing queries { @@ -431,6 +491,7 @@ static uchar *net_store_length_fast(uchar *packet, uint length) void net_end_statement(THD *thd) { + DBUG_ENTER("net_end_statement"); DBUG_ASSERT(! thd->main_da.is_sent); /* Can not be true, but do not take chances in production. */ @@ -470,6 +531,7 @@ void net_end_statement(THD *thd) } if (!error) thd->main_da.is_sent= TRUE; + DBUG_VOID_RETURN; } @@ -528,7 +590,8 @@ void Protocol::init(THD *thd_arg) void Protocol::end_partial_result_set(THD *thd_arg) { - net_send_eof(thd_arg, thd_arg->server_status, 0 /* no warnings, we're inside SP */); + net_send_eof(thd_arg, thd_arg->server_status, + 0 /* no warnings, we're inside SP */); } @@ -830,10 +893,10 @@ bool Protocol::store_string_aux(const char *from, size_t length, fromcs != &my_charset_bin && tocs != &my_charset_bin) { - uint dummy_errors; - return (convert->copy(from, length, fromcs, tocs, &dummy_errors) || - net_store_data((uchar*) convert->ptr(), convert->length())); + /* Store with conversion */ + return net_store_data((uchar*) from, length, fromcs, tocs); } + /* Store without conversion */ return net_store_data((uchar*) from, length); } @@ -1013,12 +1076,16 @@ bool Protocol_text::store(MYSQL_TIME *tm) #endif char buff[40]; uint length; - length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d", - (int) tm->year, (int) tm->month, - (int) tm->day, (int) tm->hour, - (int) tm->minute, (int) tm->second); + length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d", + (int) tm->year, + (int) tm->month, + (int) tm->day, + (int) tm->hour, + (int) tm->minute, + (int) tm->second)); if (tm->second_part) - length+= sprintf(buff+length, ".%06d", (int) tm->second_part); + length+= my_sprintf(buff+length,(buff+length, ".%06d", + (int)tm->second_part)); return net_store_data((uchar*) buff, length); } @@ -1052,11 +1119,13 @@ bool Protocol_text::store_time(MYSQL_TIME *tm) char buff[40]; uint length; uint day= (tm->year || tm->month) ? 0 : tm->day; - length= sprintf(buff, "%s%02ld:%02d:%02d", tm->neg ? "-" : "", - (long) day*24L+(long) tm->hour, (int) tm->minute, - (int) tm->second); + length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d", + tm->neg ? "-" : "", + (long) day*24L+(long) tm->hour, + (int) tm->minute, + (int) tm->second)); if (tm->second_part) - length+= sprintf(buff+length, ".%06d", (int) tm->second_part); + length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part)); return net_store_data((uchar*) buff, length); } |