From eb2eaba7fdbd13c9814ab4619cc23d9f140e5485 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 14 Jul 2020 11:48:13 +0400 Subject: [PATCH] MDEV-23162 Improve Protocol performance for numeric data Avoid character set conversion for numeric data in this scenario: SET NAMES utf8; CREATE OR REPLACE TABLE t1 (a INT); INSERT INTO t1 VALUES (1); SELECT a FROM t1; --- sql/protocol.cc | 27 ++++++++++++++++++--------- sql/protocol.h | 39 ++++++++++++++++++++++++++++----------- sql/sql_prepare.cc | 20 ++++++++++++++------ 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index 07d09ecb4ee..a97e0d0997d 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -853,7 +853,7 @@ bool Protocol_text::store_field_metadata(const THD * thd, if (thd->client_capabilities & CLIENT_PROTOCOL_41) { const LEX_CSTRING def= {STRING_WITH_LEN("def")}; - if (store_ident(def) || + if (store_ident(def, MY_REPERTOIRE_ASCII) || store_ident(field.db_name) || store_ident(field.table_name) || store_ident(field.org_table_name) || @@ -868,7 +868,8 @@ bool Protocol_text::store_field_metadata(const THD * thd, Don't apply character set conversion: extended metadata is a binary encoded data. */ - if (store_lex_cstring(metadata.lex_cstring(), cs, &my_charset_bin)) + if (store_lex_cstring(metadata.lex_cstring(), cs, + MY_REPERTOIRE_UNICODE30, &my_charset_bin)) return true; } if (packet->realloc(packet->length() + 12)) @@ -1182,10 +1183,12 @@ bool Protocol_text::store_null() */ bool Protocol::store_string_aux(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs) + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs) { /* 'tocs' is set 0 when client issues SET character_set_results=NULL */ - if (needs_conversion(fromcs, tocs)) + if (needs_conversion(fromcs, from_repertoire, tocs)) { /* Store with conversion */ return net_store_data_cs((uchar*) from, length, fromcs, tocs); @@ -1208,7 +1211,9 @@ bool Protocol::store_warning(const char *from, size_t length) bool Protocol_text::store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs) + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs) { #ifndef DBUG_OFF DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*b", field_pos, @@ -1217,7 +1222,7 @@ bool Protocol_text::store_str(const char *from, size_t length, DBUG_ASSERT(valid_handler(field_pos, PROTOCOL_SEND_STRING)); field_pos++; #endif - return store_string_aux(from, length, fromcs, tocs); + return store_string_aux(from, length, fromcs, from_repertoire, tocs); } @@ -1330,7 +1335,8 @@ bool Protocol_text::store(Field *field) dbug_tmp_restore_column_map(table->read_set, old_map); #endif - return store_string_aux(str.ptr(), str.length(), str.charset(), tocs); + return store_string_aux(str.ptr(), str.length(), str.charset(), + field->dtcollation().repertoire, tocs); } @@ -1449,10 +1455,12 @@ void Protocol_binary::prepare_for_resend() bool Protocol_binary::store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs) + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs) { field_pos++; - return store_string_aux(from, length, fromcs, tocs); + return store_string_aux(from, length, fromcs, from_repertoire, tocs); } bool Protocol_binary::store_null() @@ -1515,6 +1523,7 @@ bool Protocol_binary::store_decimal(const my_decimal *d) StringBuffer str; (void) d->to_string(&str); return store_str(str.ptr(), str.length(), str.charset(), + MY_REPERTOIRE_ASCII, thd->variables.character_set_results); } diff --git a/sql/protocol.h b/sql/protocol.h index 1b3520c4cf6..08f416fc9bf 100644 --- a/sql/protocol.h +++ b/sql/protocol.h @@ -62,19 +62,25 @@ protected: MEM_ROOT *alloc; #endif bool needs_conversion(CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, CHARSET_INFO *tocs) const { // 'tocs' is set 0 when client issues SET character_set_results=NULL return tocs && !my_charset_same(fromcs, tocs) && fromcs != &my_charset_bin && - tocs != &my_charset_bin; + tocs != &my_charset_bin && + (from_repertoire != MY_REPERTOIRE_ASCII || + (fromcs->state & MY_CS_NONASCII) || + (tocs->state & MY_CS_NONASCII)); } /* The following two are low-level functions that are invoked from higher-level store_xxx() funcs. The data is stored into this->packet. */ bool store_string_aux(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs); virtual bool send_ok(uint server_status, uint statement_warn_count, ulonglong affected_rows, ulonglong last_insert_id, @@ -131,7 +137,9 @@ public: virtual bool store_longlong(longlong from, bool unsigned_flag)=0; virtual bool store_decimal(const my_decimal *)=0; virtual bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs)=0; + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs)=0; virtual bool store(float from, uint32 decimals, String *buffer)=0; virtual bool store(double from, uint32 decimals, String *buffer)=0; virtual bool store(MYSQL_TIME *time, int decimals)=0; @@ -141,19 +149,23 @@ public: // Various useful wrappers for the virtual store*() methods. // Backward wrapper for store_str() - bool store(const char *from, size_t length, CHARSET_INFO *cs) + bool store(const char *from, size_t length, CHARSET_INFO *cs, + my_repertoire_t repertoire= MY_REPERTOIRE_UNICODE30) { - return store_str(from, length, cs, character_set_results()); + return store_str(from, length, cs, repertoire, character_set_results()); } bool store_lex_cstring(const LEX_CSTRING &s, CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, CHARSET_INFO *tocs) { - return store_str(s.str, (uint) s.length, fromcs, tocs); + return store_str(s.str, (uint) s.length, fromcs, from_repertoire, tocs); } - bool store_ident(const LEX_CSTRING &s) + bool store_ident(const LEX_CSTRING &s, + my_repertoire_t repertoire= MY_REPERTOIRE_UNICODE30) { - return store_lex_cstring(s, system_charset_info, character_set_results()); + return store_lex_cstring(s, system_charset_info, repertoire, + character_set_results()); } // End of wrappers @@ -202,7 +214,9 @@ public: virtual bool store_longlong(longlong from, bool unsigned_flag); virtual bool store_decimal(const my_decimal *); virtual bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs); virtual bool store(MYSQL_TIME *time, int decimals); virtual bool store_date(MYSQL_TIME *time); virtual bool store_time(MYSQL_TIME *time, int decimals); @@ -246,7 +260,9 @@ public: virtual bool store_longlong(longlong from, bool unsigned_flag); virtual bool store_decimal(const my_decimal *); virtual bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs); virtual bool store(MYSQL_TIME *time, int decimals); virtual bool store_date(MYSQL_TIME *time); virtual bool store_time(MYSQL_TIME *time, int decimals); @@ -293,7 +309,8 @@ public: bool store_long(longlong) { return false; } bool store_longlong(longlong, bool) { return false; } bool store_decimal(const my_decimal *) { return false; } - bool store_str(const char *, size_t, CHARSET_INFO *, CHARSET_INFO *) + bool store_str(const char *, size_t, CHARSET_INFO *, my_repertoire_t, + CHARSET_INFO *) { return false; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index a616069a0bd..913497b097a 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -263,7 +263,9 @@ protected: virtual bool store_longlong(longlong from, bool unsigned_flag); virtual bool store_decimal(const my_decimal *); virtual bool store_str(const char *from, size_t length, - CHARSET_INFO *fromcs, CHARSET_INFO *tocs); + CHARSET_INFO *fromcs, + my_repertoire_t from_repertoire, + CHARSET_INFO *tocs); virtual bool store(MYSQL_TIME *time, int decimals); virtual bool store_date(MYSQL_TIME *time); virtual bool store_time(MYSQL_TIME *time, int decimals); @@ -286,7 +288,9 @@ protected: virtual bool send_error(uint sql_errno, const char *err_msg, const char* sqlstate); private: bool store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs); + CHARSET_INFO *src_cs, + my_repertoire_t src_repertoire, + CHARSET_INFO *dst_cs); bool store_column(const void *data, size_t length); void opt_add_row_to_rset(); @@ -5269,12 +5273,14 @@ bool Protocol_local::store_column(const void *data, size_t length) bool Protocol_local::store_string(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs) + CHARSET_INFO *src_cs, + my_repertoire_t src_repertoire, + CHARSET_INFO *dst_cs) { /* Store with conversion */ uint error_unused; - if (needs_conversion(src_cs, dst_cs)) + if (needs_conversion(src_cs, src_repertoire, dst_cs)) { if (unlikely(convert->copy(str, length, src_cs, dst_cs, &error_unused))) return TRUE; @@ -5334,9 +5340,11 @@ bool Protocol_local::store_decimal(const my_decimal *value) /** Store a string. */ bool Protocol_local::store_str(const char *str, size_t length, - CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs) + CHARSET_INFO *src_cs, + my_repertoire_t from_repertoire, + CHARSET_INFO *dst_cs) { - return store_string(str, length, src_cs, dst_cs); + return store_string(str, length, src_cs, from_repertoire, dst_cs); }