summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/ctype_latin1.result15
-rw-r--r--mysql-test/r/ctype_utf8.result15
-rw-r--r--mysql-test/t/ctype_latin1.test15
-rw-r--r--mysql-test/t/ctype_utf8.test10
-rw-r--r--sql/item.cc63
-rw-r--r--sql/mysqld.h14
-rw-r--r--sql/sql_parse.cc6
-rw-r--r--sql/sql_view.cc3
8 files changed, 114 insertions, 27 deletions
diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result
index 6f773270dff..7a8f07e912b 100644
--- a/mysql-test/r/ctype_latin1.result
+++ b/mysql-test/r/ctype_latin1.result
@@ -3246,5 +3246,20 @@ maketime(`a`,`a`,`a`)
DROP TABLE t1;
SET sql_mode=default;
#
+# Bug#11764503 (Bug#57341) Query in EXPLAIN EXTENDED shows wrong characters
+#
+SET NAMES utf8;
+EXPLAIN EXTENDED SELECT 'abcdó', _latin1'abcdó', _utf8'abcdó';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select 'abcdó' AS `abcdó`,_latin1'abcd\xC3\xB3' AS `abcdó`,_utf8'abcd\xC3\xB3' AS `abcdó`
+SET NAMES latin1;
+EXPLAIN EXTENDED SELECT 'abcdó', _latin1'abcdó', _utf8'abcdó';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select 'abcdó' AS `abcdó`,_latin1'abcd\xC3\xB3' AS `abcdó`,_utf8'abcd\xC3\xB3' AS `abcd`
+#
# End of 5.5 tests
#
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index ababfe51621..ea6f00e2581 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -4969,5 +4969,20 @@ GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size));
ERROR 23000: Duplicate entry '107374182410737418241' for key 'group_key'
DROP TABLE t1;
#
+# Bug#11764503 (Bug#57341) Query in EXPLAIN EXTENDED shows wrong characters
+#
+SET NAMES latin1;
+EXPLAIN EXTENDED SELECT 'abcdÁÂÃÄÅ', _latin1'abcdÁÂÃÄÅ', _utf8'abcdÁÂÃÄÅ' AS u;
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select 'abcdÁÂÃÄÅ' AS `abcdÁÂÃÄÅ`,_latin1'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `abcdÁÂÃÄÅ`,_utf8'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `u`
+SET NAMES utf8;
+EXPLAIN EXTENDED SELECT 'abcdÁÂÃÄÅ', _latin1'abcdÁÂÃÄÅ', _utf8'abcdÁÂÃÄÅ';
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select 'abcdÁÂÃÄÅ' AS `abcdÁÂÃÄÅ`,_latin1'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `abcdÁÂÃÄÅ`,_utf8'abcd\xC3\x81\xC3\x82\xC3\x83\xC3\x84\xC3\x85' AS `abcdÁÂÃÄÅ`
+#
# End of 5.5 tests
#
diff --git a/mysql-test/t/ctype_latin1.test b/mysql-test/t/ctype_latin1.test
index b8aae2eae40..5d1acf107d7 100644
--- a/mysql-test/t/ctype_latin1.test
+++ b/mysql-test/t/ctype_latin1.test
@@ -144,5 +144,20 @@ SELECT '' LIKE '' ESCAPE EXPORT_SET(1, 1, 1, 1, '');
--source include/ctype_numconv.inc
--echo #
+--echo # Bug#11764503 (Bug#57341) Query in EXPLAIN EXTENDED shows wrong characters
+--echo #
+# Test latin1 client erroneously started with --default-character-set=utf8
+# EXPLAIN output should still be pretty readable.
+# We're using 'ó' (\xC3\xB3) as a magic sequence:
+# - it's "LATIN CAPITAL LETTER A WITH TILDE ABOVE + SUPERSCRIPT 3" in latin1
+# - it's "LATIN SMALL LETTER O WITH ACUTE ABOVE" in utf8.
+SET NAMES utf8;
+EXPLAIN EXTENDED SELECT 'abcdó', _latin1'abcdó', _utf8'abcdó';
+# Test normal latin1
+SET NAMES latin1;
+EXPLAIN EXTENDED SELECT 'abcdó', _latin1'abcdó', _utf8'abcdó';
+
+
+--echo #
--echo # End of 5.5 tests
--echo #
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 2aea21afe68..a519a417192 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1550,6 +1550,16 @@ SELECT COUNT(*) FROM t1, t1 t2
GROUP BY INSERT('', t2.a, t1.a, (@@global.max_binlog_size));
DROP TABLE t1;
+--echo #
+--echo # Bug#11764503 (Bug#57341) Query in EXPLAIN EXTENDED shows wrong characters
+--echo #
+# Emulate utf8 client erroneously started with --default-character-set=latin1,
+# as in the bug report. EXPLAIN output should still be pretty readable
+SET NAMES latin1;
+EXPLAIN EXTENDED SELECT 'abcdÁÂÃÄÅ', _latin1'abcdÁÂÃÄÅ', _utf8'abcdÁÂÃÄÅ' AS u;
+# Test normal utf8
+SET NAMES utf8;
+EXPLAIN EXTENDED SELECT 'abcdÁÂÃÄÅ', _latin1'abcdÁÂÃÄÅ', _utf8'abcdÁÂÃÄÅ';
--echo #
--echo # End of 5.5 tests
diff --git a/sql/item.cc b/sql/item.cc
index c7787d65c22..2090a1e4eda 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2514,7 +2514,9 @@ my_decimal *Item_float::val_decimal(my_decimal *decimal_value)
void Item_string::print(String *str, enum_query_type query_type)
{
- if (query_type == QT_ORDINARY && is_cs_specified())
+ const bool print_introducer=
+ !(query_type & QT_WITHOUT_INTRODUCERS) && is_cs_specified();
+ if (print_introducer)
{
str->append('_');
str->append(collation.collation->csname);
@@ -2522,27 +2524,52 @@ void Item_string::print(String *str, enum_query_type query_type)
str->append('\'');
- if (query_type == QT_ORDINARY ||
- my_charset_same(str_value.charset(), system_charset_info))
+ if (query_type & QT_TO_SYSTEM_CHARSET)
{
- str_value.print(str);
- }
- else
- {
- THD *thd= current_thd;
- LEX_STRING utf8_lex_str;
+ if (print_introducer)
+ {
+ /*
+ Because we wrote an introducer, we must print str_value in its
+ charset, and the resulting bytes must not be changed until they
+ reach the end client.
+ But the caller is asking for system_charset_info, and may later
+ convert into character_set_results. That means two conversions: we
+ must ensure that they don't change our printed bytes.
+ So we print str_value in the least common denominator of the three
+ charsets involved: ASCII. Non-ASCII characters are printed as \xFF
+ sequences (which is ASCII too). This way, our bytes will not be
+ changed.
+ */
+ ErrConvString tmp(str_value.ptr(), str_value.length(), &my_charset_bin);
+ str->append(tmp.ptr());
+ }
+ else
+ {
+ if (my_charset_same(str_value.charset(), system_charset_info))
+ str_value.print(str); // already in system_charset_info
+ else // need to convert
+ {
+ THD *thd= current_thd;
+ LEX_STRING utf8_lex_str;
- thd->convert_string(&utf8_lex_str,
- system_charset_info,
- str_value.c_ptr_safe(),
- str_value.length(),
- str_value.charset());
+ thd->convert_string(&utf8_lex_str,
+ system_charset_info,
+ str_value.c_ptr_safe(),
+ str_value.length(),
+ str_value.charset());
- String utf8_str(utf8_lex_str.str,
- utf8_lex_str.length,
- system_charset_info);
+ String utf8_str(utf8_lex_str.str,
+ utf8_lex_str.length,
+ system_charset_info);
- utf8_str.print(str);
+ utf8_str.print(str);
+ }
+ }
+ }
+ else
+ {
+ // Caller wants a result in the charset of str_value.
+ str_value.print(str);
}
str->append('\'');
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 2099e57e96d..5af1260ecbc 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -399,16 +399,16 @@ enum options_mysqld
/**
- Query type constants.
-
- QT_ORDINARY -- ordinary SQL query.
- QT_IS -- SQL query to be shown in INFORMATION_SCHEMA (in utf8 and without
- character set introducers).
+ Query type constants (usable as bitmap flags).
*/
enum enum_query_type
{
- QT_ORDINARY,
- QT_IS
+ /// Nothing specific, ordinary SQL query.
+ QT_ORDINARY= 0,
+ /// In utf8.
+ QT_TO_SYSTEM_CHARSET= (1 << 0),
+ /// Without character set introducers.
+ QT_WITHOUT_INTRODUCERS= (1 << 1)
};
/* query_id */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d9e1245bf66..367699ea6cb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4439,7 +4439,11 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
char buff[1024];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
- thd->lex->unit.print(&str, QT_ORDINARY);
+ /*
+ The warnings system requires input in utf8, @see
+ mysqld_show_warnings().
+ */
+ thd->lex->unit.print(&str, QT_TO_SYSTEM_CHARSET);
str.append('\0');
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_YES, str.ptr());
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 17b8056a165..6051aa028c7 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -841,7 +841,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
lex->unit.print(&view_query, QT_ORDINARY);
- lex->unit.print(&is_query, QT_IS);
+ lex->unit.print(&is_query,
+ enum_query_type(QT_TO_SYSTEM_CHARSET | QT_WITHOUT_INTRODUCERS));
thd->variables.sql_mode|= sql_mode;
}