diff options
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r-- | sql/sql_lex.cc | 84 |
1 files changed, 60 insertions, 24 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a3c3db8947e..42a8a700da3 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,15 +1,15 @@ /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ @@ -142,20 +142,22 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) lex->next_state=STATE_START; lex->end_of_query=(lex->ptr=buf)+length; lex->yylineno = 1; - lex->create_refs=lex->in_comment=0; + lex->select->create_refs=lex->in_comment=0; lex->length=0; - lex->in_sum_expr=0; - lex->expr_list.empty(); - lex->ftfunc_list.empty(); - lex->convert_set=thd->convert_set; + lex->select->in_sum_expr=0; + lex->select->expr_list.empty(); + lex->select->ftfunc_list.empty(); + lex->convert_set=(lex->thd=thd)->convert_set; lex->yacc_yyss=lex->yacc_yyvs=0; lex->ignore_space=test(thd->sql_mode & MODE_IGNORE_SPACE); + lex->slave_thd_opt=0; + bzero(&lex->mi,sizeof(lex->mi)); return lex; } void lex_end(LEX *lex) { - lex->expr_list.delete_elements(); // If error when parsing sql-varargs + lex->select->expr_list.delete_elements(); // If error when parsing sql-varargs x_free(lex->yacc_yyss); x_free(lex->yacc_yyvs); } @@ -196,12 +198,12 @@ static int find_keyword(LEX *lex, uint len, bool function) /* make a copy of token before ptr and set yytoklen */ -static inline LEX_STRING get_token(LEX *lex,uint length) +LEX_STRING get_token(LEX *lex,uint length) { LEX_STRING tmp; yyUnget(); // ptr points now after last token char tmp.length=lex->yytoklen=length; - tmp.str=(char*) sql_strmake((char*) lex->tok_start,tmp.length); + tmp.str=(char*) lex->thd->strmake((char*) lex->tok_start,tmp.length); return tmp; } @@ -250,7 +252,7 @@ static char *get_text(LEX *lex) str=lex->tok_start+1; end=lex->ptr-1; - if (!(start=(uchar*) sql_alloc((uint) (end-str)+1))) + if (!(start=(uchar*) lex->thd->alloc((uint) (end-str)+1))) return (char*) ""; // Sql_alloc has set error flag if (!found_escape) { @@ -337,7 +339,8 @@ static const char *longlong_str="9223372036854775807"; static const uint longlong_len=19; static const char *signed_longlong_str="-9223372036854775808"; static const uint signed_longlong_len=19; - +static const char *unsigned_longlong_str="18446744073709551615"; +static const uint unsigned_longlong_len=20; inline static uint int_token(const char *str,uint length) { @@ -393,7 +396,13 @@ inline static uint int_token(const char *str,uint length) else if (length < longlong_len) return LONG_NUM; else if (length > longlong_len) - return REAL_NUM; + { + if (length > unsigned_longlong_len) + return REAL_NUM; + cmp=unsigned_longlong_str; + smaller=ULONGLONG_NUM; + bigger=REAL_NUM; + } else { cmp=longlong_str; @@ -430,7 +439,7 @@ int yylex(void *arg) switch(state) { case STATE_OPERATOR_OR_IDENT: // Next is operator or keyword case STATE_START: // Start of token - // Skipp startspace + // Skip startspace for (c=yyGet() ; (state_map[c] == STATE_SKIP) ; c= yyGet()) { if (c == '\n') @@ -458,6 +467,11 @@ int yylex(void *arg) return((int) c); case STATE_IDENT: // Incomplete keyword or ident + if ((c == 'x' || c == 'X') && yyPeek() == '\'') + { // Found x'hex-number' + state=STATE_HEX_NUMBER; + break; + } #if defined(USE_MB) && defined(USE_MB_IDENT) if (use_mb(default_charset_info)) { @@ -509,6 +523,8 @@ int yylex(void *arg) yySkip(); // next state does a unget } yylval->lex_str=get_token(lex,length); + if (lex->convert_set) + lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); return(IDENT); case STATE_IDENT_SEP: // Found ident and now '.' @@ -518,7 +534,7 @@ int yylex(void *arg) c=yyGet(); // should be '.' return((int) c); - case STATE_NUMBER_IDENT: // number or ident which starts with num + case STATE_NUMBER_IDENT: // number or ident which num-start while (isdigit((c = yyGet()))) ; if (state_map[c] != STATE_IDENT) { // Can't be identifier @@ -544,10 +560,10 @@ int yylex(void *arg) lex->tok_start[0] == '0' ) { // Varbinary while (isxdigit((c = yyGet()))) ; - if ((lex->ptr - lex->tok_start) >= 4) + if ((lex->ptr - lex->tok_start) >= 4 && state_map[c] != STATE_IDENT) { yylval->lex_str=get_token(lex,yyLength()); - yylval->lex_str.str+=2; // Skipp 0x + yylval->lex_str.str+=2; // Skip 0x yylval->lex_str.length-=2; lex->yytoklen-=2; return (HEX_NUM); @@ -597,10 +613,12 @@ int yylex(void *arg) case STATE_FOUND_IDENT: // Complete ident yylval->lex_str=get_token(lex,yyLength()); + if (lex->convert_set) + lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); return(IDENT); case STATE_USER_VARIABLE_DELIMITER: - lex->tok_start=lex->ptr; // Skipp first ` + lex->tok_start=lex->ptr; // Skip first ` #ifdef USE_MB if (use_mb(default_charset_info)) { @@ -625,14 +643,17 @@ int yylex(void *arg) c != (uchar) NAMES_SEP_CHAR) ; } yylval->lex_str=get_token(lex,yyLength()); + if (lex->convert_set) + lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); if (state_map[c] == STATE_USER_VARIABLE_DELIMITER) - yySkip(); // Skipp end ` + yySkip(); // Skip end ` return(IDENT); case STATE_SIGNED_NUMBER: // Incomplete signed number if (prev_state == STATE_OPERATOR_OR_IDENT) { - if (c == '-' && yyPeek() == '-' && isspace(yyPeek2())) + if (c == '-' && yyPeek() == '-' && + (isspace(yyPeek2()) || iscntrl(yyPeek2()))) state=STATE_COMMENT; else state= STATE_CHAR; // Must be operator @@ -672,7 +693,7 @@ int yylex(void *arg) { c = yyGet(); if (c == '-' || c == '+') - c = yyGet(); // Skipp sign + c = yyGet(); // Skip sign if (!isdigit(c)) { // No digit after sign state= STATE_CHAR; @@ -685,6 +706,21 @@ int yylex(void *arg) yylval->lex_str=get_token(lex,yyLength()); return(REAL_NUM); + case STATE_HEX_NUMBER: // Found x'hexstring' + yyGet(); // Skip ' + while (isxdigit((c = yyGet()))) ; + length=(lex->ptr - lex->tok_start); // Length of hexnum+3 + if (!(length & 1) || c != '\'') + { + return(ABORT_SYM); // Illegal hex constant + } + yyGet(); // get_token makes an unget + yylval->lex_str=get_token(lex,length); + yylval->lex_str.str+=2; // Skip x' + yylval->lex_str.length-=3; // Don't count x' and last ' + lex->yytoklen-=3; + return (HEX_NUM); + case STATE_CMP_OP: // Incomplete comparison operator if (state_map[yyPeek()] == STATE_CMP_OP || state_map[yyPeek()] == STATE_LONG_CMP_OP) @@ -734,7 +770,7 @@ int yylex(void *arg) return(TEXT_STRING); case STATE_COMMENT: // Comment - lex->options|= OPTION_FOUND_COMMENT; + lex->select_lex.options|= OPTION_FOUND_COMMENT; while ((c = yyGet()) != '\n' && c) ; yyUnget(); // Safety against eof state = STATE_START; // Try again @@ -746,7 +782,7 @@ int yylex(void *arg) break; } yySkip(); // Skip '*' - lex->options|= OPTION_FOUND_COMMENT; + lex->select_lex.options|= OPTION_FOUND_COMMENT; if (yyPeek() == '!') // MySQL command in comment { ulong version=MYSQL_VERSION_ID; |