diff options
author | pekka@mysql.com <> | 2006-05-30 22:54:06 +0200 |
---|---|---|
committer | pekka@mysql.com <> | 2006-05-30 22:54:06 +0200 |
commit | bc889160b1b52a42887edc2feed73493133b8f3e (patch) | |
tree | 9463ea754946d7d52715828c856838a7e6f9d8c7 /sql | |
parent | 7f46e03f5569d403d97c9362fca5562d4783c557 (diff) | |
parent | d402c3d4a39658eb967ee65f49688a2db1d9b9b3 (diff) | |
download | mariadb-git-bc889160b1b52a42887edc2feed73493133b8f3e.tar.gz |
Merge pnousiainen@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/space/pekka/ndb/version/my50
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_lex.cc | 108 | ||||
-rw-r--r-- | sql/sql_lex.h | 151 | ||||
-rw-r--r-- | sql/sql_show.cc | 17 | ||||
-rw-r--r-- | sql/sql_table.cc | 2 |
4 files changed, 193 insertions, 85 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c4c72910265..d2699b88aa4 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -151,8 +151,7 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->found_semicolon= 0; lex->safe_to_cache_query= 1; lex->time_zone_tables_used= 0; - lex->leaf_tables_insert= lex->query_tables= 0; - lex->query_tables_last= &lex->query_tables; + lex->leaf_tables_insert= 0; lex->variables_used= 0; lex->empty_field_list_on_rset= 0; lex->select_lex.select_number= 1; @@ -175,14 +174,9 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->sphead= NULL; lex->spcont= NULL; lex->proc_list.first= 0; - lex->query_tables_own_last= 0; lex->escape_used= FALSE; + lex->reset_query_tables_list(FALSE); - if (lex->sroutines.records) - my_hash_reset(&lex->sroutines); - lex->sroutines_list.empty(); - lex->sroutines_list_own_last= lex->sroutines_list.next; - lex->sroutines_list_own_elements= 0; lex->nest_level=0 ; lex->allow_sum_func= 0; lex->in_sum_func= NULL; @@ -1615,6 +1609,52 @@ void st_select_lex::print_limit(THD *thd, String *str) /* + Initialize (or reset) Query_tables_list object. + + SYNOPSIS + reset_query_tables_list() + init TRUE - we should perform full initialization of object with + allocating needed memory + FALSE - object is already initialized so we should only reset + its state so it can be used for parsing/processing + of new statement + + DESCRIPTION + This method initializes Query_tables_list so it can be used as part + of LEX object for parsing/processing of statement. One can also use + this method to reset state of already initialized Query_tables_list + so it can be used for processing of new statement. +*/ + +void Query_tables_list::reset_query_tables_list(bool init) +{ + query_tables= 0; + query_tables_last= &query_tables; + query_tables_own_last= 0; + if (init) + hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); + else if (sroutines.records) + my_hash_reset(&sroutines); + sroutines_list.empty(); + sroutines_list_own_last= sroutines_list.next; + sroutines_list_own_elements= 0; +} + + +/* + Destroy Query_tables_list object with freeing all resources used by it. + + SYNOPSIS + destroy_query_tables_list() +*/ + +void Query_tables_list::destroy_query_tables_list() +{ + hash_free(&sroutines); +} + + +/* Initialize LEX object. SYNOPSIS @@ -1630,12 +1670,9 @@ void st_select_lex::print_limit(THD *thd, String *str) st_lex::st_lex() :result(0), yacc_yyss(0), yacc_yyvs(0), - sql_command(SQLCOM_END), query_tables_own_last(0) + sql_command(SQLCOM_END) { - hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); - sroutines_list.empty(); - sroutines_list_own_last= sroutines_list.next; - sroutines_list_own_elements= 0; + reset_query_tables_list(TRUE); } @@ -2019,6 +2056,11 @@ void st_lex::link_first_table_back(TABLE_LIST *first, SYNOPSIS st_lex::cleanup_after_one_table_open() + + NOTE + This method is mostly responsible for cleaning up of selects lists and + derived tables state. To rollback changes in Query_tables_list one has + to call Query_tables_list::reset_query_tables_list(FALSE). */ void st_lex::cleanup_after_one_table_open() @@ -2045,11 +2087,41 @@ void st_lex::cleanup_after_one_table_open() select_lex.cut_subtree(); } time_zone_tables_used= 0; - if (sroutines.records) - my_hash_reset(&sroutines); - sroutines_list.empty(); - sroutines_list_own_last= sroutines_list.next; - sroutines_list_own_elements= 0; +} + + +/* + Save current state of Query_tables_list for this LEX, and prepare it + for processing of new statemnt. + + SYNOPSIS + reset_n_backup_query_tables_list() + backup Pointer to Query_tables_list instance to be used for backup +*/ + +void st_lex::reset_n_backup_query_tables_list(Query_tables_list *backup) +{ + backup->set_query_tables_list(this); + /* + We have to perform full initialization here since otherwise we + will damage backed up state. + */ + this->reset_query_tables_list(TRUE); +} + + +/* + Restore state of Query_tables_list for this LEX from backup. + + SYNOPSIS + restore_backup_query_tables_list() + backup Pointer to Query_tables_list instance used for backup +*/ + +void st_lex::restore_backup_query_tables_list(Query_tables_list *backup) +{ + this->destroy_query_tables_list(); + this->set_query_tables_list(backup); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 34e7ee969b6..6b5c6ddca60 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -702,9 +702,95 @@ extern sys_var_long_ptr trg_new_row_fake_var; enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE, XA_SUSPEND, XA_FOR_MIGRATE}; + +/* + Class representing list of all tables used by statement. + It also contains information about stored functions used by statement + since during its execution we may have to add all tables used by its + stored functions/triggers to this list in order to pre-open and lock + them. + + Also used by st_lex::reset_n_backup/restore_backup_query_tables_list() + methods to save and restore this information. +*/ + +class Query_tables_list +{ +public: + /* Global list of all tables used by this statement */ + TABLE_LIST *query_tables; + /* Pointer to next_global member of last element in the previous list. */ + TABLE_LIST **query_tables_last; + /* + If non-0 then indicates that query requires prelocking and points to + next_global member of last own element in query table list (i.e. last + table which was not added to it as part of preparation to prelocking). + 0 - indicates that this query does not need prelocking. + */ + TABLE_LIST **query_tables_own_last; + /* Set of stored routines called by statement. */ + HASH sroutines; + /* + List linking elements of 'sroutines' set. Allows you to add new elements + to this set as you iterate through the list of existing elements. + 'sroutines_list_own_last' is pointer to ::next member of last element of + this list which represents routine which is explicitly used by query. + 'sroutines_list_own_elements' number of explicitly used routines. + We use these two members for restoring of 'sroutines_list' to the state + in which it was right after query parsing. + */ + SQL_LIST sroutines_list; + byte **sroutines_list_own_last; + uint sroutines_list_own_elements; + + /* + These constructor and destructor serve for creation/destruction + of Query_tables_list instances which are used as backup storage. + */ + Query_tables_list() {} + ~Query_tables_list() {} + + /* Initializes (or resets) Query_tables_list object for "real" use. */ + void reset_query_tables_list(bool init); + void destroy_query_tables_list(); + void set_query_tables_list(Query_tables_list *state) + { + *this= *state; + } + + void add_to_query_tables(TABLE_LIST *table) + { + *(table->prev_global= query_tables_last)= table; + query_tables_last= &table->next_global; + } + bool requires_prelocking() + { + return test(query_tables_own_last); + } + void mark_as_requiring_prelocking(TABLE_LIST **tables_own_last) + { + query_tables_own_last= tables_own_last; + } + /* Return pointer to first not-own table in query-tables or 0 */ + TABLE_LIST* first_not_own_table() + { + return ( query_tables_own_last ? *query_tables_own_last : 0); + } + void chop_off_not_own_tables() + { + if (query_tables_own_last) + { + *query_tables_own_last= 0; + query_tables_last= query_tables_own_last; + query_tables_own_last= 0; + } + } +}; + + /* The state of the lex parsing. This is saved in the THD struct */ -typedef struct st_lex +typedef struct st_lex : public Query_tables_list { uint yylineno,yytoklen; /* Simulate lex */ LEX_YYSTYPE yylval; @@ -736,14 +822,6 @@ typedef struct st_lex gptr yacc_yyss,yacc_yyvs; THD *thd; CHARSET_INFO *charset; - TABLE_LIST *query_tables; /* global list of all tables in this query */ - /* - last element next_global of previous list (used only for list building - during parsing and VIEW processing. This pointer could be invalid during - processing of information schema tables(see get_schema_tables_result - function) - */ - TABLE_LIST **query_tables_last; /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; /* Position (first character index) of SELECT of CREATE VIEW statement */ @@ -876,20 +954,6 @@ typedef struct st_lex bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */ bool all_privileges; sp_pcontext *spcont; - /* Set of stored routines called by statement. */ - HASH sroutines; - /* - List linking elements of 'sroutines' set. Allows you to add new elements - to this set as you iterate through the list of existing elements. - 'sroutines_list_own_last' is pointer to ::next member of last element of - this list which represents routine which is explicitly used by query. - 'sroutines_list_own_elements' number of explicitly used routines. - We use these two members for restoring of 'sroutines_list' to the state - in which it was right after query parsing. - */ - SQL_LIST sroutines_list; - byte **sroutines_list_own_last; - uint sroutines_list_own_elements; st_sp_chistics sp_chistics; bool only_view; /* used for SHOW CREATE TABLE/VIEW */ @@ -926,14 +990,6 @@ typedef struct st_lex const char *stmt_definition_begin; /* - If non-0 then indicates that query requires prelocking and points to - next_global member of last own element in query table list (i.e. last - table which was not added to it as part of preparation to prelocking). - 0 - indicates that this query does not need prelocking. - */ - TABLE_LIST **query_tables_own_last; - - /* Pointers to part of LOAD DATA statement that should be rewritten during replication ("LOCAL 'filename' REPLACE INTO" part). */ @@ -945,7 +1001,7 @@ typedef struct st_lex virtual ~st_lex() { - hash_free(&sroutines); + destroy_query_tables_list(); } inline void uncacheable(uint8 cause) @@ -970,11 +1026,6 @@ typedef struct st_lex TABLE_LIST *unlink_first_table(bool *link_to_local); void link_first_table_back(TABLE_LIST *first, bool link_to_local); void first_lists_tables_same(); - inline void add_to_query_tables(TABLE_LIST *table) - { - *(table->prev_global= query_tables_last)= table; - query_tables_last= &table->next_global; - } bool add_time_zone_tables_to_query_tables(THD *thd); bool can_be_merged(); @@ -1006,28 +1057,7 @@ typedef struct st_lex return FALSE; } } - inline bool requires_prelocking() - { - return test(query_tables_own_last); - } - inline void mark_as_requiring_prelocking(TABLE_LIST **tables_own_last) - { - query_tables_own_last= tables_own_last; - } - /* Return pointer to first not-own table in query-tables or 0 */ - TABLE_LIST* first_not_own_table() - { - return ( query_tables_own_last ? *query_tables_own_last : 0); - } - void chop_off_not_own_tables() - { - if (query_tables_own_last) - { - *query_tables_own_last= 0; - query_tables_last= query_tables_own_last; - query_tables_own_last= 0; - } - } + void cleanup_after_one_table_open(); bool push_context(Name_resolution_context *context) @@ -1044,6 +1074,9 @@ typedef struct st_lex { return context_stack.head(); } + + void reset_n_backup_query_tables_list(Query_tables_list *backup); + void restore_backup_query_tables_list(Query_tables_list *backup); } LEX; struct st_lex_local: public st_lex diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9018b364ec9..246da4dfeec 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2065,7 +2065,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; SELECT_LEX *select_lex= &lex->select_lex; SELECT_LEX *old_all_select_lex= lex->all_selects_list; - TABLE_LIST **save_query_tables_last= lex->query_tables_last; enum_sql_command save_sql_command= lex->sql_command; SELECT_LEX *lsel= tables->schema_select_lex; ST_SCHEMA_TABLE *schema_table= tables->schema_table; @@ -2084,6 +2083,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) db_type not_used; Open_tables_state open_tables_state_backup; bool save_view_prepare_mode= lex->view_prepare_mode; + Query_tables_list query_tables_list_backup; lex->view_prepare_mode= TRUE; DBUG_ENTER("get_all_tables"); @@ -2096,6 +2096,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) */ lex->sql_command= SQLCOM_SHOW_FIELDS; + lex->reset_n_backup_query_tables_list(&query_tables_list_backup); + /* We should not introduce deadlocks even if we already have some tables open and locked, since we won't lock tables which we will @@ -2136,8 +2138,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) show_table_list->db), show_table_list->alias)); thd->temporary_tables= 0; - close_thread_tables(thd); - show_table_list->table= 0; + close_tables_for_reopen(thd, &show_table_list); goto err; } @@ -2248,9 +2249,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) in this case. */ res= schema_table->process_table(thd, show_table_list, table, - res, base_name, - show_table_list->alias); - close_thread_tables(thd); + res, base_name, + show_table_list->alias); + close_tables_for_reopen(thd, &show_table_list); + DBUG_ASSERT(!lex->query_tables_own_last); if (res) goto err; } @@ -2267,11 +2269,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) error= 0; err: thd->restore_backup_open_tables_state(&open_tables_state_backup); + lex->restore_backup_query_tables_list(&query_tables_list_backup); lex->derived_tables= derived_tables; lex->all_selects_list= old_all_select_lex; - lex->query_tables_last= save_query_tables_last; lex->view_prepare_mode= save_view_prepare_mode; - *save_query_tables_last= 0; lex->sql_command= save_sql_command; DBUG_RETURN(error); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 476d5536581..9ec8e8db1fb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2240,6 +2240,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, tables can be left opening */ close_thread_tables(thd); + lex->reset_query_tables_list(FALSE); if (protocol->write()) goto err; continue; @@ -2487,6 +2488,7 @@ send_result_message: } } close_thread_tables(thd); + lex->reset_query_tables_list(FALSE); table->table=0; // For query cache if (protocol->write()) goto err; |