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. mysql-test/r/view.result: Added test case for bug #8528. Fixed other test cases. mysql-test/t/view.test: Added test case for bug #8528. sql/sql_base.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_delete.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_insert.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_parse.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_prepare.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_select.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_update.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/sql_view.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/table.cc: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views. sql/table.h: Fixed bug #8528. Representation for single-table views was made similar to representation for multi-table views.
This commit is contained in:
parent
179451fc2a
commit
e02416c53c
@ -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=
|
||||
|
28
sql/table.cc
28
sql/table.cc
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user