#At file:///home/mysql_src/bzrrepos_new/bar/ based on revid:alexander.barkov@stripped
3358 Guilhem Bichot 2011-03-03
Suggestion of refactoring in the context of Bug 11764503 (Bug 57341)
"Query in EXPLAIN EXTENDED shows wrong characters".
Item_string::print() is hard to understand because of the different
QT_ constants: in "query_type==QT_x", QT_x is explicitely included
but the other two QT_ are implicitely excluded. The combinations
with '||' and '&&' make this even harder. Proposal:
- Make logic more "explicit" by changing QT_ constants to a bitmap of flags:
QT_ORDINARY: no change,
QT_IS -> QT_TO_SYSTEM_CHARSET | QT_WITHOUT_INTRODUCERS,
QT_EXPLAIN -> QT_TO_SYSTEM_CHARSET.
- Rewrite Item_string::print() using those flags
- Comments.
This patch shouldn't change anything as far results are concerned.
Full test suite has been run.
modified:
sql/item.cc
sql/mysqld.h
sql/sql_parse.cc
sql/sql_view.cc
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2011-03-01 10:17:10 +0000
+++ b/sql/item.cc 2011-03-03 09:54:52 +0000
@@ -2514,8 +2514,9 @@ my_decimal *Item_float::val_decimal(my_d
void Item_string::print(String *str, enum_query_type query_type)
{
- if ((query_type == QT_ORDINARY || query_type == QT_EXPLAIN) &&
- 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);
@@ -2523,33 +2524,52 @@ void Item_string::print(String *str, enu
str->append('\'');
- if (query_type == QT_EXPLAIN && is_cs_specified())
+ if (query_type & QT_TO_SYSTEM_CHARSET)
{
- /* Print ASCII as is, print extended characters using \xFF sequences */
- ErrConvString tmp(str_value.ptr(), str_value.length(), &my_charset_bin);
- str->append(tmp.ptr());
- }
- else if (query_type == QT_ORDINARY ||
- my_charset_same(str_value.charset(), system_charset_info))
- {
- str_value.print(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());
+
+ String utf8_str(utf8_lex_str.str,
+ utf8_lex_str.length,
+ system_charset_info);
+
+ utf8_str.print(str);
+ }
+ }
}
else
{
- 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());
-
- String utf8_str(utf8_lex_str.str,
- utf8_lex_str.length,
- system_charset_info);
-
- utf8_str.print(str);
+ // Caller wants a result in the charset of str_value.
+ str_value.print(str);
}
str->append('\'');
=== modified file 'sql/mysqld.h'
--- a/sql/mysqld.h 2011-03-01 10:17:10 +0000
+++ b/sql/mysqld.h 2011-03-03 09:54:52 +0000
@@ -399,19 +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).
- QT_EXPLAIN -- SQL query to be shown in EXPLAIN SELECT EXTENDED (with
- introducers and \xFF escape sequences for extended characters)
+ Query type constants (usable as bitmap flags).
*/
enum enum_query_type
{
- QT_ORDINARY,
- QT_IS,
- QT_EXPLAIN
+ /// 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 */
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2011-03-01 10:17:10 +0000
+++ b/sql/sql_parse.cc 2011-03-03 09:54:52 +0000
@@ -4439,7 +4439,11 @@ static bool execute_sqlcom_select(THD *t
char buff[1024];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
- thd->lex->unit.print(&str, QT_EXPLAIN);
+ /*
+ 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());
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2011-02-08 15:47:33 +0000
+++ b/sql/sql_view.cc 2011-03-03 09:54:52 +0000
@@ -841,7 +841,8 @@ static int mysql_register_view(THD *thd,
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;
}
Attachment: [text/bzr-bundle] bzr/guilhem.bichot@oracle.com-20110303095452-frwx787wv0gb4or8.bundle
| Thread |
|---|
| • bzr commit into mysql-5.5 branch (guilhem.bichot:3358) | Guilhem Bichot | 3 Mar |