diff options
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r-- | sql/sql_lex.cc | 78 |
1 files changed, 48 insertions, 30 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 352a79843a9..cc9cedbfad6 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -40,10 +40,18 @@ LEX_STRING tmp_table_alias= {(char*) "tmp-table",8}; pthread_key(LEX*,THR_LEX); +/* Longest standard keyword name */ #define TOCK_NAME_LENGTH 24 /* - The following is based on the latin1 character set, and is only + Map to default keyword characters. This is used to test if an identifer + is 'simple', in which case we don't have to do any character set conversions + on it +*/ +uchar *bin_ident_map= my_charset_bin.ident_map; + +/* + The following data is based on the latin1 character set, and is only used when comparing keywords */ @@ -66,6 +74,7 @@ uchar to_upper_lex[] = { 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255 }; + inline int lex_casecmp(const char *s, const char *t, uint len) { while (len-- != 0 && @@ -410,15 +419,18 @@ inline static uint int_token(const char *str,uint length) } -// yylex remember the following states from the following yylex() -// MY_LEX_EOQ ; found end of query -// MY_LEX_OPERATOR_OR_IDENT ; last state was an ident, text or number -// (which can't be followed by a signed number) +/* + yylex remember the following states from the following yylex() + + - MY_LEX_EOQ Found end of query + - MY_LEX_OPERATOR_OR_IDENT Last state was an ident, text or number + (which can't be followed by a signed number) +*/ int yylex(void *arg, void *yythd) { reg1 uchar c; - int tokval; + int tokval, result_state; uint length; enum my_lex_states state,prev_state; LEX *lex= &(((THD *)yythd)->lex); @@ -503,6 +515,7 @@ int yylex(void *arg, void *yythd) #if defined(USE_MB) && defined(USE_MB_IDENT) if (use_mb(cs)) { + result_state= IDENT_QUOTED; if (my_mbcharlen(cs, yyGetLast()) > 1) { int l = my_ismbchar(cs, @@ -529,7 +542,15 @@ int yylex(void *arg, void *yythd) } else #endif - while (ident_map[c=yyGet()]) ; + { + result_state= bin_ident_map[c] ? IDENT : IDENT_QUOTED; + while (ident_map[c=yyGet()]) + { + /* If not simple character, mark that we must convert it */ + if (!bin_ident_map[c]) + result_state= IDENT_QUOTED; + } + } length= (uint) (lex->ptr - lex->tok_start)-1; if (lex->ignore_space) { @@ -560,8 +581,7 @@ int yylex(void *arg, void *yythd) (lex->charset=get_charset_by_csname(yylval->lex_str.str+1, MY_CS_PRIMARY,MYF(0)))) return(UNDERSCORE_CHARSET); - else - return(IDENT); + return(result_state); // IDENT or IDENT_QUOTED case MY_LEX_IDENT_SEP: // Found ident and now '.' yylval->lex_str.str=(char*) lex->ptr; @@ -611,21 +631,11 @@ int yylex(void *arg, void *yythd) } // fall through case MY_LEX_IDENT_START: // We come here after '.' + result_state= IDENT; #if defined(USE_MB) && defined(USE_MB_IDENT) if (use_mb(cs)) { - if (my_mbcharlen(cs, yyGetLast()) > 1) - { - int l = my_ismbchar(cs, - (const char *)lex->ptr-1, - (const char *)lex->end_of_query); - if (l == 0) - { - state = MY_LEX_CHAR; - continue; - } - lex->ptr += l - 1; - } + result_state= IDENT_QUOTED; while (ident_map[c=yyGet()]) { if (my_mbcharlen(cs, c) > 1) @@ -641,15 +651,17 @@ int yylex(void *arg, void *yythd) } else #endif - while (ident_map[c = yyGet()]) ; - + while (ident_map[c = yyGet()]) + { + /* If not simple character, mark that we must convert it */ + if (!bin_ident_map[c]) + result_state= IDENT_QUOTED; + } if (c == '.' && ident_map[yyPeek()]) lex->next_state=MY_LEX_IDENT_SEP;// Next is '.' - // fall through - case MY_LEX_FOUND_IDENT: // Complete ident - yylval->lex_str=get_token(lex,yyLength()); - return(IDENT); + yylval->lex_str= get_token(lex,yyLength()); + return(result_state); case MY_LEX_USER_VARIABLE_DELIMITER: { @@ -699,7 +711,7 @@ int yylex(void *arg, void *yythd) if (c == delim) yySkip(); // Skip end ` lex->next_state= MY_LEX_START; - return(IDENT); + return(IDENT_QUOTED); } case MY_LEX_INT_OR_REAL: // Compleat int or incompleat real if (c != '.') @@ -924,7 +936,13 @@ int yylex(void *arg, void *yythd) We should now be able to handle: [(global | local | session) .]variable_name */ - while (ident_map[c=yyGet()]) ; + result_state= IDENT; + while (ident_map[c=yyGet()]) + { + /* If not simple character, mark that we must convert it */ + if (!bin_ident_map[c]) + result_state= IDENT_QUOTED; + } if (c == '.') lex->next_state=MY_LEX_IDENT_SEP; length= (uint) (lex->ptr - lex->tok_start)-1; @@ -934,7 +952,7 @@ int yylex(void *arg, void *yythd) return(tokval); // Was keyword } yylval->lex_str=get_token(lex,length); - return(IDENT); + return(result_state); } } } |