diff options
-rw-r--r-- | client/mysql.cc | 88 | ||||
-rw-r--r-- | mysql-test/r/binary_to_hex.result | 117 | ||||
-rw-r--r-- | mysql-test/t/binary_to_hex.test | 76 |
3 files changed, 268 insertions, 13 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 2269563814c..6e6dc4971ac 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -142,7 +142,7 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0, default_pager_set= 0, opt_sigint_ignore= 0, auto_vertical_output= 0, show_warnings= 0, executing_query= 0, interrupted_query= 0, - ignore_spaces= 0; + ignore_spaces= 0, opt_binhex= 0; static my_bool debug_info_flag, debug_check_flag; static my_bool column_types_flag; static my_bool preserve_comments= 0; @@ -1392,6 +1392,8 @@ static struct my_option my_long_options[] = {"batch", 'B', "Don't use history file. Disable interactive behavior. (Enables --silent.)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"binary-as-hex", 'b', "Print binary data as hex", &opt_binhex, &opt_binhex, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, "Directory for character set files.", &charsets_dir, &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -3101,7 +3103,8 @@ com_go(String *buffer,char *line __attribute__((unused))) print_table_data_html(result); else if (opt_xml) print_table_data_xml(result); - else if (vertical || (auto_vertical_output && (terminal_width < get_result_width(result)))) + else if (vertical || (auto_vertical_output && + (terminal_width < get_result_width(result)))) print_table_data_vertically(result); else if (opt_silent && verbose <= 2 && !output_tables) print_tab_data(result); @@ -3320,6 +3323,41 @@ print_field_types(MYSQL_RES *result) } +/* Used to determine if we should invoke print_as_hex for this field */ + +static bool +is_binary_field(MYSQL_FIELD *field) +{ + if ((field->charsetnr == 63) && + (field->type == MYSQL_TYPE_BIT || + field->type == MYSQL_TYPE_BLOB || + field->type == MYSQL_TYPE_LONG_BLOB || + field->type == MYSQL_TYPE_MEDIUM_BLOB || + field->type == MYSQL_TYPE_TINY_BLOB || + field->type == MYSQL_TYPE_VAR_STRING || + field->type == MYSQL_TYPE_STRING || + field->type == MYSQL_TYPE_VARCHAR || + field->type == MYSQL_TYPE_GEOMETRY)) + return 1; + return 0; +} + + +/* Print binary value as hex literal (0x ...) */ + +static void +print_as_hex(FILE *output_file, const char *str, ulong len, ulong total_bytes_to_send) +{ + const char *ptr= str, *end= ptr+len; + ulong i; + fprintf(output_file, "0x"); + for(; ptr < end; ptr++) + fprintf(output_file, "%02X", *((uchar*)ptr)); + for (i= 2*len+2; i < total_bytes_to_send; i++) + tee_putc((int)' ', output_file); +} + + static void print_table_data(MYSQL_RES *result) { @@ -3346,6 +3384,8 @@ print_table_data(MYSQL_RES *result) length=max(length,field->max_length); if (length < 4 && !IS_NOT_NULL(field->flags)) length=4; // Room for "NULL" + if (opt_binhex && is_binary_field(field)) + length= 2 + length * 2; field->max_length=length; separator.fill(separator.length()+length+2,'-'); separator.append('+'); @@ -3415,7 +3455,9 @@ print_table_data(MYSQL_RES *result) visible_length= charset_info->cset->numcells(charset_info, buffer, buffer + data_length); extra_padding= data_length - visible_length; - if (field_max_length > MAX_COLUMN_LENGTH) + if (opt_binhex && is_binary_field(field)) + print_as_hex(PAGER, cur[off], lengths[off], field_max_length); + else if (field_max_length > MAX_COLUMN_LENGTH) tee_print_sized_data(buffer, data_length, MAX_COLUMN_LENGTH+extra_padding, FALSE); else { @@ -3548,11 +3590,15 @@ print_table_data_html(MYSQL_RES *result) if (interrupted_query) break; ulong *lengths=mysql_fetch_lengths(result); + field= mysql_fetch_fields(result); (void) tee_fputs("<TR>", PAGER); for (uint i=0; i < mysql_num_fields(result); i++) { (void) tee_fputs("<TD>", PAGER); - xmlencode_print(cur[i], lengths[i]); + if (opt_binhex && is_binary_field(&field[i])) + print_as_hex(PAGER, cur[i], lengths[i], lengths[i]); + else + xmlencode_print(cur[i], lengths[i]); (void) tee_fputs("</TD>", PAGER); } (void) tee_fputs("</TR>", PAGER); @@ -3588,7 +3634,10 @@ print_table_data_xml(MYSQL_RES *result) if (cur[i]) { tee_fprintf(PAGER, "\">"); - xmlencode_print(cur[i], lengths[i]); + if (opt_binhex && is_binary_field(&fields[i])) + print_as_hex(PAGER, cur[i], lengths[i], lengths[i]); + else + xmlencode_print(cur[i], lengths[i]); tee_fprintf(PAGER, "</field>\n"); } else @@ -3635,23 +3684,28 @@ print_table_data_vertically(MYSQL_RES *result) { unsigned int i; const char *p; - + if (opt_binhex && is_binary_field(field)) + fprintf(PAGER, "0x"); for (i= 0, p= cur[off]; i < lengths[off]; i+= 1, p+= 1) { - if (*p == '\0') - tee_putc((int)' ', PAGER); + if (opt_binhex && is_binary_field(field)) + fprintf(PAGER, "%02X", *((uchar*)p)); else - tee_putc((int)*p, PAGER); + { + if (*p == '\0') + tee_putc((int)' ', PAGER); + else + tee_putc((int)*p, PAGER); + } } tee_putc('\n', PAGER); } - else + else tee_fprintf(PAGER, "NULL\n"); } } } - /* print_warnings should be called right after executing a statement */ static void print_warnings() @@ -3788,11 +3842,19 @@ print_tab_data(MYSQL_RES *result) while ((cur = mysql_fetch_row(result))) { lengths=mysql_fetch_lengths(result); - safe_put_field(cur[0],lengths[0]); + field= mysql_fetch_fields(result); + if (opt_binhex && is_binary_field(&field[0])) + print_as_hex(PAGER, cur[0], lengths[0], lengths[0]); + else + safe_put_field(cur[0],lengths[0]); + for (uint off=1 ; off < mysql_num_fields(result); off++) { (void) tee_fputs("\t", PAGER); - safe_put_field(cur[off], lengths[off]); + if (opt_binhex && field && is_binary_field(&field[off])) + print_as_hex(PAGER, cur[off], lengths[off], lengths[off]); + else + safe_put_field(cur[off], lengths[off]); } (void) tee_fputs("\n", PAGER); } diff --git a/mysql-test/r/binary_to_hex.result b/mysql-test/r/binary_to_hex.result new file mode 100644 index 00000000000..a6b68834da8 --- /dev/null +++ b/mysql-test/r/binary_to_hex.result @@ -0,0 +1,117 @@ +USE test; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (c1 TINYBLOB, +c2 BLOB, +c3 MEDIUMBLOB, +c4 LONGBLOB, +c5 TEXT, +c6 BIT(1), +c7 CHAR, +c8 VARCHAR(10), +c9 GEOMETRY) CHARACTER SET = binary; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` tinyblob, + `c2` blob, + `c3` mediumblob, + `c4` longblob, + `c5` blob, + `c6` bit(1) DEFAULT NULL, + `c7` binary(1) DEFAULT NULL, + `c8` varbinary(10) DEFAULT NULL, + `c9` geometry DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=binary +INSERT INTO t1 VALUES ('tinyblob-text readable', 'blob-text readable', +'mediumblob-text readable', 'longblob-text readable', +'text readable', b'1', 'c', 'variable', +POINT(1, 1)); +CREATE TABLE t2(id int, `col1` binary(10),`col2` blob); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `id` int(11) DEFAULT NULL, + `col1` binary(10) DEFAULT NULL, + `col2` blob +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +INSERT INTO t2 VALUES (1, X'AB1234', X'123ABC'), (2, X'DE1234', X'123DEF'); +#Print the table contents when binary-as-hex option is off. +SELECT * FROM t1; +c1 c2 c3 c4 c5 c6 c7 c8 c9 +tinyblob-text readable blob-text readable mediumblob-text readable longblob-text readable text readable # c variable # +SELECT * FROM t2; +id col1 col2 +1 # # +2 # # +#Print the table contents after turning on the binary-as-hex option + +#Print the table contents in tab format + +c1 c2 c3 c4 c5 c6 c7 c8 c9 +0x74696E79626C6F622D74657874207265616461626C65 0x626C6F622D74657874207265616461626C65 0x6D656469756D626C6F622D74657874207265616461626C65 0x6C6F6E67626C6F622D74657874207265616461626C65 0x74657874207265616461626C65 0x01 0x63 0x7661726961626C65 0x000000000101000000000000000000F03F000000000000F03F +id col1 col2 +1 0xAB123400000000000000 0x123ABC +2 0xDE123400000000000000 0x123DEF + +#Print the table contents in table format + ++------------------------------------------------+----------------------------------------+----------------------------------------------------+------------------------------------------------+------------------------------+------------+------------+--------------------+------------------------------------------------------+ +| c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | ++------------------------------------------------+----------------------------------------+----------------------------------------------------+------------------------------------------------+------------------------------+------------+------------+--------------------+------------------------------------------------------+ +| 0x74696E79626C6F622D74657874207265616461626C65 | 0x626C6F622D74657874207265616461626C65 | 0x6D656469756D626C6F622D74657874207265616461626C65 | 0x6C6F6E67626C6F622D74657874207265616461626C65 | 0x74657874207265616461626C65 | 0x01 | 0x63 | 0x7661726961626C65 | 0x000000000101000000000000000000F03F000000000000F03F | ++------------------------------------------------+----------------------------------------+----------------------------------------------------+------------------------------------------------+------------------------------+------------+------------+--------------------+------------------------------------------------------+ ++------+------------------------+------------+ +| id | col1 | col2 | ++------+------------------------+------------+ +| 1 | 0xAB123400000000000000 | 0x123ABC | ++------+------------------------+------------+ + +#Print the table contents vertically + +*************************** 1. row *************************** +c1: 0x74696E79626C6F622D74657874207265616461626C65 +c2: 0x626C6F622D74657874207265616461626C65 +c3: 0x6D656469756D626C6F622D74657874207265616461626C65 +c4: 0x6C6F6E67626C6F622D74657874207265616461626C65 +c5: 0x74657874207265616461626C65 +c6: 0x01 +c7: 0x63 +c8: 0x7661726961626C65 +c9: 0x000000000101000000000000000000F03F000000000000F03F + +#Print the table contents in xml format + +<?xml version="1.0"?> + +<resultset statement="SELECT * FROM t1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <row> + <field name="c1">0x74696E79626C6F622D74657874207265616461626C65</field> + <field name="c2">0x626C6F622D74657874207265616461626C65</field> + <field name="c3">0x6D656469756D626C6F622D74657874207265616461626C65</field> + <field name="c4">0x6C6F6E67626C6F622D74657874207265616461626C65</field> + <field name="c5">0x74657874207265616461626C65</field> + <field name="c6">0x01</field> + <field name="c7">0x63</field> + <field name="c8">0x7661726961626C65</field> + <field name="c9">0x000000000101000000000000000000F03F000000000000F03F</field> + </row> +</resultset> +<?xml version="1.0"?> + +<resultset statement="SELECT * FROM t2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <row> + <field name="id">1</field> + <field name="col1">0xAB123400000000000000</field> + <field name="col2">0x123ABC</field> + </row> + + <row> + <field name="id">2</field> + <field name="col1">0xDE123400000000000000</field> + <field name="col2">0x123DEF</field> + </row> +</resultset> + +#Print the table contents in html format + +<TABLE BORDER=1><TR><TH>c1</TH><TH>c2</TH><TH>c3</TH><TH>c4</TH><TH>c5</TH><TH>c6</TH><TH>c7</TH><TH>c8</TH><TH>c9</TH></TR><TR><TD>0x74696E79626C6F622D74657874207265616461626C65</TD><TD>0x626C6F622D74657874207265616461626C65</TD><TD>0x6D656469756D626C6F622D74657874207265616461626C65</TD><TD>0x6C6F6E67626C6F622D74657874207265616461626C65</TD><TD>0x74657874207265616461626C65</TD><TD>0x01</TD><TD>0x63</TD><TD>0x7661726961626C65</TD><TD>0x000000000101000000000000000000F03F000000000000F03F</TD></TR></TABLE><TABLE BORDER=1><TR><TH>id</TH><TH>col1</TH><TH>col2</TH></TR><TR><TD>1</TD><TD>0xAB123400000000000000</TD><TD>0x123ABC</TD></TR><TR><TD>2</TD><TD>0xDE123400000000000000</TD><TD>0x123DEF</TD></TR></TABLE>DROP TABLE t1, t2; diff --git a/mysql-test/t/binary_to_hex.test b/mysql-test/t/binary_to_hex.test new file mode 100644 index 00000000000..8312a246d0c --- /dev/null +++ b/mysql-test/t/binary_to_hex.test @@ -0,0 +1,76 @@ +# === Purpose === +# The purpose of this test case is to make +# sure that the binary data in tables is printed +# as hex when the option binary-as-hex is enabled. +# +# === Related bugs and/or worklogs === +# Bug #25340722 - PRINT BINARY DATA AS HEX IN THE MYSQL +# CLIENT (CONTRIBUTION) +# + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc +--source include/not_embedded.inc + +USE test; +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 (c1 TINYBLOB, + c2 BLOB, + c3 MEDIUMBLOB, + c4 LONGBLOB, + c5 TEXT, + c6 BIT(1), + c7 CHAR, + c8 VARCHAR(10), + c9 GEOMETRY) CHARACTER SET = binary; + +SHOW CREATE TABLE t1; + +INSERT INTO t1 VALUES ('tinyblob-text readable', 'blob-text readable', + 'mediumblob-text readable', 'longblob-text readable', + 'text readable', b'1', 'c', 'variable', + POINT(1, 1)); + +CREATE TABLE t2(id int, `col1` binary(10),`col2` blob); + +SHOW CREATE TABLE t2; + +INSERT INTO t2 VALUES (1, X'AB1234', X'123ABC'), (2, X'DE1234', X'123DEF'); + +--echo #Print the table contents when binary-as-hex option is off. +--replace_column 6 # 9 # +SELECT * FROM t1; + +--replace_column 2 # 3 # +SELECT * FROM t2; + +--echo #Print the table contents after turning on the binary-as-hex option +--echo +--echo #Print the table contents in tab format +--echo +--exec $MYSQL test --binary-as-hex -e "SELECT * FROM t1; SELECT * FROM t2;" +--echo +--echo #Print the table contents in table format +--echo +--exec $MYSQL test --binary-as-hex --table -e "SELECT * FROM t1; SELECT * FROM t2 WHERE col2=0x123ABC;" +--echo +--echo #Print the table contents vertically +--echo +--exec $MYSQL test --binary-as-hex --vertical -e "SELECT * FROM t1;" +--echo +--echo #Print the table contents in xml format +--echo +--exec $MYSQL test --binary-as-hex --xml -e "SELECT * FROM t1; SELECT * FROM t2;" +--echo +--echo #Print the table contents in html format +--echo +--exec $MYSQL test --binary-as-hex --html -e "SELECT * FROM t1; SELECT * FROM t2;" + +#Cleanup +DROP TABLE t1, t2; + +# Wait till all disconnects are completed + --source include/wait_until_count_sessions.inc |