diff options
-rw-r--r-- | mysql-test/r/show_check.result | 48 | ||||
-rw-r--r-- | mysql-test/t/show_check.test | 40 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 18 | ||||
-rw-r--r-- | sql/sql_show.cc | 76 |
5 files changed, 175 insertions, 9 deletions
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 290f916ae72..235c6cd0ecf 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -265,3 +265,51 @@ c decimal(4,3) YES NULL d double(4,3) YES NULL f float(4,3) YES NULL drop table t1; +SET sql_mode=''; +SET sql_quote_show_create=OFF; +CREATE TABLE ```ab``cd``` (i INT); +SHOW CREATE TABLE ```ab``cd```; +Table Create Table +`ab`cd` CREATE TABLE ```ab``cd``` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE ```ab``cd```; +CREATE TABLE ```ab````cd``` (i INT); +SHOW CREATE TABLE ```ab````cd```; +Table Create Table +`ab``cd` CREATE TABLE ```ab````cd``` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE ```ab````cd```; +CREATE TABLE ```a` (i INT); +SHOW CREATE TABLE ```a`; +Table Create Table +`a CREATE TABLE ```a` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE ```a`; +SET sql_mode='ANSI_QUOTES'; +CREATE TABLE """a" (i INT); +SHOW CREATE TABLE """a"; +Table Create Table +"a CREATE TABLE """a" ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE """a"; +SET sql_mode=''; +SET sql_quote_show_create=OFF; +CREATE TABLE t1 (i INT); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE t1 ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE `table` (i INT); +SHOW CREATE TABLE `table`; +Table Create Table +table CREATE TABLE `table` ( + i int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE `table`; +SET sql_quote_show_create=ON; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index d262f02c978..1d64cfd2105 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -142,3 +142,43 @@ drop table t1; create table t1 (c decimal(3,3), d double(3,3), f float(3,3)); show columns from t1; drop table t1; + +# +# Test for Bug #2593 "SHOW CREATE TABLE doesn't properly double quotes" +# + +SET sql_mode=''; +SET sql_quote_show_create=OFF; + +CREATE TABLE ```ab``cd``` (i INT); +SHOW CREATE TABLE ```ab``cd```; +DROP TABLE ```ab``cd```; + +CREATE TABLE ```ab````cd``` (i INT); +SHOW CREATE TABLE ```ab````cd```; +DROP TABLE ```ab````cd```; + +CREATE TABLE ```a` (i INT); +SHOW CREATE TABLE ```a`; +DROP TABLE ```a`; + +SET sql_mode='ANSI_QUOTES'; + +CREATE TABLE """a" (i INT); +SHOW CREATE TABLE """a"; +DROP TABLE """a"; + +# to test quotes around keywords.. : + +SET sql_mode=''; +SET sql_quote_show_create=OFF; + +CREATE TABLE t1 (i INT); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE `table` (i INT); +SHOW CREATE TABLE `table`; +DROP TABLE `table`; + +SET sql_quote_show_create=ON; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 73e30e72a3c..c79c942979a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -761,6 +761,8 @@ uint find_type(TYPELIB *lib, const char *find, uint length, bool part_match); uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); +bool is_keyword(const char *name, uint len); + /* sql_parse.cc */ void free_items(Item *item); void cleanup_items(Item *item); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 70c69bb7389..b5988dac40c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -181,6 +181,23 @@ static int find_keyword(LEX *lex, uint len, bool function) return 0; } +/* + Check if name is a keyword + + SYNOPSIS + is_keyword() + name checked name + len length of checked name + + RETURN VALUES + 0 name is a keyword + 1 name isn't a keyword +*/ + +bool is_keyword(const char *name, uint len) +{ + return get_hash_symbol(name,len,0)!=0; +} /* make a copy of token before ptr and set yytoklen */ @@ -427,7 +444,6 @@ inline static uint int_token(const char *str,uint length) return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger; } - /* yylex remember the following states from the following yylex() diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 4da2522bd3f..f076e2fe802 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1085,8 +1085,7 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } -/* possible TODO: call find_keyword() from sql_lex.cc here */ -static bool require_quotes(const char *name, uint length) +static inline const char *require_quotes(const char *name, uint length) { uint i, d, c; for (i=0; i<length; i+=d) @@ -1094,7 +1093,37 @@ static bool require_quotes(const char *name, uint length) c=((uchar *)name)[i]; d=my_mbcharlen(system_charset_info, c); if (d==1 && !system_charset_info->ident_map[c]) - return 1; + return name+i; + } + return 0; +} + +/* + Looking for char in multibyte string + + SYNOPSIS + look_for_char() + name string for looking at + length length of name + q '\'' or '\"' for looking for + + RETURN VALUES + # pointer to found char in string + 0 string doesn't contain required char +*/ + +static inline const char *look_for_char(const char *name, + uint length, char q) +{ + const char *cur= name; + const char *end= cur+length; + uint symbol_length; + for (; cur<end; cur+= symbol_length) + { + char c= *cur; + symbol_length= my_mbcharlen(system_charset_info, c); + if (symbol_length==1 && c==q) + return cur; } return 0; } @@ -1103,21 +1132,52 @@ void append_identifier(THD *thd, String *packet, const char *name, uint length) { char qtype; + uint part_len; + const char *qplace; if (thd->variables.sql_mode & MODE_ANSI_QUOTES) qtype= '\"'; else qtype= '`'; - if ((thd->options & OPTION_QUOTE_SHOW_CREATE) || - require_quotes(name, length)) + if (is_keyword(name,length)) { - packet->append(&qtype, 1); + packet->append(&qtype, 1, system_charset_info); packet->append(name, length, system_charset_info); - packet->append(&qtype, 1); + packet->append(&qtype, 1, system_charset_info); } else { - packet->append(name, length, system_charset_info); + if (!(qplace= require_quotes(name, length))) + { + if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) + packet->append(name, length, system_charset_info); + else + { + packet->append(&qtype, 1, system_charset_info); + packet->append(name, length, system_charset_info); + packet->append(&qtype, 1, system_charset_info); + } + } + else + { + packet->shrink(packet->length()+length+2); + packet->append(&qtype, 1, system_charset_info); + if (*qplace != qtype) + qplace= look_for_char(qplace+1,length-(qplace-name)-1,qtype); + while (qplace) + { + if ((part_len= qplace-name)) + { + packet->append(name, part_len, system_charset_info); + length-= part_len; + } + packet->append(qplace, 1, system_charset_info); + name= qplace; + qplace= look_for_char(name+1,length-1,qtype); + } + packet->append(name, length, system_charset_info); + packet->append(&qtype, 1, system_charset_info); + } } } |