summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorpekka@mysql.com <>2006-05-30 22:54:06 +0200
committerpekka@mysql.com <>2006-05-30 22:54:06 +0200
commitbc889160b1b52a42887edc2feed73493133b8f3e (patch)
tree9463ea754946d7d52715828c856838a7e6f9d8c7 /sql
parent7f46e03f5569d403d97c9362fca5562d4783c557 (diff)
parentd402c3d4a39658eb967ee65f49688a2db1d9b9b3 (diff)
downloadmariadb-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.cc108
-rw-r--r--sql/sql_lex.h151
-rw-r--r--sql/sql_show.cc17
-rw-r--r--sql/sql_table.cc2
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;