diff --git a/sql/field.cc b/sql/field.cc index 90535344174..d20c2c3af5c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1888,7 +1888,7 @@ void Field::copy_from_tmp(int row_offset) } -bool Field::send_binary(Protocol *protocol) +bool Field::send(Protocol *protocol) { char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),charset()); @@ -1897,6 +1897,18 @@ bool Field::send_binary(Protocol *protocol) } +bool Field_num::send_numeric_zerofill_str(Protocol_text *protocol, + protocol_send_type_t send_type) +{ + DBUG_ASSERT(marked_for_read()); + StringBuffer tmp(&my_charset_latin1); + val_str(&tmp); + return protocol->store_numeric_zerofill_str(tmp.ptr(), + tmp.length(), + send_type); +} + + /** Check to see if field size is compatible with destination. @@ -3855,11 +3867,16 @@ String *Field_tiny::val_str(String *val_buffer, return val_str_from_long(val_buffer, 5, -10, nr); } -bool Field_tiny::send_binary(Protocol *protocol) +bool Field_tiny::send(Protocol *protocol) { - return protocol->store_tiny((longlong) (int8) ptr[0]); + DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_TINY); + return protocol->store_tiny(Field_tiny::val_int()); } + int Field_tiny::cmp(const uchar *a_ptr, const uchar *b_ptr) const { signed char a,b; @@ -4015,8 +4032,12 @@ String *Field_short::val_str(String *val_buffer, } -bool Field_short::send_binary(Protocol *protocol) +bool Field_short::send(Protocol *protocol) { + DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_SHORT); return protocol->store_short(Field_short::val_int()); } @@ -4198,9 +4219,12 @@ String *Field_int::val_str_from_long(String *val_buffer, } -bool Field_medium::send_binary(Protocol *protocol) +bool Field_medium::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_LONG); return protocol->store_long(Field_medium::val_int()); } @@ -4369,12 +4393,16 @@ String *Field_long::val_str(String *val_buffer, } -bool Field_long::send_binary(Protocol *protocol) +bool Field_long::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_LONG); return protocol->store_long(Field_long::val_int()); } + int Field_long::cmp(const uchar *a_ptr, const uchar *b_ptr) const { int32 a,b; @@ -4506,9 +4534,12 @@ String *Field_longlong::val_str(String *val_buffer, } -bool Field_longlong::send_binary(Protocol *protocol) +bool Field_longlong::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_LONGLONG); return protocol->store_longlong(Field_longlong::val_int(), unsigned_flag); } @@ -4686,9 +4717,12 @@ void Field_float::sort_string(uchar *to,uint length __attribute__((unused))) } -bool Field_float::send_binary(Protocol *protocol) +bool Field_float::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_FLOAT); return protocol->store_float((float) Field_float::val_real(), dec); } @@ -4980,8 +5014,12 @@ String *Field_double::val_str(String *val_buffer, return val_buffer; } -bool Field_double::send_binary(Protocol *protocol) +bool Field_double::send(Protocol *protocol) { + DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if (unlikely(zerofill) && (txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_DOUBLE); return protocol->store_double(Field_double::val_real(), dec); } @@ -5378,7 +5416,7 @@ bool Field_timestamp::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) } -bool Field_timestamp0::send_binary(Protocol *protocol) +bool Field_timestamp0::send(Protocol *protocol) { MYSQL_TIME ltime; Field_timestamp0::get_date(<ime, date_mode_t(0)); @@ -5538,7 +5576,7 @@ int Field_timestamp_with_dec::set_time() return 0; } -bool Field_timestamp_with_dec::send_binary(Protocol *protocol) +bool Field_timestamp_with_dec::send(Protocol *protocol) { MYSQL_TIME ltime; Field_timestamp::get_date(<ime, date_mode_t(0)); @@ -6047,7 +6085,7 @@ bool Field_time0::get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) } -bool Field_time::send_binary(Protocol *protocol) +bool Field_time::send(Protocol *protocol) { MYSQL_TIME ltime; get_date(<ime, Time::Options(TIME_TIME_ONLY, get_thd())); @@ -6369,9 +6407,12 @@ int Field_year::store_time_dec(const MYSQL_TIME *ltime, uint dec_arg) return 0; } -bool Field_year::send_binary(Protocol *protocol) +bool Field_year::send(Protocol *protocol) { DBUG_ASSERT(marked_for_read()); + Protocol_text *txt; + if ((txt= dynamic_cast(protocol))) + return send_numeric_zerofill_str(txt, PROTOCOL_SEND_SHORT); ulonglong tmp= Field_year::val_int(); return protocol->store_short(tmp); } @@ -6506,7 +6547,7 @@ void Field_date::store_TIME(const MYSQL_TIME *ltime) int4store(ptr,tmp); } -bool Field_date::send_binary(Protocol *protocol) +bool Field_date::send(Protocol *protocol) { longlong tmp= Field_date::val_int(); MYSQL_TIME tm; @@ -6600,7 +6641,7 @@ void Field_newdate::store_TIME(const MYSQL_TIME *ltime) } -bool Field_newdate::send_binary(Protocol *protocol) +bool Field_newdate::send(Protocol *protocol) { MYSQL_TIME tm; Field_newdate::get_date(&tm, date_mode_t(0)); @@ -6772,7 +6813,7 @@ Field_datetime::conversion_depends_on_sql_mode(THD *thd, Item *expr) const } -bool Field_datetime0::send_binary(Protocol *protocol) +bool Field_datetime0::send(Protocol *protocol) { MYSQL_TIME tm; Field_datetime0::get_date(&tm, date_mode_t(0)); @@ -6900,7 +6941,7 @@ void Field_datetime_hires::store_TIME(const MYSQL_TIME *ltime) store_bigendian(packed, ptr, Field_datetime_hires::pack_length()); } -bool Field_datetime_with_dec::send_binary(Protocol *protocol) +bool Field_datetime_with_dec::send(Protocol *protocol) { MYSQL_TIME ltime; get_date(<ime, date_mode_t(0)); @@ -7109,6 +7150,23 @@ void Field_longstr::make_send_field(Send_field *field) } } + +/* + An optimized version that uses less stack than Field::send(). +*/ +bool Field_longstr::send(Protocol *protocol) +{ + String tmp; + val_str(&tmp, &tmp); + /* + Ensure this function is only used with classes that do not allocate + memory in val_str() + */ + DBUG_ASSERT(tmp.alloced_length() == 0); + return protocol->store(tmp.ptr(), tmp.length(), tmp.charset()); +} + + /* Copy a string and fill with space */ int Field_string::store(const char *from, size_t length,CHARSET_INFO *cs) @@ -7698,6 +7756,17 @@ my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value) } +/* + An optimized version that uses less stack and less temporary + variable initialization than Field_longstr::send() +*/ +bool Field_varstring::send(Protocol *protocol) +{ + return protocol->store((const char *) get_data(), get_length(), + field_charset()); +} + + #ifdef HAVE_valgrind void Field_varstring::mark_unused_memory_as_defined() { diff --git a/sql/field.h b/sql/field.h index 0f531564116..2c73fed708b 100644 --- a/sql/field.h +++ b/sql/field.h @@ -37,6 +37,7 @@ class Send_field; class Copy_field; class Protocol; +class Protocol_text; class Create_field; class Relay_log_info; class Field; @@ -1576,7 +1577,7 @@ public: ptr= old_ptr; return str; } - virtual bool send_binary(Protocol *protocol); + virtual bool send(Protocol *protocol); virtual uchar *pack(uchar *to, const uchar *from, uint max_length); /** @@ -2005,6 +2006,9 @@ protected: return (flags & UNSIGNED_FLAG) ? Binlog_type_info::SIGN_UNSIGNED : Binlog_type_info::SIGN_SIGNED; } + bool send_numeric_zerofill_str(Protocol_text *protocol, + protocol_send_type_t send_type); + public: const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields @@ -2194,6 +2198,7 @@ public: int store_decimal(const my_decimal *d) override; uint32 max_data_length() const override; void make_send_field(Send_field *) override; + bool send(Protocol *protocol) override; bool is_varchar_and_in_write_set() const override { @@ -2520,7 +2525,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 1; } @@ -2583,7 +2588,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 2; } @@ -2630,7 +2635,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 3; } @@ -2681,7 +2686,7 @@ public: int reset() override { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; return 0; } double val_real() override; longlong val_int() override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; String *val_str(String *, String *) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; @@ -2743,7 +2748,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 8; } @@ -2843,7 +2848,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff, uint length) override; uint32 pack_length() const override { return sizeof(float); } @@ -2907,7 +2912,7 @@ public: longlong val_int() override final { return val_int_from_real(false); } ulonglong val_uint() override final { return (ulonglong) val_int_from_real(true); } String *val_str(String *, String *) override final; - bool send_binary(Protocol *protocol) override final; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override final; void sort_string(uchar *buff, uint length) override final; uint32 pack_length() const override final { return sizeof(double); } @@ -3210,7 +3215,7 @@ public: { return (double) Field_timestamp0::val_int(); } - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } @@ -3265,7 +3270,7 @@ public: DBUG_ASSERT(length == pack_length()); memcpy(to, ptr, length); } - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; double val_real() override; my_decimal* val_decimal(my_decimal*) override; int set_time() override; @@ -3403,7 +3408,7 @@ public: longlong val_int() override; String *val_str(String *, String *) override; bool get_date(MYSQL_TIME *ltime, date_mode_t fuzzydate) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; Information_schema_numeric_attributes information_schema_numeric_attributes() const override { @@ -3462,7 +3467,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 4; } @@ -3501,7 +3506,7 @@ public: double val_real() override; longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 3; } @@ -3561,7 +3566,7 @@ public: int store(longlong nr, bool unsigned_val) override; int store_decimal(const my_decimal *) override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; void set_curdays(THD *thd); Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, @@ -3775,7 +3780,7 @@ public: } longlong val_int() override; String *val_str(String *, String *) override; - bool send_binary(Protocol *protocol) override; + bool send(Protocol *protocol) override; int cmp(const uchar *,const uchar *) const override; void sort_string(uchar *buff,uint length) override; uint32 pack_length() const override { return 8; } @@ -3815,7 +3820,7 @@ public: uint decimals() const override final { return dec; } enum ha_base_keytype key_type() const override final { return HA_KEYTYPE_BINARY; } void make_send_field(Send_field *field) override final; - bool send_binary(Protocol *protocol) override final; + bool send(Protocol *protocol) override final; uchar *pack(uchar *to, const uchar *from, uint max_length) override final { return Field::pack(to, from, max_length); } const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, @@ -4153,6 +4158,7 @@ public: longlong val_int() override; String *val_str(String *, String *) override; my_decimal *val_decimal(my_decimal *) override; + bool send(Protocol *protocol) override; int cmp(const uchar *a,const uchar *b) const override; int cmp_prefix(const uchar *a, const uchar *b, size_t prefix_len) const override; @@ -4217,6 +4223,15 @@ private: double val_real() override; longlong val_int() override; uint size_of() const override { return sizeof *this; } + /* + We use the default Field::send() implementation, + because the derived optimized version (from Field_longstr) + is not suitable for compressed fields. + */ + bool send(Protocol *protocol) override + { + return Field::send(protocol); + } enum_field_types binlog_type() const override { return MYSQL_TYPE_VARCHAR_COMPRESSED; } void sql_type(String &str) const override @@ -4614,6 +4629,15 @@ private: String *val_str(String *, String *) override; double val_real() override; longlong val_int() override; + /* + We use the default Field::send() implementation, + because the derived optimized version (from Field_longstr) + is not suitable for compressed fields. + */ + bool send(Protocol *protocol) override + { + return Field::send(protocol); + } uint size_of() const override { return sizeof *this; } enum_field_types binlog_type() const override { return MYSQL_TYPE_BLOB_COMPRESSED; } diff --git a/sql/protocol.cc b/sql/protocol.cc index 189cdfca9af..a446e3b656f 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -1232,6 +1232,22 @@ bool Protocol_text::store_str(const char *from, size_t length, } +bool Protocol_text::store_numeric_zerofill_str(const char *from, + size_t length, + protocol_send_type_t send_type) +{ +#ifndef DBUG_OFF + DBUG_PRINT("info", + ("Protocol_text::store_numeric_zerofill_str field %u : %.*b", + field_pos, (int) length, (length == 0 ? "" : from))); + DBUG_ASSERT(field_handlers == 0 || field_pos < field_count); + DBUG_ASSERT(valid_handler(field_pos, send_type)); + field_pos++; +#endif + return store_numeric_string_aux(from, length); +} + + bool Protocol_text::store_tiny(longlong from) { #ifndef DBUG_OFF @@ -1321,12 +1337,6 @@ bool Protocol_text::store(Field *field) { if (field->is_null()) return store_null(); -#ifndef DBUG_OFF - field_pos++; -#endif - char buff[MAX_FIELD_WIDTH]; - String str(buff,sizeof(buff), &my_charset_bin); - CHARSET_INFO *tocs= this->thd->variables.character_set_results; #ifdef DBUG_ASSERT_EXISTS TABLE *table= field->table; my_bitmap_map *old_map= 0; @@ -1334,13 +1344,14 @@ bool Protocol_text::store(Field *field) old_map= dbug_tmp_use_all_columns(table, table->read_set); #endif - field->val_str(&str); + bool rc= field->send(this); + #ifdef DBUG_ASSERT_EXISTS if (old_map) dbug_tmp_restore_column_map(table->read_set, old_map); #endif - return store_string_aux(str.ptr(), str.length(), str.charset(), tocs); + return rc; } @@ -1553,12 +1564,12 @@ bool Protocol_binary::store_double(double from, uint32 decimals) bool Protocol_binary::store(Field *field) { /* - We should not increment field_pos here as send_binary() will call another + We should not increment field_pos here as send() will call another protocol function to do this for us */ if (field->is_null()) return store_null(); - return field->send_binary(this); + return field->send(this); } diff --git a/sql/protocol.h b/sql/protocol.h index da01b6244e1..72cbc672cde 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -219,6 +219,10 @@ public: bool store(Field *field) override; bool send_out_parameters(List *sp_params) override; + + bool store_numeric_zerofill_str(const char *from, size_t length, + protocol_send_type_t send_type); + #ifdef EMBEDDED_LIBRARY void remove_last_row() override; #endif diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5d034b80b6d..ade531339bb 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -5390,7 +5390,7 @@ bool Protocol_local::store(Field *field) { if (field->is_null()) return store_null(); - return field->send_binary(this); + return field->send(this); }