Commit 9d4b228b authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

Many files:

  Fixed bug #8528.
  Representation for single-table views was made similar to
  representation for multi-table views.
view.test:
  Added test case for bug #8528.
view.result:
  Added test case for bug #8528. Fixed other test cases.
parent fd717612
......@@ -51,7 +51,7 @@ explain extended select c from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
Warnings:
Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`v1`
Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1`
create algorithm=temptable view v2 (c) as select b+1 from t1;
show create view v2;
View Create View
......@@ -85,7 +85,7 @@ explain extended select c from v3;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
Warnings:
Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`v3`
Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1`
create algorithm=temptable view v4 (c) as select c+1 from v2;
select c from v4;
c
......@@ -114,7 +114,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5
3 DERIVED t1 ALL NULL NULL NULL NULL 5
Warnings:
Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v5`
Note 1003 select (`v2`.`c` + 1) AS `c` from `test`.`v2`
create algorithm=temptable view v6 (c) as select c+1 from v1;
select c from v6;
c
......@@ -204,21 +204,6 @@ create table t1 (a int);
insert into t1 values (1), (2), (3);
create view v1 (a) as select a+1 from t1;
create view v2 (a) as select a-1 from t1;
select * from t1 natural left join v1;
a a
1 NULL
2 2
3 3
select * from v2 natural left join t1;
a a
0 NULL
1 1
2 2
select * from v2 natural left join v1;
a a
0 NULL
1 NULL
2 2
drop view v1, v2;
drop table t1;
create table t1 (a int);
......@@ -378,7 +363,7 @@ explain extended select * from v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
Warnings:
Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`v1` where (`test`.`t1`.`a` < 3)
Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3)
update v1 set c=c+1;
select * from t1;
a b
......@@ -1393,7 +1378,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
Warnings:
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`v1` left join `test`.`v2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
execute stmt1;
a a b
......@@ -1694,3 +1679,19 @@ col1 col2 col2 col3
5 david NULL NULL
DROP VIEW v1,v2,v3;
DROP TABLE t1,t2;
CREATE TABLE t1 (a int);
CREATE TABLE t2 (b int);
INSERT INTO t1 VALUES (1), (2), (3), (4);
INSERT INTO t2 VALUES (4), (2);
CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b;
SELECT * FROM v1;
a b
2 2
4 4
CREATE VIEW v2 AS SELECT * FROM v1;
SELECT * FROM v2;
a b
2 2
4 4
DROP VIEW v2,v1;
DROP TABLE t1,t2;
......@@ -148,9 +148,10 @@ insert into t1 values (1), (2), (3);
create view v1 (a) as select a+1 from t1;
create view v2 (a) as select a-1 from t1;
select * from t1 natural left join v1;
select * from v2 natural left join t1;
select * from v2 natural left join v1;
# WL #2486 should enable these tests
#select * from t1 natural left join v1;
#select * from v2 natural left join t1;
#select * from v2 natural left join v1;
drop view v1, v2;
drop table t1;
......@@ -1519,3 +1520,20 @@ SELECT a.col1,a.col2,b.col2,b.col3
DROP VIEW v1,v2,v3;
DROP TABLE t1,t2;
#
# Test case for bug #8528: select from view over multi-table view
#
CREATE TABLE t1 (a int);
CREATE TABLE t2 (b int);
INSERT INTO t1 VALUES (1), (2), (3), (4);
INSERT INTO t2 VALUES (4), (2);
CREATE VIEW v1 AS SELECT * FROM t1,t2 WHERE t1.a=t2.b;
SELECT * FROM v1;
CREATE VIEW v2 AS SELECT * FROM v1;
SELECT * FROM v2;
DROP VIEW v2,v1;
DROP TABLE t1,t2;
......@@ -3157,10 +3157,8 @@ TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
{
for (TABLE_LIST *table= tables; table; table= table->next_local)
{
if (table->view && !table->table)
if (table->view && table->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
/* it is for multi table views only, check it */
DBUG_ASSERT(table->ancestor->next_local != 0);
list= make_leaves_list(list, table->ancestor);
}
else
......
......@@ -46,8 +46,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
DBUG_RETURN(TRUE);
if (!(table= table_list->table))
{
DBUG_ASSERT(table_list->view &&
table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(-1);
......
......@@ -81,8 +81,6 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
{
if (!table)
{
DBUG_ASSERT(table_list->view &&
table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
table_list->view_db.str, table_list->view_name.str);
return -1;
......@@ -124,7 +122,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
thd->lex->select_lex.no_wrap_view_item= 0;
if (res)
return -1;
if (table == 0)
if (table_list->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
/* it is join view => we need to find table for update */
List_iterator_fast<Item> it(fields);
......@@ -134,7 +132,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
while ((item= it++))
map|= item->used_tables();
if (table_list->check_single_table(&tbl, map) || tbl == 0)
if (table_list->check_single_table(&tbl, map, table_list) || tbl == 0)
{
my_error(ER_VIEW_MULTIUPDATE, MYF(0),
table_list->view_db.str, table_list->view_name.str);
......@@ -706,8 +704,6 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
thd->lex->empty_field_list_on_rset= 1;
if (!table_list->table)
{
DBUG_ASSERT(table_list->view &&
table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(TRUE);
......
......@@ -1764,7 +1764,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->lex->
select_lex.table_list.link_in_list((byte*) &table_list,
(byte**) &table_list.next_local);
thd->lex->query_tables= &table_list;
thd->lex->add_to_query_tables(&table_list);
/* switch on VIEW optimisation: do not fill temporary tables */
thd->lex->sql_command= SQLCOM_SHOW_FIELDS;
......
......@@ -1006,7 +1006,7 @@ static int mysql_test_update(Prepared_statement *stmt,
if (!open_tables(thd, &table_list, &table_count))
{
if (table_list->ancestor && table_list->ancestor->next_local)
if (table_list->multitable_view)
{
DBUG_ASSERT(table_list->view != 0);
DBUG_PRINT("info", ("Switch to multi-update"));
......@@ -1095,8 +1095,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
bool res;
if (!table_list->table)
{
DBUG_ASSERT(table_list->view &&
table_list->ancestor && table_list->ancestor->next_local);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
table_list->view_db.str, table_list->view_name.str);
DBUG_RETURN(-1);
......@@ -1458,8 +1456,6 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
return res;
if (!tables->table)
{
DBUG_ASSERT(tables->view &&
tables->ancestor && tables->ancestor->next_local);
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
tables->view_db.str, tables->view_name.str);
return -1;
......
......@@ -7351,7 +7351,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
*/
if (table->on_expr)
{
Item *expr;
Item *expr= table->prep_on_expr ? table->prep_on_expr : table->on_expr;
/*
If an on expression E is attached to the table,
check all null rejected predicates in this expression.
......@@ -7361,7 +7361,7 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
the corresponding on expression is added to E.
*/
expr= simplify_joins(join, &nested_join->join_list,
table->on_expr, FALSE);
expr, FALSE);
table->prep_on_expr= table->on_expr= expr;
}
nested_join->used_tables= (table_map) 0;
......
......@@ -139,7 +139,7 @@ int mysql_update(THD *thd,
if (open_tables(thd, &table_list, &table_count))
DBUG_RETURN(1);
if (table_list->ancestor && table_list->ancestor->next_local)
if (table_list->multitable_view)
{
DBUG_ASSERT(table_list->view != 0);
DBUG_PRINT("info", ("Switch to multi-update"));
......@@ -706,9 +706,11 @@ bool mysql_multi_update_prepare(THD *thd)
if (!tl->placeholder() && !tl->schema_table && !using_lock_tables)
tl->table->reginfo.lock_type= tl->lock_type;
}
}
for(tl= table_list; tl; tl= tl->next_local)
{
/* Check access privileges for table */
if (!tl->derived && !tl->belong_to_view)
if (!tl->derived)
{
uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL;
if (check_access(thd, want_privilege,
......@@ -721,12 +723,10 @@ bool mysql_multi_update_prepare(THD *thd)
/* check single table update for view compound from several tables */
for (tl= table_list; tl; tl= tl->next_local)
{
if (tl->table == 0)
if (tl->effective_algorithm == VIEW_ALGORITHM_MERGE)
{
DBUG_ASSERT(tl->view &&
tl->ancestor && tl->ancestor->next_local);
TABLE_LIST *for_update= 0;
if (tl->check_single_table(&for_update, tables_for_update))
if (tl->check_single_table(&for_update, tables_for_update, tl))
{
my_error(ER_VIEW_MULTIUPDATE, MYF(0),
tl->view_db.str, tl->view_name.str);
......
......@@ -773,9 +773,9 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
tbl->lock_type= table->lock_type;
}
/* multi table view */
if (view_tables->next_local)
{
if (view_tables->next_local)
table->multitable_view= TRUE;
/* make nested join structure for view tables */
NESTED_JOIN *nested_join;
if (!(nested_join= table->nested_join=
......
......@@ -1644,11 +1644,13 @@ void st_table_list::set_ancestor()
*/
tbl->ancestor->set_ancestor();
}
tbl->table->grant= grant;
if (tbl->multitable_view)
multitable_view= TRUE;
if (tbl->table)
tbl->table->grant= grant;
} while ((tbl= tbl->next_local));
/* if view contain only one table, substitute TABLE of it */
if (!ancestor->next_local)
if (!multitable_view)
{
table= ancestor->table;
schema_table= ancestor->schema_table;
......@@ -1675,8 +1677,6 @@ void st_table_list::save_and_clear_want_privilege()
}
else
{
DBUG_ASSERT(tbl->view && tbl->ancestor &&
tbl->ancestor->next_local);
tbl->save_and_clear_want_privilege();
}
}
......@@ -1698,8 +1698,6 @@ void st_table_list::restore_want_privilege()
tbl->table->grant.want_privilege= privilege_backup;
else
{
DBUG_ASSERT(tbl->view && tbl->ancestor &&
tbl->ancestor->next_local);
tbl->restore_want_privilege();
}
}
......@@ -2053,16 +2051,17 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
{
if (check_option && check_option->val_int() == 0)
{
TABLE_LIST *view= (belong_to_view ? belong_to_view : this);
if (ignore_failure)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_VIEW_CHECK_FAILED, ER(ER_VIEW_CHECK_FAILED),
view_db.str, view_name.str);
view->view_db.str, view->view_name.str);
return(VIEW_CHECK_SKIP);
}
else
{
my_error(ER_VIEW_CHECK_FAILED, MYF(0), view_db.str, view_name.str);
my_error(ER_VIEW_CHECK_FAILED, MYF(0), view->view_db.str, view->view_name.str);
return(VIEW_CHECK_ERROR);
}
}
......@@ -2080,13 +2079,15 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
(should be 0 on call, to find table, or point to table for
unique test)
map bit mask of tables
view view for which we are looking table
RETURN
FALSE table not found or found only one
TRUE found several tables
*/
bool st_table_list::check_single_table(st_table_list **table, table_map map)
bool st_table_list::check_single_table(st_table_list **table, table_map map,
st_table_list *view)
{
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
{
......@@ -2097,11 +2098,14 @@ bool st_table_list::check_single_table(st_table_list **table, table_map map)
if (*table)
return TRUE;
else
{
*table= tbl;
tbl->check_option= view->check_option;
}
}
}
else
if (tbl->check_single_table(table, map))
if (tbl->check_single_table(table, map, view))
return TRUE;
}
return FALSE;
......@@ -2131,7 +2135,7 @@ bool st_table_list::set_insert_values(MEM_ROOT *mem_root)
}
else
{
DBUG_ASSERT(view && ancestor && ancestor->next_local);
DBUG_ASSERT(view && ancestor);
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
if (tbl->set_insert_values(mem_root))
return TRUE;
......
......@@ -432,6 +432,10 @@ typedef struct st_table_list
bool skip_temporary; /* this table shouldn't be temporary */
/* TRUE if this merged view contain auto_increment field */
bool contain_auto_increment;
#if 0
#else
bool multitable_view; /* TRUE iff this is multitable view */
#endif
/* FRMTYPE_ERROR if any type is acceptable */
enum frm_type_enum required_type;
char timestamp_buffer[20]; /* buffer for timestamp (19+1) */
......@@ -450,7 +454,8 @@ typedef struct st_table_list
void print(THD *thd, String *str);
void save_and_clear_want_privilege();
void restore_want_privilege();
bool check_single_table(st_table_list **table, table_map map);
bool check_single_table(st_table_list **table, table_map map,
st_table_list *view);
bool set_insert_values(MEM_ROOT *mem_root);
st_table_list *find_underlying_table(TABLE *table);
} TABLE_LIST;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment