diff options
author | bell@sanja.is.com.ua <> | 2004-09-11 23:52:55 +0300 |
---|---|---|
committer | bell@sanja.is.com.ua <> | 2004-09-11 23:52:55 +0300 |
commit | 31379fbebe149392550d3d3e2387785d55a230d5 (patch) | |
tree | 5d8b24fe6db8715fdb04854cd3b9d80b848cb888 /sql | |
parent | bcadf50bc0e932b6d6a85114e84749eacaac6128 (diff) | |
download | mariadb-git-31379fbebe149392550d3d3e2387785d55a230d5.tar.gz |
table lists management during VIEW processing code cleanup
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_lex.h | 11 | ||||
-rw-r--r-- | sql/sql_parse.cc | 39 | ||||
-rw-r--r-- | sql/sql_view.cc | 100 |
3 files changed, 77 insertions, 73 deletions
diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9e724dab6a6..d43b1f81f3d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -643,7 +643,11 @@ typedef struct st_lex THD *thd; CHARSET_INFO *charset; TABLE_LIST *query_tables; /* global list of all tables in this query */ - /* last element next_global of previous list */ + /* + last element next_global of previous list (used only for list building + during parsing and VIEW processing. This pointer is not valid in + mysql_execute_command + */ TABLE_LIST **query_tables_last; TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */ @@ -765,6 +769,11 @@ 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 can_be_merged(); bool can_use_merged(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 556bc5d5d88..e1baf47b234 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5152,8 +5152,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, /* Link table in local list (list for current select) */ table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local); /* Link table in global list (all used tables) */ - *(ptr->prev_global= lex->query_tables_last)= ptr; - lex->query_tables_last= &ptr->next_global; + lex->add_to_query_tables(ptr); DBUG_RETURN(ptr); } @@ -5162,9 +5161,9 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, Initialize a new table list for a nested join SYNOPSIS - init_table_list() + init_table_list() thd current thread - + DESCRIPTION The function initializes a structure of the TABLE_LIST type for a nested join. It sets up its nested join list as empty. @@ -5184,7 +5183,7 @@ bool st_select_lex::init_nested_join(THD *thd) TABLE_LIST *ptr; NESTED_JOIN *nested_join; DBUG_ENTER("init_nested_join"); - + if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))) || !(nested_join= ptr->nested_join= (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN)))) @@ -5209,7 +5208,7 @@ bool st_select_lex::init_nested_join(THD *thd) DESCRIPTION The function returns to the previous join nest level. If the current level contains only one member, the function - moves it one level up, eliminating the nest. + moves it one level up, eliminating the nest. RETURN VALUE Pointer to TABLE_LIST element added to the total table list, if success @@ -5241,7 +5240,7 @@ TABLE_LIST *st_select_lex::end_nested_join(THD *thd) Nest last join operation SYNOPSIS - nest_last_join() + nest_last_join() thd current thread DESCRIPTION @@ -5257,7 +5256,7 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) TABLE_LIST *ptr; NESTED_JOIN *nested_join; DBUG_ENTER("nest_last_join"); - + if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))) || !(nested_join= ptr->nested_join= (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN)))) @@ -5281,7 +5280,7 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) /* Save names for a join with using clase - + SYNOPSIS save_names_for_using_list tab1 left table in join @@ -5289,11 +5288,11 @@ TABLE_LIST *st_select_lex::nest_last_join(THD *thd) DESCRIPTION The function saves the full names of the tables in st_select_lex - to be able to build later an on expression to replace the using clause. - + to be able to build later an on expression to replace the using clause. + RETURN VALUE - None -*/ + None +*/ void st_select_lex::save_names_for_using_list(TABLE_LIST *tab1, TABLE_LIST *tab2) @@ -5315,7 +5314,7 @@ void st_select_lex::save_names_for_using_list(TABLE_LIST *tab1, db2= tab2->db; table2= tab2->alias; } - + /* Add a table to the current join list @@ -5350,9 +5349,9 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) SYNOPSIS convert_right_join() thd current thread - - DESCRIPTION - The function takes the current join list t[0],t[1] ... and + + DESCRIPTION + The function takes the current join list t[0],t[1] ... and effectively converts it into the list t[1],t[0] ... Although the outer_join flag for the new nested table contains JOIN_TYPE_RIGHT, it will be handled as the inner table of a left join @@ -5376,10 +5375,10 @@ void st_select_lex::add_joined_table(TABLE_LIST *table) 0, otherwise */ -TABLE_LIST *st_select_lex::convert_right_join() +TABLE_LIST *st_select_lex::convert_right_join() { TABLE_LIST *tab2= join_list->pop(); - TABLE_LIST *tab1= join_list->pop(); + TABLE_LIST *tab1= join_list->pop(); DBUG_ENTER("convert_right_join"); join_list->push_front(tab2); @@ -5443,7 +5442,7 @@ void add_join_on(TABLE_LIST *b,Item *expr) add_join_natural() a Table to do normal join with b Do normal join with this table - + IMPLEMENTATION This function just marks that table b should be joined with a. The function setup_cond() will create in b->on_expr a list diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 91b66251fd0..2364be228f8 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -45,6 +45,7 @@ TYPELIB sql_updatable_view_key_typelib= -1 Error 1 Error and error message given */ + int mysql_create_view(THD *thd, enum_view_create_mode mode) { @@ -356,6 +357,7 @@ static LEX_STRING view_file_type[]= {{(char*)"VIEW", 4}}; -1 Error 1 Error and error message given */ + static int mysql_register_view(THD *thd, TABLE_LIST *view, enum_view_create_mode mode) { @@ -423,7 +425,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, /* read revision number - + TODO: read dependense list, too, to process cascade/restrict TODO: special cascade/restrict procedure for alter? */ @@ -501,7 +503,6 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, my_bool mysql_make_view(File_parser *parser, TABLE_LIST *table) { - bool include_proc_table= 0; DBUG_ENTER("mysql_make_view"); if (table->view) @@ -512,7 +513,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) DBUG_RETURN(0); } - TABLE_LIST *old_next, *tbl_end, *tbl_next; SELECT_LEX *end; THD *thd= current_thd; LEX *old_lex= thd->lex, *lex; @@ -599,11 +599,14 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) TABLE_LIST *top_view= (table->belong_to_view ? table->belong_to_view : table); + TABLE_LIST *view_tables= lex->query_tables; + TABLE_LIST *view_tables_tail= 0; if (lex->spfuns.records) { /* move SP to main LEX */ sp_merge_funs(old_lex, lex); + /* open mysq.proc for functions which are not in cache */ if (old_lex->proc_table == 0 && (old_lex->proc_table= (TABLE_LIST*)thd->calloc(sizeof(TABLE_LIST))) != 0) @@ -614,18 +617,20 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) table->real_name= table->alias= (char*)"proc"; table->real_name_length= 4; table->cacheable_table= 1; - include_proc_table= 1; + old_lex->add_to_query_tables(table); } } + /* cleanup LEX */ if (lex->spfuns.array.buffer) hash_free(&lex->spfuns); - old_next= table->old_next= table->next_global; - if ((table->next_global= lex->query_tables)) - table->next_global->prev_global= &table->next_global; - - /* mark to avoid temporary table using and put view reference*/ - for (TABLE_LIST *tbl= table->next_global; tbl; tbl= tbl->next_global) + /* + mark to avoid temporary table using and put view reference and find + last view table + */ + for (TABLE_LIST *tbl= view_tables; + tbl; + tbl= (view_tables_tail= tbl)->next_global) { tbl->skip_temporary= 1; tbl->belong_to_view= top_view; @@ -638,8 +643,8 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) if ((old_lex->sql_command == SQLCOM_SELECT && old_lex->describe) || old_lex->sql_command == SQLCOM_SHOW_CREATE) { - if (check_table_access(thd, SELECT_ACL, table->next_global, 1) && - check_table_access(thd, SHOW_VIEW_ACL, table->next_global, 1)) + if (check_table_access(thd, SELECT_ACL, view_tables, 1) && + check_table_access(thd, SHOW_VIEW_ACL, view_tables, 1)) { my_error(ER_VIEW_NO_EXPLAIN, MYF(0)); goto err; @@ -654,6 +659,29 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE; /* + Put tables of VIEW after VIEW TABLE_LIST + + NOTE: It is important for UPDATE/INSERT/DELETE checks to have this + tables just after VIEW instead of tail of list, to be able check that + table is unique. Also we store old next table for the same purpose. + */ + table->old_next= table->next_global; + if (view_tables) + { + if (table->next_global) + { + table->next_global->prev_global= &view_tables_tail->next_global; + view_tables_tail->next_global= table->old_next; + } + else + { + lex->query_tables_last= &view_tables_tail->next_global; + } + view_tables->prev_global= &table->next_global; + table->next_global= view_tables; + } + + /* check MERGE algorithm ability - algorithm is not explicit TEMPORARY TABLE - VIEW SELECT allow marging @@ -667,31 +695,26 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) { /* TODO: support multi tables substitutions - - table->next_global should be the same as - (TABLE_LIST *)lex->select_lex.table_list.first; */ - TABLE_LIST *view_table= table->next_global; /* lex should contain at least one table */ - DBUG_ASSERT(view_table != 0); + DBUG_ASSERT(view_tables != 0); table->effective_algorithm= VIEW_ALGORITHM_MERGE; DBUG_PRINT("info", ("algorithm: MERGE")); table->updatable= (table->updatable_view != 0); - if (old_next) - { - if ((view_table->next_global= old_next)) - old_next->prev_global= &view_table->next_global; - } - table->ancestor= view_table; - // next table should include SELECT_LEX under this table SELECT_LEX + table->ancestor= view_tables; + /* + next table should include SELECT_LEX under this table SELECT_LEX + + TODO: ehere should be loop for multi tables substitution + */ table->ancestor->select_lex= table->select_lex; /* move lock type (TODO: should we issue error in case of TMPTABLE algorithm and non-read locking)? */ - view_table->lock_type= table->lock_type; + view_tables->lock_type= table->lock_type; /* Store WHERE clause for postprocessing in setup_ancestor */ table->where= lex->select_lex.where; @@ -714,22 +737,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) lex->unit.include_down(table->select_lex); lex->unit.slave= &lex->select_lex; // fix include_down initialisation - if (old_next) - { - if ((tbl_end= table->next_global)) - { - for (; (tbl_next= tbl_end->next_global); tbl_end= tbl_next) - ; - if ((tbl_end->next_global= old_next)) - tbl_end->next_global->prev_global= &tbl_end->next_global; - } - else - { - /* VIEW do not contain tables */ - table->next_global= old_next; - } - } - table->derived= &lex->unit; } else @@ -746,17 +753,6 @@ ok: lex->all_selects_list->link_prev= (st_select_lex_node**)&old_lex->all_selects_list; - if (include_proc_table) - { - TABLE_LIST *proc= old_lex->proc_table; - if((proc->next_global= table->next_global)) - { - table->next_global->prev_global= &proc->next_global; - } - proc->prev_global= &table->next_global; - table->next_global= proc; - } - thd->lex= old_lex; DBUG_RETURN(0); |