diff options
author | Varun <varun.gupta@mariadb.com> | 2019-06-10 15:56:36 +0530 |
---|---|---|
committer | Varun <varun.gupta@mariadb.com> | 2019-06-11 15:44:58 +0530 |
commit | a0cb7551a4467fbce74f3ced78549bf92866c11f (patch) | |
tree | a06c13af6dd33cf207d636276ca213e106e95299 | |
parent | 40ff8019d2a00071f533bb3210b4d3a552e95bc8 (diff) | |
download | mariadb-git-a0cb7551a4467fbce74f3ced78549bf92866c11f.tar.gz |
MDEV-18880: Optimizer trace prints date in hexadecimal
Introduced a print_key_value function to makes sure that the trace prints data in readable format
for readable characters and the rest of the characters are printed as hexadecimal.
-rw-r--r-- | mysql-test/main/opt_trace.result | 298 | ||||
-rw-r--r-- | mysql-test/main/opt_trace.test | 54 | ||||
-rw-r--r-- | mysql-test/main/opt_trace_ucs2.result | 54 | ||||
-rw-r--r-- | mysql-test/main/opt_trace_ucs2.test | 10 | ||||
-rw-r--r-- | sql/field.cc | 55 | ||||
-rw-r--r-- | sql/field.h | 14 | ||||
-rw-r--r-- | sql/opt_range.cc | 32 | ||||
-rw-r--r-- | sql/sql_string.cc | 12 | ||||
-rw-r--r-- | sql/sql_string.h | 3 |
9 files changed, 501 insertions, 31 deletions
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index 3e4b7fe6e8a..82a2196545d 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -1446,7 +1446,7 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id { { "index": "id", "covering": true, - "ranges": ["(0x24a20f) <= (a)"], + "ranges": ["(2001-01-04) <= (a)"], "rows": 9, "cost": 2.35 } @@ -1462,7 +1462,7 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id { "rows": 9, "cost": 2.35, "key_parts_used_for_access": ["id"], - "ranges": ["(0x24a20f) <= (a)"], + "ranges": ["(2001-01-04) <= (a)"], "chosen": false, "cause": "cost" }, @@ -1624,7 +1624,7 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id { { "index": "id", "covering": true, - "ranges": ["(0x24a20f) <= (a) <= (0x24a20f)"], + "ranges": ["(2001-01-04) <= (a) <= (2001-01-04)"], "rows": 9, "cost": 2.35 } @@ -1640,7 +1640,7 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id { "rows": 9, "cost": 2.35, "key_parts_used_for_access": ["id", "a"], - "ranges": ["(0x24a20f) <= (a) <= (0x24a20f)"], + "ranges": ["(2001-01-04) <= (a) <= (2001-01-04)"], "chosen": false, "cause": "cost" }, @@ -6130,7 +6130,7 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) "index": "start_date", "ranges": [ - "(0x4ac60f,NULL) < (start_date,end_date)" + "(2019-02-10,NULL) < (start_date,end_date)" ], "rowid_ordered": false, "using_mrr": false, @@ -6214,7 +6214,7 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) "index": "i_b", "ranges": [ - "(0xd95b94336a9946a39cf5b58cfe772d8c) <= (b) <= (0xd95b94336a9946a39cf5b58cfe772d8c)" + "(\xD9[\x943j\x99F\xA3\x9C\xF5\xB5\x8C\xFEw-\x8C) <= (b) <= (\xD9[\x943j\x99F\xA3\x9C\xF5\xB5\x8C\xFEw-\x8C)" ], "rowid_ordered": true, "using_mrr": false, @@ -6268,4 +6268,290 @@ JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) } ] drop table t1; +# +# MDEV-18880: Optimizer trace prints date in hexadecimal +# +CREATE TABLE t1(i INT PRIMARY KEY, b VARCHAR(10) CHARSET BINARY , INDEX i_b(b)); +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, NULL); +set optimizer_trace=1; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i_b i_b 13 const 1 Using index condition +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "i_b", + "ranges": + [ + "(ab\x0A) <= (b) <= (ab\x0A)" + ], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 2.3787, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +ALTER TABLE t1 modify column b BINARY(10) AFTER i; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i_b i_b 11 const 1 Using index condition +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "i_b", + "ranges": + [ + "(ab\x0A\x00\x00\x00\x00\x00\x00\x00) <= (b) <= (ab\x0A\x00\x00\x00\x00\x00\x00\x00)" + ], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 2.3785, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +ALTER TABLE t1 modify column b VARBINARY(10) AFTER i; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i_b i_b 13 const 1 Using index condition +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "i_b", + "ranges": + [ + "(ab\x0A) <= (b) <= (ab\x0A)" + ], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 2.3787, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +drop table t1; +CREATE TABLE t1(i INT PRIMARY KEY, b CHAR(10), INDEX i_b(b)); +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, NULL); +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i_b i_b 11 const 1 Using index condition +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "i_b", + "ranges": + [ + "(ab\n) <= (b) <= (ab\n)" + ], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 2.3785, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +drop table t1; +CREATE TABLE t1(i INT PRIMARY KEY, b blob , INDEX i_b(b)); +Warnings: +Note 1071 Specified key was too long; max key length is 1000 bytes +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, NULL); +set optimizer_trace=1; +EXPLAIN SELECT * FROM t1 WHERE b= 'ab\n'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i_b i_b 1003 const 1 Using where +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "i_b", + "ranges": + [ + "(ab\x0A) <= (b) <= (ab\x0A)" + ], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 3.5719, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +drop table t1; +CREATE TABLE t1(i INT PRIMARY KEY, b VARCHAR(10), INDEX i_b(b)); +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, 'ab\n'); +set optimizer_trace=1; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i_b i_b 13 const 2 Using index condition +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "i_b", + "ranges": + [ + "(ab\n) <= (b) <= (ab\n)" + ], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 2, + "cost": 3.6324, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +drop table t1; +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table one_k (a int); +insert into one_k select A.a + B.a*10 + C.a*100 from t0 A, t0 B, t0 C; +create table t1 (start_date date, end_date date, filler char(100), key(start_date, end_date)) ; +insert into t1 select date_add(now(), interval a day), date_add(now(), interval (a+7) day), 'data' from one_k; +explain format=json select * from t1 force index(start_date) where start_date >= '2019-02-10' and end_date <'2019-04-01'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["start_date"], + "key": "start_date", + "key_length": "8", + "used_key_parts": ["start_date", "end_date"], + "rows": 1000, + "filtered": 100, + "index_condition": "t1.start_date >= '2019-02-10' and t1.end_date < '2019-04-01'" + } + } +} +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "start_date", + "ranges": + [ + "(2019-02-10,NULL) < (start_date,end_date)" + ], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 1000, + "cost": 1282.2, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +drop table t1, t0, one_k; set optimizer_trace='enabled=off'; diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test index 981a53ac1ad..916b9313ca6 100644 --- a/mysql-test/main/opt_trace.test +++ b/mysql-test/main/opt_trace.test @@ -444,4 +444,58 @@ select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) fr drop table t1; +--echo # +--echo # MDEV-18880: Optimizer trace prints date in hexadecimal +--echo # + +CREATE TABLE t1(i INT PRIMARY KEY, b VARCHAR(10) CHARSET BINARY , INDEX i_b(b)); +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, NULL); +set optimizer_trace=1; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; + +ALTER TABLE t1 modify column b BINARY(10) AFTER i; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; + +ALTER TABLE t1 modify column b VARBINARY(10) AFTER i; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; + +CREATE TABLE t1(i INT PRIMARY KEY, b CHAR(10), INDEX i_b(b)); +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, NULL); +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; + +CREATE TABLE t1(i INT PRIMARY KEY, b blob , INDEX i_b(b)); +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, NULL); +set optimizer_trace=1; +EXPLAIN SELECT * FROM t1 WHERE b= 'ab\n'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; + +CREATE TABLE t1(i INT PRIMARY KEY, b VARCHAR(10), INDEX i_b(b)); +INSERT INTO t1 VALUES (1, 'ab\n'); +INSERT INTO t1 VALUES (2, 'ab\n'); +set optimizer_trace=1; +EXPLAIN SELECT * FROM t1 WHERE b='ab\n'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; +create table t0(a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table one_k (a int); +insert into one_k select A.a + B.a*10 + C.a*100 from t0 A, t0 B, t0 C; +create table t1 (start_date date, end_date date, filler char(100), key(start_date, end_date)) ; +--disable_warnings +insert into t1 select date_add(now(), interval a day), date_add(now(), interval (a+7) day), 'data' from one_k; +--enable_warnings +explain format=json select * from t1 force index(start_date) where start_date >= '2019-02-10' and end_date <'2019-04-01'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1, t0, one_k; + set optimizer_trace='enabled=off'; diff --git a/mysql-test/main/opt_trace_ucs2.result b/mysql-test/main/opt_trace_ucs2.result new file mode 100644 index 00000000000..306fdbf94ad --- /dev/null +++ b/mysql-test/main/opt_trace_ucs2.result @@ -0,0 +1,54 @@ +create or replace table t1 (col1 char(10) character set ucs2, filler char(100), key(col1)) ; +insert into t1 values ('a', 'a'); +insert into t1 values ('a', 'a'); +set optimizer_trace=1; +explain format=json select * from t1 force index(col1) where col1 >='a'; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t1", + "access_type": "range", + "possible_keys": ["col1"], + "key": "col1", + "key_length": "21", + "used_key_parts": ["col1"], + "rows": 2, + "filtered": 100, + "index_condition": "t1.col1 >= 'a'" + } + } +} +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) +[ + + { + "range_scan_alternatives": + [ + + { + "index": "col1", + "ranges": + [ + "(a) <= (col1)" + ], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 2, + "cost": 3.7609, + "chosen": true + } + ], + "analyzing_roworder_intersect": + { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": + [ + ] + } +] +drop table t1; diff --git a/mysql-test/main/opt_trace_ucs2.test b/mysql-test/main/opt_trace_ucs2.test new file mode 100644 index 00000000000..827dc403d58 --- /dev/null +++ b/mysql-test/main/opt_trace_ucs2.test @@ -0,0 +1,10 @@ +--source include/not_embedded.inc +--source include/have_ucs2.inc + +create or replace table t1 (col1 char(10) character set ucs2, filler char(100), key(col1)) ; +insert into t1 values ('a', 'a'); +insert into t1 values ('a', 'a'); +set optimizer_trace=1; +explain format=json select * from t1 force index(col1) where col1 >='a'; +select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index a671195ba2b..46e33dc8526 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -11242,3 +11242,58 @@ bool Field::val_str_nopad(MEM_ROOT *mem_root, LEX_CSTRING *to) thd->variables.sql_mode= sql_mode_backup; return rc; } + + +void Field::print_key_value(String *out, uint32 length) +{ + if (charset() == &my_charset_bin) + print_key_value_binary(out, ptr, length); + else + val_str(out); +} + + +void Field_string::print_key_value(String *out, uint32 length) +{ + if (charset() == &my_charset_bin) + { + size_t len= field_charset->cset->lengthsp(field_charset, (const char*) ptr, length); + print_key_value_binary(out, ptr, static_cast<uint32>(len)); + } + else + { + THD *thd= get_thd(); + sql_mode_t sql_mode_backup= thd->variables.sql_mode; + thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; + val_str(out,out); + thd->variables.sql_mode= sql_mode_backup; + } +} + + +void Field_varstring::print_key_value(String *out, uint32 length) +{ + if (charset() == &my_charset_bin) + print_key_value_binary(out, get_data(), get_length()); + else + val_str(out,out); +} + + +void Field_blob::print_key_value(String *out, uint32 length) +{ + if (charset() == &my_charset_bin) + { + uchar *blob; + memcpy(&blob, ptr+packlength, sizeof(uchar*)); + print_key_value_binary(out, blob, get_length()); + } + else + val_str(out, out); +} + + +void Field::print_key_value_binary(String *out, const uchar* key, uint32 length) +{ + out->append_semi_hex((const char*)key, length, charset()); +}
\ No newline at end of file diff --git a/sql/field.h b/sql/field.h index ceb4a8bb93f..8b65f2e95e4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1383,6 +1383,8 @@ public: virtual int set_time() { return 1; } bool set_warning(Sql_condition::enum_warning_level, unsigned int code, int cuted_increment, ulong current_row=0) const; + virtual void print_key_value(String *out, uint32 length); + void print_key_value_binary(String *out, const uchar* key, uint32 length); protected: bool set_warning(unsigned int code, int cuted_increment) const { @@ -3592,6 +3594,7 @@ public: { return charset() == &my_charset_bin ? FALSE : TRUE; } Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type); virtual uint get_key_image(uchar *buff,uint length, imagetype type); + void print_key_value(String *out, uint32 length); private: int save_field_metadata(uchar *first_byte); }; @@ -3697,6 +3700,7 @@ public: uint is_equal(Create_field *new_field); void hash(ulong *nr, ulong *nr2); uint length_size() { return length_bytes; } + void print_key_value(String *out, uint32 length); private: int save_field_metadata(uchar *first_byte); }; @@ -4035,6 +4039,7 @@ public: uint32 char_length() const; uint32 character_octet_length() const; uint is_equal(Create_field *new_field); + void print_key_value(String *out, uint32 length); friend void TABLE::remember_blob_values(String *blob_storage); friend void TABLE::restore_blob_values(String *blob_storage); @@ -4159,6 +4164,10 @@ public: geometry_type get_geometry_type() { return geom_type; }; static geometry_type geometry_type_merge(geometry_type, geometry_type); uint get_srid() { return srid; } + void print_key_value(String *out, uint32 length) + { + out->append(STRING_WITH_LEN("unprintable_geometry_value")); + } }; uint gis_field_options_image(uchar *buff, List<Create_field> &create_fields); @@ -4466,6 +4475,11 @@ public: { return get_mm_leaf_int(param, key_part, cond, op, value, true); } + void print_key_value(String *out, uint32 length) + { + val_int_as_str(out, 1); + } + private: virtual size_t do_last_null_byte() const; int save_field_metadata(uchar *first_byte); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index bff5bd371b6..d0c4ed2ffbc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -15835,12 +15835,10 @@ static void print_key_value(String *out, const KEY_PART_INFO *key_part, { // Byte 0 of a nullable key is the null-byte. If set, key is NULL. if (field->real_maybe_null() && *key) + { out->append(STRING_WITH_LEN("NULL")); - else - (field->type() == MYSQL_TYPE_GEOMETRY) - ? out->append(STRING_WITH_LEN("unprintable_geometry_value")) - : out->append(STRING_WITH_LEN("unprintable_blob_value")); - goto next; + goto next; + } } if (field->real_maybe_null()) @@ -15859,28 +15857,12 @@ static void print_key_value(String *out, const KEY_PART_INFO *key_part, store_length--; } - /* - Binary data cannot be converted to UTF8 which is what the - optimizer trace expects. If the column is binary, the hex - representation is printed to the trace instead. - */ - if (field->flags & BINARY_FLAG) - { - out->append("0x"); - for (uint i = 0; i < store_length; i++) - { - out->append(_dig_vec_lower[*(key + i) >> 4]); - out->append(_dig_vec_lower[*(key + i) & 0x0F]); - } - goto next; - } - field->set_key_image(key, key_part->length); - if (field->type() == MYSQL_TYPE_BIT) - (void)field->val_int_as_str(&tmp, 1); // may change tmp's charset + field->print_key_value(&tmp, key_part->length); + if (field->charset() == &my_charset_bin) + out->append(tmp.ptr(), tmp.length(), tmp.charset()); else - field->val_str(&tmp); // may change tmp's charset - out->append(tmp.ptr(), tmp.length(), tmp.charset()); + tmp.print(out, system_charset_info); next: if (key + store_length < key_end) diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 410f52a8c74..1b567ecb325 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -1196,3 +1196,15 @@ uint convert_to_printable(char *to, size_t to_len, *t= '\0'; return (uint) (t - to); } + + +bool String::append_semi_hex(const char *s, uint len, CHARSET_INFO *cs) +{ + size_t dst_len= len * 4 + 1; //extra length for the '\0' character + if (reserve(dst_len)) + return true; + uint nbytes= convert_to_printable(Ptr + str_length, dst_len, s, len, cs); + DBUG_ASSERT((ulonglong) str_length + nbytes < UINT_MAX32); + str_length+= nbytes; + return false; +} diff --git a/sql/sql_string.h b/sql/sql_string.h index caefee7ec09..d8edf5e81f0 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -674,6 +674,7 @@ public: int reserve(size_t space_needed) { + DBUG_ASSERT((ulonglong) str_length + space_needed < UINT_MAX32); return realloc(str_length + space_needed); } int reserve(size_t space_needed, size_t grow_by); @@ -959,6 +960,8 @@ public: { return !sortcmp(this, other, cs); } +private: + bool append_semi_hex(const char *s, uint len, CHARSET_INFO *cs); }; |