diff options
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r-- | sql/sql_lex.cc | 294 |
1 files changed, 187 insertions, 107 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7bcdc499011..65e5f8035e4 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -28,14 +28,15 @@ We are using pointer to this variable for distinguishing between assignment to NEW row field (when parsing trigger definition) and structured variable. */ -sys_var_long_ptr trg_new_row_fake_var(0, 0); + +sys_var *trg_new_row_fake_var= (sys_var*) 0x01; /* Macros to look like lex */ -#define yyGet() *(lip->ptr++) -#define yyGetLast() lip->ptr[-1] -#define yyPeek() lip->ptr[0] -#define yyPeek2() lip->ptr[1] +#define yyGet() ((uchar) *(lip->ptr++)) +#define yyGetLast() ((uchar) lip->ptr[-1]) +#define yyPeek() ((uchar) lip->ptr[0]) +#define yyPeek2() ((uchar) lip->ptr[1]) #define yyUnget() lip->ptr-- #define yySkip() lip->ptr++ #define yyLength() ((uint) (lip->ptr - lip->tok_start)-1) @@ -68,6 +69,17 @@ static uchar to_upper_lex[]= 208,209,210,211,212,213,214,247,216,217,218,219,220,221,222,255 }; +/* + Names of the index hints (for error messages). Keep in sync with + index_hint_type +*/ + +const char * index_hint_type_name[] = +{ + "IGNORE INDEX", + "USE INDEX", + "FORCE INDEX" +}; inline int lex_casecmp(const char *s, const char *t, uint len) { @@ -76,7 +88,7 @@ inline int lex_casecmp(const char *s, const char *t, uint len) return (int) len+1; } -#include "lex_hash.h" +#include <lex_hash.h> void lex_init(void) @@ -176,35 +188,53 @@ void lex_start(THD *thd) lex->derived_tables= 0; lex->lock_option= TL_READ; lex->safe_to_cache_query= 1; - lex->time_zone_tables_used= 0; lex->leaf_tables_insert= 0; lex->parsing_options.reset(); lex->empty_field_list_on_rset= 0; lex->select_lex.select_number= 1; - lex->in_comment=0; lex->length=0; + lex->part_info= 0; lex->select_lex.in_sum_expr=0; lex->select_lex.expr_list.empty(); lex->select_lex.ftfunc_list_alloc.empty(); lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; lex->select_lex.group_list.empty(); lex->select_lex.order_list.empty(); - lex->select_lex.udf_list.empty(); - lex->current_select= &lex->select_lex; - lex->yacc_yyss=lex->yacc_yyvs=0; - lex->sql_command= lex->orig_sql_command= SQLCOM_END; + lex->sql_command= SQLCOM_END; lex->duplicates= DUP_ERROR; lex->ignore= 0; + lex->spname= NULL; lex->sphead= NULL; lex->spcont= NULL; lex->proc_list.first= 0; lex->escape_used= FALSE; + lex->query_tables= 0; lex->reset_query_tables_list(FALSE); + lex->expr_allows_subselect= TRUE; + + lex->name.str= 0; + lex->name.length= 0; + lex->event_parse_data= NULL; lex->nest_level=0 ; lex->allow_sum_func= 0; lex->in_sum_func= NULL; + /* + ok, there must be a better solution for this, long-term + I tried "bzero" in the sql_yacc.yy code, but that for + some reason made the values zero, even if they were set + */ + lex->server_options.server_name= 0; + lex->server_options.server_name_length= 0; + lex->server_options.host= 0; + lex->server_options.db= 0; + lex->server_options.username= 0; + lex->server_options.password= 0; + lex->server_options.scheme= 0; + lex->server_options.socket= 0; + lex->server_options.owner= 0; + lex->server_options.port= -1; DBUG_VOID_RETURN; } @@ -212,8 +242,19 @@ void lex_end(LEX *lex) { DBUG_ENTER("lex_end"); DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex)); - x_free(lex->yacc_yyss); - x_free(lex->yacc_yyvs); + if (lex->yacc_yyss) + { + my_free(lex->yacc_yyss, MYF(0)); + my_free(lex->yacc_yyvs, MYF(0)); + lex->yacc_yyss= 0; + lex->yacc_yyvs= 0; + } + + /* release used plugins */ + plugin_unlock_list(0, (plugin_ref*)lex->plugins.buffer, + lex->plugins.elements); + reset_dynamic(&lex->plugins); + DBUG_VOID_RETURN; } @@ -228,14 +269,14 @@ static int find_keyword(Lex_input_stream *lip, uint len, bool function) lip->yylval->symbol.symbol=symbol; lip->yylval->symbol.str= (char*) tok; lip->yylval->symbol.length=len; - + if ((symbol->tok == NOT_SYM) && (lip->m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE)) return NOT2_SYM; if ((symbol->tok == OR_OR_SYM) && !(lip->m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT)) return OR2_SYM; - + return symbol->tok; } return 0; @@ -260,6 +301,12 @@ bool is_keyword(const char *name, uint len) return get_hash_symbol(name,len,0)!=0; } +bool is_lex_native_function(const LEX_STRING *name) +{ + DBUG_ASSERT(name != NULL); + return (get_hash_symbol(name->str, name->length, 1) != 0); +} + /* make a copy of token before ptr and set yytoklen */ static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length) @@ -283,12 +330,13 @@ static LEX_STRING get_quoted_token(Lex_input_stream *lip, uint length, char quote) { LEX_STRING tmp; - byte *from, *to, *end; + const char *from, *end; + char *to; yyUnget(); // ptr points now after last token char - tmp.length=lip->yytoklen=length; + tmp.length= lip->yytoklen=length; tmp.str=(char*) lip->m_thd->alloc(tmp.length+1); - from= (byte*) lip->tok_start + skip; - to= (byte*) tmp.str; + from= lip->tok_start + skip; + to= tmp.str; end= to+length; for ( ; to != end; ) { @@ -319,16 +367,14 @@ static char *get_text(Lex_input_stream *lip) { int l; if (use_mb(cs) && - (l = my_ismbchar(cs, - lip->ptr-1, - lip->end_of_query))) { + (l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query))) { lip->ptr += l-1; continue; } } #endif if (c == '\\' && - !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) + !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) { // Escaped character found_escape=1; if (lip->ptr == lip->end_of_query) @@ -346,13 +392,12 @@ static char *get_text(Lex_input_stream *lip) yyUnget(); /* Found end. Unescape and return string */ - const char *str; - const char *end; + const char *str, *end; char *start; str=lip->tok_start+1; end=lip->ptr-1; - if (!(start=(char*) lip->m_thd->alloc((uint) (end-str)+1))) + if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1))) return (char*) ""; // Sql_alloc has set error flag if (!found_escape) { @@ -362,15 +407,14 @@ static char *get_text(Lex_input_stream *lip) } else { - char *to; + char *to; for (to=start ; str != end ; str++) { #ifdef USE_MB int l; if (use_mb(cs) && - (l = my_ismbchar(cs, - (const char *)str, (const char *)end))) { + (l = my_ismbchar(cs, str, end))) { while (l--) *to++ = *str++; str--; @@ -416,7 +460,7 @@ static char *get_text(Lex_input_stream *lip) *to=0; lip->yytoklen=(uint) (to-start); } - return (char*) start; + return start; } } return 0; // unexpected end of query @@ -627,9 +671,7 @@ int MYSQLlex(void *arg, void *yythd) result_state= IDENT_QUOTED; if (my_mbcharlen(cs, yyGetLast()) > 1) { - int l = my_ismbchar(cs, - lip->ptr-1, - lip->end_of_query); + int l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query); if (l == 0) { state = MY_LEX_CHAR; continue; @@ -641,9 +683,7 @@ int MYSQLlex(void *arg, void *yythd) if (my_mbcharlen(cs, c) > 1) { int l; - if ((l = my_ismbchar(cs, - lip->ptr-1, - lip->end_of_query)) == 0) + if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0) break; lip->ptr += l-1; } @@ -671,7 +711,7 @@ int MYSQLlex(void *arg, void *yythd) else { // '(' must follow directly if function yyUnget(); - if ((tokval = find_keyword(lip, length, c == '('))) + if ((tokval = find_keyword(lip, length,c == '('))) { lip->next_state= MY_LEX_START; // Allow signed numbers return(tokval); // Was keyword @@ -762,9 +802,7 @@ int MYSQLlex(void *arg, void *yythd) if (my_mbcharlen(cs, c) > 1) { int l; - if ((l = my_ismbchar(cs, - lip->ptr-1, - lip->end_of_query)) == 0) + if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0) break; lip->ptr += l-1; } @@ -792,8 +830,6 @@ int MYSQLlex(void *arg, void *yythd) int var_length; if ((var_length= my_mbcharlen(cs, c)) == 1) { - if (c == (uchar) NAMES_SEP_CHAR) - break; /* Old .frm format can't handle this char */ if (c == quote_char) { if (yyPeek() != quote_char) @@ -877,7 +913,7 @@ int MYSQLlex(void *arg, void *yythd) if (state_map[yyPeek()] == MY_LEX_CMP_OP || state_map[yyPeek()] == MY_LEX_LONG_CMP_OP) yySkip(); - if ((tokval = find_keyword(lip,(uint) (lip->ptr - lip->tok_start),0))) + if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0))) { lip->next_state= MY_LEX_START; // Allow signed numbers return(tokval); @@ -893,7 +929,7 @@ int MYSQLlex(void *arg, void *yythd) if (state_map[yyPeek()] == MY_LEX_CMP_OP) yySkip(); } - if ((tokval = find_keyword(lip,(uint) (lip->ptr - lip->tok_start),0))) + if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0))) { lip->next_state= MY_LEX_START; // Found long op return(tokval); @@ -994,7 +1030,7 @@ int MYSQLlex(void *arg, void *yythd) lex->safe_to_cache_query= 0; lip->found_semicolon= lip->ptr; thd->server_status|= SERVER_MORE_RESULTS_EXISTS; - lip->next_state= MY_LEX_END; + lip->next_state= MY_LEX_END; return (END_OF_INPUT); } state= MY_LEX_CHAR; // Return ';' @@ -1082,17 +1118,6 @@ int MYSQLlex(void *arg, void *yythd) } -Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root) - :drop_list(rhs.drop_list, mem_root), - alter_list(rhs.alter_list, mem_root), - key_list(rhs.key_list, mem_root), - create_list(rhs.create_list, mem_root), - flags(rhs.flags), - keys_onoff(rhs.keys_onoff), - tablespace_op(rhs.tablespace_op) -{} - - /* Skip comment in the end of statement. @@ -1108,7 +1133,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root) Pointer to the last non-comment symbol of the statement. */ -char *skip_rear_comments(char *begin, char *end) +const char *skip_rear_comments(const char *begin, const char *end) { while (begin < end && (end[-1] <= ' ' || end[-1] == '*' || end[-1] == '/' || end[-1] == ';')) @@ -1197,16 +1222,13 @@ void st_select_lex::init_select() group_list.empty(); type= db= 0; having= 0; - use_index_ptr= ignore_index_ptr= 0; table_join_options= 0; in_sum_expr= with_wild= 0; options= 0; sql_cache= SQL_CACHE_UNSPECIFIED; braces= 0; expr_list.empty(); - udf_list.empty(); interval_list.empty(); - use_index.empty(); ftfunc_list_alloc.empty(); inner_sum_func_list= 0; ftfunc_list= &ftfunc_list_alloc; @@ -1433,14 +1455,11 @@ bool st_select_lex_node::inc_in_sum_expr() { return 1; } uint st_select_lex_node::get_in_sum_expr() { return 0; } TABLE_LIST* st_select_lex_node::get_table_list() { return 0; } List<Item>* st_select_lex_node::get_item_list() { return 0; } -List<String>* st_select_lex_node::get_use_index() { return 0; } -List<String>* st_select_lex_node::get_ignore_index() { return 0; } -TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table, +TABLE_LIST *st_select_lex_node::add_table_to_list (THD *thd, Table_ident *table, LEX_STRING *alias, ulong table_join_options, thr_lock_type flags, - List<String> *use_index, - List<String> *ignore_index, + List<index_hint> *hints, LEX_STRING *option) { return 0; @@ -1488,7 +1507,7 @@ bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc) bool st_select_lex::add_item_to_list(THD *thd, Item *item) { DBUG_ENTER("st_select_lex::add_item_to_list"); - DBUG_PRINT("info", ("Item: %p", item)); + DBUG_PRINT("info", ("Item: 0x%lx", (long) item)); DBUG_RETURN(item_list.push_back(item)); } @@ -1547,19 +1566,6 @@ List<Item>* st_select_lex::get_item_list() return &item_list; } - -List<String>* st_select_lex::get_use_index() -{ - return use_index_ptr; -} - - -List<String>* st_select_lex::get_ignore_index() -{ - return ignore_index_ptr; -} - - ulong st_select_lex::get_table_join_options() { return table_join_options; @@ -1715,6 +1721,17 @@ void st_lex::cleanup_lex_after_parse_error(THD *thd) void Query_tables_list::reset_query_tables_list(bool init) { + if (!init && query_tables) + { + TABLE_LIST *table= query_tables; + for (;;) + { + delete table->view; + if (query_tables_last == &table->next_global || + !(table= table->next_global)) + break; + } + } query_tables= 0; query_tables_last= &query_tables; query_tables_own_last= 0; @@ -1734,6 +1751,7 @@ void Query_tables_list::reset_query_tables_list(bool init) sroutines_list.empty(); sroutines_list_own_last= sroutines_list.next; sroutines_list_own_elements= 0; + binlog_row_based_if_mixed= FALSE; } @@ -1766,8 +1784,15 @@ void Query_tables_list::destroy_query_tables_list() st_lex::st_lex() :result(0), yacc_yyss(0), yacc_yyvs(0), - sql_command(SQLCOM_END) + sql_command(SQLCOM_END), option_type(OPT_DEFAULT) { + /* Check that plugins_static_buffer is declared immediately after plugins */ + compile_time_assert((&plugins + 1) == (DYNAMIC_ARRAY*)plugins_static_buffer); + + my_init_dynamic_array2(&plugins, sizeof(plugin_ref), + plugins_static_buffer, + INITIAL_LEX_PLUGIN_LIST_SIZE, + INITIAL_LEX_PLUGIN_LIST_SIZE); reset_query_tables_list(TRUE); } @@ -2090,31 +2115,6 @@ void st_lex::first_lists_tables_same() /* - Add implicitly used time zone description tables to global table list - (if needed). - - SYNOPSYS - st_lex::add_time_zone_tables_to_query_tables() - thd - pointer to current thread context - - RETURN VALUE - TRUE - error - FALSE - success -*/ - -bool st_lex::add_time_zone_tables_to_query_tables(THD *thd_arg) -{ - /* We should not add these tables twice */ - if (!time_zone_tables_used) - { - time_zone_tables_used= my_tz_get_table_list(thd_arg, &query_tables_last); - if (time_zone_tables_used == &fake_time_zone_tables_list) - return TRUE; - } - return FALSE; -} - -/* Link table back that was unlinked with unlink_first_table() SYNOPSIS @@ -2183,7 +2183,6 @@ void st_lex::cleanup_after_one_table_open() /* remove underlying units (units of VIEW) subtree */ select_lex.cut_subtree(); } - time_zone_tables_used= 0; } @@ -2223,6 +2222,28 @@ void st_lex::restore_backup_query_tables_list(Query_tables_list *backup) /* + Checks for usage of routines and/or tables in a parsed statement + + SYNOPSIS + st_lex:table_or_sp_used() + + RETURN + FALSE No routines and tables used + TRUE Either or both routines and tables are used. +*/ + +bool st_lex::table_or_sp_used() +{ + DBUG_ENTER("table_or_sp_used"); + + if (sroutines.records || query_tables) + DBUG_RETURN(TRUE); + + DBUG_RETURN(FALSE); +} + + +/* Do end-of-prepare fixup for list of tables and their merge-VIEWed tables SYNOPSIS @@ -2289,6 +2310,7 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, } } + /* There are st_select_lex::add_table_to_list & st_select_lex::set_lock_for_tables are in sql_parse.cc @@ -2301,3 +2323,61 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, are in sql_union.cc */ +/* + Sets the kind of hints to be added by the calls to add_index_hint(). + + SYNOPSIS + set_index_hint_type() + type the kind of hints to be added from now on. + clause the clause to use for hints to be added from now on. + + DESCRIPTION + Used in filling up the tagged hints list. + This list is filled by first setting the kind of the hint as a + context variable and then adding hints of the current kind. + Then the context variable index_hint_type can be reset to the + next hint type. +*/ +void st_select_lex::set_index_hint_type(enum index_hint_type type, + index_clause_map clause) +{ + current_index_hint_type= type; + current_index_hint_clause= clause; +} + + +/* + Makes an array to store index usage hints (ADD/FORCE/IGNORE INDEX). + + SYNOPSIS + alloc_index_hints() + thd current thread. +*/ + +void st_select_lex::alloc_index_hints (THD *thd) +{ + index_hints= new (thd->mem_root) List<index_hint>(); +} + + + +/* + adds an element to the array storing index usage hints + (ADD/FORCE/IGNORE INDEX). + + SYNOPSIS + add_index_hint() + thd current thread. + str name of the index. + length number of characters in str. + + RETURN VALUE + 0 on success, non-zero otherwise +*/ +bool st_select_lex::add_index_hint (THD *thd, char *str, uint length) +{ + return index_hints->push_front (new (thd->mem_root) + index_hint(current_index_hint_type, + current_index_hint_clause, + str, length)); +} |