[Commits] 98189b6: MDEV-18880: Optimizer trace prints date in hexadecimal

varun varunraiko1803 at gmail.com
Wed Apr 10 11:25:03 EEST 2019


revision-id: 98189b6df7a7f88efc9b7a199a436eb3022fd157 (mariadb-10.4.3-168-g98189b6)
parent(s): 517a56c1884e74b7c7606b56b0884537e792089e
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-04-10 13:49:16 +0530
message:

MDEV-18880: Optimizer trace prints date in hexadecimal

Introducded 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.

---
 mysql-test/main/opt_trace.result | 442 ++++++++++++++++++++++++++++++++++++++-
 mysql-test/main/opt_trace.test   |  56 +++++
 sql/field.cc                     |  59 ++++++
 sql/field.h                      |  15 ++
 sql/opt_range.cc                 |  34 +--
 sql/sql_string.h                 |   5 +
 6 files changed, 579 insertions(+), 32 deletions(-)

diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index ed5881e..3aec8aa 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,434 @@ 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 IN ('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 IN ('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 IN ('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 IN ('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 IN ('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 IN ('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 * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY	TRACE	MISSING_BYTES_BEYOND_MAX_MEM_SIZE	INSUFFICIENT_PRIVILEGES
+EXPLAIN SELECT * FROM t1 WHERE b IN ('ab\n')	{
+  "steps": [
+    {
+      "join_preparation": {
+        "select_id": 1,
+        "steps": [
+          {
+            "expanded_query": "select t1.i AS i,t1.b AS b from t1 where t1.b = 'ab\n'"
+          }
+        ]
+      }
+    },
+    {
+      "join_optimization": {
+        "select_id": 1,
+        "steps": [
+          {
+            "condition_processing": {
+              "condition": "WHERE",
+              "original_condition": "t1.b = 'ab\n'",
+              "steps": [
+                {
+                  "transformation": "equality_propagation",
+                  "resulting_condition": "multiple equal('ab\n', t1.b)"
+                },
+                {
+                  "transformation": "constant_propagation",
+                  "resulting_condition": "multiple equal('ab\n', t1.b)"
+                },
+                {
+                  "transformation": "trivial_condition_removal",
+                  "resulting_condition": "multiple equal('ab\n', t1.b)"
+                }
+              ]
+            }
+          },
+          {
+            "table_dependencies": [
+              {
+                "table": "t1",
+                "row_may_be_null": false,
+                "map_bit": 0,
+                "depends_on_map_bits": []
+              }
+            ]
+          },
+          {
+            "ref_optimizer_key_uses": [
+              {
+                "table": "t1",
+                "field": "b",
+                "equals": "'ab\n'",
+                "null_rejecting": false
+              }
+            ]
+          },
+          {
+            "rows_estimation": [
+              {
+                "table": "t1",
+                "range_analysis": {
+                  "table_scan": {
+                    "rows": 2,
+                    "cost": 4.5098
+                  },
+                  "potential_range_indexes": [
+                    {
+                      "index": "PRIMARY",
+                      "usable": false,
+                      "cause": "not applicable"
+                    },
+                    {
+                      "index": "i_b",
+                      "usable": true,
+                      "key_parts": ["b"]
+                    }
+                  ],
+                  "setup_range_conditions": [],
+                  "group_index_range": {
+                    "chosen": false,
+                    "cause": "no group by or distinct"
+                  },
+                  "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": []
+                  },
+                  "chosen_range_access_summary": {
+                    "range_access_plan": {
+                      "type": "range_scan",
+                      "index": "i_b",
+                      "rows": 2,
+                      "ranges": ["(ab\n) <= (b) <= (ab\n)"]
+                    },
+                    "rows_for_plan": 2,
+                    "cost_for_plan": 3.6324,
+                    "chosen": true
+                  }
+                }
+              },
+              {
+                "selectivity_for_indexes": [
+                  {
+                    "index_name": "i_b",
+                    "selectivity_from_index": 1
+                  }
+                ],
+                "selectivity_for_columns": [],
+                "cond_selectivity": 1
+              }
+            ]
+          },
+          {
+            "considered_execution_plans": [
+              {
+                "plan_prefix": [],
+                "table": "t1",
+                "best_access_path": {
+                  "considered_access_paths": [
+                    {
+                      "access_type": "ref",
+                      "index": "i_b",
+                      "used_range_estimates": true,
+                      "rows": 2,
+                      "cost": 3,
+                      "chosen": true
+                    },
+                    {
+                      "type": "scan",
+                      "chosen": false,
+                      "cause": "cost"
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            "attaching_conditions_to_tables": {
+              "original_condition": "t1.b = 'ab\n'",
+              "attached_conditions_computation": [],
+              "attached_conditions_summary": [
+                {
+                  "table": "t1",
+                  "attached": "t1.b = 'ab\n'"
+                }
+              ]
+            }
+          }
+        ]
+      }
+    },
+    {
+      "join_execution": {
+        "select_id": 1,
+        "steps": []
+      }
+    }
+  ]
+}	0	0
+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 981a53a..36bdc86 100644
--- a/mysql-test/main/opt_trace.test
+++ b/mysql-test/main/opt_trace.test
@@ -444,4 +444,60 @@ 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 IN ('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 IN ('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 IN ('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 IN ('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 IN ('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 IN ('ab\n');
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+#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/sql/field.cc b/sql/field.cc
index 4a93464..12fd423 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -11228,3 +11228,62 @@ 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, uint 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, uint length)
+{
+  if (charset() == &my_charset_bin)
+  {
+    length= field_charset->cset->lengthsp(field_charset, (const char*) ptr, length);
+    print_key_value_binary(out, ptr, length);
+  }
+  else
+    val_str(out,out);
+}
+
+
+void Field_varstring::print_key_value(String *out, uint 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, uint length)
+{
+  uchar *blob;
+  memcpy(&blob, ptr+packlength, sizeof(uchar*));
+  print_key_value_binary(out, blob, get_length());
+}
+
+
+void Field::print_key_value_binary(String *out, const uchar* key, uint length)
+{
+  size_t dst_len= length*4;
+  StringBuffer<128> tmp(system_charset_info);
+  tmp.reserve(dst_len);
+
+  tmp.copy_semi_hex((const char*) key, static_cast<size_t>(length), charset());
+  out->append(tmp.c_ptr_safe(), tmp.length(), charset());
+}
+
+
+void Field::print_key_value_helper(String *out, uint length)
+{
+  THD *thd= get_thd();
+  sql_mode_t sql_mode_backup= thd->variables.sql_mode;
+  thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
+  print_key_value(out, length);
+  thd->variables.sql_mode= sql_mode_backup;
+}
diff --git a/sql/field.h b/sql/field.h
index 8bd7343..35ca939 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1380,6 +1380,9 @@ class Field: public Value_source
   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, uint length);
+  virtual void print_key_value_helper(String *out, uint length);
+  void print_key_value_binary(String *out, const uchar* key, uint length);
 protected:
   bool set_warning(unsigned int code, int cuted_increment) const
   {
@@ -3587,6 +3590,7 @@ class Field_string :public Field_longstr {
   { 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, uint length);
 private:
   int save_field_metadata(uchar *first_byte);
 };
@@ -3692,6 +3696,8 @@ class Field_varstring :public Field_longstr {
   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, uint length);
+
 private:
   int save_field_metadata(uchar *first_byte);
 };
@@ -4029,6 +4035,7 @@ class Field_blob :public Field_longstr {
   uint32 char_length() const;
   uint32 character_octet_length() const;
   uint is_equal(Create_field *new_field);
+  void print_key_value(String *out, uint length);
 
   friend void TABLE::remember_blob_values(String *blob_storage);
   friend void TABLE::restore_blob_values(String *blob_storage);
@@ -4153,6 +4160,10 @@ class Field_geom :public Field_blob {
   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, uint length)
+  {
+    out->append(STRING_WITH_LEN("unprintable_geometry_value"));
+  }
 };
 
 uint gis_field_options_image(uchar *buff, List<Create_field> &create_fields);
@@ -4445,6 +4456,10 @@ class Field_bit :public Field {
   {
     return get_mm_leaf_int(param, key_part, cond, op, value, true);
   }
+  void print_key_value(String *out, uint 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 7c40a99..3ceb484 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -15785,7 +15785,7 @@ static void append_range_all_keyparts(Json_writer_array *range_trace,
   uint n_key_parts= param.table->actual_n_key_parts(keyinfo);
   seq.keyno= idx;
   seq.real_keyno= param.real_keynr[idx];
-  seq.param= ¶m;
+  seq.param= ¶m;
   seq.start= keypart;
   const KEY_PART_INFO *cur_key_part= key_parts + keypart->part;
   seq_it= seq_if.init((void *) &seq, 0, flags);
@@ -15828,12 +15828,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())
@@ -15852,28 +15850,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_helper(&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.h b/sql/sql_string.h
index fa941c8..d5a795d 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -951,6 +951,11 @@ class String: public Charset, public Binary_string
   {
     return !sortcmp(this, other, cs);
   }
+  void copy_semi_hex(const char *st, size_t len, CHARSET_INFO *cs)
+  {
+    uint length= convert_to_printable(Ptr, len*4, st, len, cs);
+    str_length+= length;
+  }
 };
 
 


More information about the commits mailing list