summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorbell@sanja.is.com.ua <>2004-09-11 23:52:55 +0300
committerbell@sanja.is.com.ua <>2004-09-11 23:52:55 +0300
commit31379fbebe149392550d3d3e2387785d55a230d5 (patch)
tree5d8b24fe6db8715fdb04854cd3b9d80b848cb888 /sql
parentbcadf50bc0e932b6d6a85114e84749eacaac6128 (diff)
downloadmariadb-git-31379fbebe149392550d3d3e2387785d55a230d5.tar.gz
table lists management during VIEW processing code cleanup
Diffstat (limited to 'sql')
-rw-r--r--sql/sql_lex.h11
-rw-r--r--sql/sql_parse.cc39
-rw-r--r--sql/sql_view.cc100
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);