diff options
Diffstat (limited to 'sql/protocol.cc')
-rw-r--r-- | sql/protocol.cc | 115 |
1 files changed, 73 insertions, 42 deletions
diff --git a/sql/protocol.cc b/sql/protocol.cc index c5937cee807..606bf4ccb00 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. + Copyright (c) 2011 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 @@ -577,6 +578,56 @@ bool Protocol::send_error(uint sql_errno, const char *err_msg, } +/** + Send a progress report to the client + + What we send is: + header (255,255,255,1) + stage, max_stage as on byte integers + percentage withing the stage as percentage*1000 + (that is, ratio*100000) as a 3 byte integer + proc_info as a string +*/ + +const uchar progress_header[2]= {(uchar) 255, (uchar) 255 }; + +void net_send_progress_packet(THD *thd) +{ + uchar buff[200], *pos; + const char *proc_info= thd->proc_info ? thd->proc_info : ""; + uint length= strlen(proc_info); + ulonglong progress; + DBUG_ENTER("net_send_progress_packet"); + + if (unlikely(!thd->net.vio)) + DBUG_VOID_RETURN; // Socket is closed + + pos= buff; + /* + Store number of strings first. This allows us to later expand the + progress indicator if needed. + */ + *pos++= (uchar) 1; // Number of strings + *pos++= (uchar) thd->progress.stage + 1; + /* + We have the max() here to avoid problems if max_stage is not set, + which may happen during automatic repair of table + */ + *pos++= (uchar) max(thd->progress.max_stage, thd->progress.stage + 1); + progress= 0; + if (thd->progress.max_counter) + progress= 100000ULL * thd->progress.counter / thd->progress.max_counter; + int3store(pos, progress); // Between 0 & 100000 + pos+= 3; + pos= net_store_data(pos, (const uchar*) proc_info, + min(length, sizeof(buff)-7)); + net_write_command(&thd->net, (uchar) 255, progress_header, + sizeof(progress_header), (uchar*) buff, + (uint) (pos - buff)); + DBUG_VOID_RETURN; +} + + /**************************************************************************** Functions used by the protocol functions (like net_send_ok) to store strings and numbers in the header result packet. @@ -679,7 +730,7 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags) Protocol_text prot(thd); String *local_packet= prot.storage_packet(); CHARSET_INFO *thd_charset= thd->variables.character_set_results; - DBUG_ENTER("send_result_set_metadata"); + DBUG_ENTER("Protocol::send_result_set_metadata"); if (flags & SEND_NUM_ROWS) { // Packet with number of elements @@ -694,6 +745,9 @@ bool Protocol::send_result_set_metadata(List<Item> *list, uint flags) uint count= 0; #endif + /* We have to reallocate it here as a stored procedure may have reset it */ + (void) local_packet->alloc(thd->variables.net_buffer_length); + while ((item=it++)) { char *pos; @@ -1121,13 +1175,7 @@ bool Protocol_text::store(Field *field) } -/** - @todo - Second_part format ("%06") needs to change when - we support 0-6 decimals for time. -*/ - -bool Protocol_text::store(MYSQL_TIME *tm) +bool Protocol_text::store(MYSQL_TIME *tm, int decimals) { #ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || @@ -1135,18 +1183,8 @@ bool Protocol_text::store(MYSQL_TIME *tm) field_types[field_pos] == MYSQL_TYPE_TIMESTAMP); field_pos++; #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); - if (tm->second_part) - length+= sprintf(buff+length, ".%06d", - (int)tm->second_part); + char buff[MAX_DATE_STRING_REP_LENGTH]; + uint length= my_datetime_to_str(tm, buff, decimals); return net_store_data((uchar*) buff, length); } @@ -1164,29 +1202,15 @@ bool Protocol_text::store_date(MYSQL_TIME *tm) } -/** - @todo - Second_part format ("%06") needs to change when - we support 0-6 decimals for time. -*/ - -bool Protocol_text::store_time(MYSQL_TIME *tm) +bool Protocol_text::store_time(MYSQL_TIME *tm, int decimals) { #ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TIME); field_pos++; #endif - 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); - if (tm->second_part) - length+= sprintf(buff+length, ".%06d", (int)tm->second_part); + char buff[MAX_DATE_STRING_REP_LENGTH]; + uint length= my_time_to_str(tm, buff, decimals); return net_store_data((uchar*) buff, length); } @@ -1389,7 +1413,7 @@ bool Protocol_binary::store(Field *field) } -bool Protocol_binary::store(MYSQL_TIME *tm) +bool Protocol_binary::store(MYSQL_TIME *tm, int decimals) { char buff[12],*pos; uint length; @@ -1402,6 +1426,10 @@ bool Protocol_binary::store(MYSQL_TIME *tm) pos[4]= (uchar) tm->hour; pos[5]= (uchar) tm->minute; pos[6]= (uchar) tm->second; + DBUG_ASSERT(decimals == AUTO_SEC_PART_DIGITS || + (decimals >= 0 && decimals <= TIME_SECOND_PART_DIGITS)); + if (decimals != AUTO_SEC_PART_DIGITS) + tm->second_part= sec_part_truncate(tm->second_part, decimals); int4store(pos+7, tm->second_part); if (tm->second_part) length=11; @@ -1419,11 +1447,11 @@ bool Protocol_binary::store_date(MYSQL_TIME *tm) { tm->hour= tm->minute= tm->second=0; tm->second_part= 0; - return Protocol_binary::store(tm); + return Protocol_binary::store(tm, 0); } -bool Protocol_binary::store_time(MYSQL_TIME *tm) +bool Protocol_binary::store_time(MYSQL_TIME *tm, int decimals) { char buff[13], *pos; uint length; @@ -1432,7 +1460,6 @@ bool Protocol_binary::store_time(MYSQL_TIME *tm) pos[0]= tm->neg ? 1 : 0; if (tm->hour >= 24) { - /* Fix if we come from Item::send */ uint days= tm->hour/24; tm->hour-= days*24; tm->day+= days; @@ -1441,6 +1468,10 @@ bool Protocol_binary::store_time(MYSQL_TIME *tm) pos[5]= (uchar) tm->hour; pos[6]= (uchar) tm->minute; pos[7]= (uchar) tm->second; + DBUG_ASSERT(decimals == AUTO_SEC_PART_DIGITS || + (decimals >= 0 && decimals <= TIME_SECOND_PART_DIGITS)); + if (decimals != AUTO_SEC_PART_DIGITS) + tm->second_part= sec_part_truncate(tm->second_part, decimals); int4store(pos+8, tm->second_part); if (tm->second_part) length=12; |