mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
Fixed UNION support in view creation (BUG#4664)
This commit is contained in:
parent
5abb148d01
commit
be31afd176
3 changed files with 86 additions and 56 deletions
|
@ -830,7 +830,7 @@ a b c
|
|||
30 4 -60
|
||||
50 6 -100
|
||||
40 5 NULL
|
||||
drop table t1;
|
||||
drop table t1, t2;
|
||||
drop view v1,v2,v3,v4,v5;
|
||||
create database mysqltest;
|
||||
create table mysqltest.t1 (a int, b int, primary key(a));
|
||||
|
@ -1040,7 +1040,6 @@ CREATE VIEW v02 AS SELECT * FROM DUAL;
|
|||
ERROR HY000: No tables used
|
||||
SHOW TABLES;
|
||||
Tables_in_test table_type
|
||||
t2 BASE TABLE
|
||||
v4 VIEW
|
||||
CREATE VIEW v1 AS SELECT EXISTS (SELECT 1 UNION SELECT 2);
|
||||
select * from v1;
|
||||
|
@ -1058,3 +1057,20 @@ SHOW CREATE VIEW v1;
|
|||
Table Create Table
|
||||
v1 CREATE VIEW test.v1 AS select sql_no_cache connection_id() AS `f1`,pi() AS `f2`,current_user() AS `f3`,version() AS `f4`
|
||||
drop view v1;
|
||||
create table t1 (s1 int);
|
||||
create table t2 (s2 int);
|
||||
insert into t1 values (1), (2);
|
||||
insert into t2 values (2), (3);
|
||||
create view v1 as select * from t1,t2 union all select * from t1,t2;
|
||||
select * from v1;
|
||||
s1 s2
|
||||
1 2
|
||||
2 2
|
||||
1 3
|
||||
2 3
|
||||
1 2
|
||||
2 2
|
||||
1 3
|
||||
2 3
|
||||
drop view v1;
|
||||
drop tables t1, t2;
|
||||
|
|
|
@ -693,7 +693,7 @@ insert into v1 select c, b, a from t2;
|
|||
insert into v1 (z,y,x) select a+20,b+2,-100 from t2;
|
||||
insert into v2 select b+1, a+10 from t2;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
drop table t1, t2;
|
||||
drop view v1,v2,v3,v4,v5;
|
||||
|
||||
#
|
||||
|
@ -1004,3 +1004,15 @@ drop table t1;
|
|||
CREATE VIEW v1 (f1,f2,f3,f4) AS SELECT connection_id(), pi(), current_user(), version();
|
||||
SHOW CREATE VIEW v1;
|
||||
drop view v1;
|
||||
|
||||
#
|
||||
# VIEW built over UNION
|
||||
#
|
||||
create table t1 (s1 int);
|
||||
create table t2 (s2 int);
|
||||
insert into t1 values (1), (2);
|
||||
insert into t2 values (2), (3);
|
||||
create view v1 as select * from t1,t2 union all select * from t1,t2;
|
||||
select * from v1;
|
||||
drop view v1;
|
||||
drop tables t1, t2;
|
||||
|
|
108
sql/sql_view.cc
108
sql/sql_view.cc
|
@ -54,7 +54,7 @@ int mysql_create_view(THD *thd,
|
|||
TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
|
||||
TABLE_LIST *tables= lex->query_tables;
|
||||
TABLE_LIST *tbl;
|
||||
SELECT_LEX *select_lex= &lex->select_lex;
|
||||
SELECT_LEX *select_lex= &lex->select_lex, *sl;
|
||||
SELECT_LEX_UNIT *unit= &lex->unit;
|
||||
int res= 0;
|
||||
DBUG_ENTER("mysql_create_view");
|
||||
|
@ -74,56 +74,59 @@ int mysql_create_view(THD *thd,
|
|||
0, 0) ||
|
||||
grant_option && check_grant(thd, CREATE_VIEW_ACL, view, 0, 1, 0))
|
||||
DBUG_RETURN(1);
|
||||
for (tbl= tables; tbl; tbl= tbl->next_local)
|
||||
for (sl= select_lex; sl; sl= sl->next_select())
|
||||
{
|
||||
/*
|
||||
Ensure that we have some privilage on this table, more strict check
|
||||
will be done on column level after preparation,
|
||||
|
||||
SELECT_ACL will be checked for sure for all fields because it is
|
||||
listed first (if we have not rights to SELECT from whole table this
|
||||
right will be written as tbl->grant.want_privilege and will be checked
|
||||
later (except fields which need any privilege and can be updated).
|
||||
*/
|
||||
if ((check_access(thd, SELECT_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 1)) &&
|
||||
(check_access(thd, INSERT_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, INSERT_ACL, tbl, 0, 1, 1)) &&
|
||||
(check_access(thd, DELETE_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, DELETE_ACL, tbl, 0, 1, 1)) &&
|
||||
(check_access(thd, UPDATE_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, UPDATE_ACL, tbl, 0, 1, 1))
|
||||
)
|
||||
for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
|
||||
{
|
||||
my_printf_error(ER_TABLEACCESS_DENIED_ERROR,
|
||||
ER(ER_TABLEACCESS_DENIED_ERROR),
|
||||
MYF(0),
|
||||
"ANY",
|
||||
thd->priv_user,
|
||||
thd->host_or_ip,
|
||||
tbl->real_name);
|
||||
DBUG_RETURN(-1);
|
||||
/*
|
||||
Ensure that we have some privilage on this table, more strict check
|
||||
will be done on column level after preparation,
|
||||
|
||||
SELECT_ACL will be checked for sure for all fields because it is
|
||||
listed first (if we have not rights to SELECT from whole table this
|
||||
right will be written as tbl->grant.want_privilege and will be checked
|
||||
later (except fields which need any privilege and can be updated).
|
||||
*/
|
||||
if ((check_access(thd, SELECT_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 1)) &&
|
||||
(check_access(thd, INSERT_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, INSERT_ACL, tbl, 0, 1, 1)) &&
|
||||
(check_access(thd, DELETE_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, DELETE_ACL, tbl, 0, 1, 1)) &&
|
||||
(check_access(thd, UPDATE_ACL, tbl->db,
|
||||
&tbl->grant.privilege, 0, 1) ||
|
||||
grant_option && check_grant(thd, UPDATE_ACL, tbl, 0, 1, 1))
|
||||
)
|
||||
{
|
||||
my_printf_error(ER_TABLEACCESS_DENIED_ERROR,
|
||||
ER(ER_TABLEACCESS_DENIED_ERROR),
|
||||
MYF(0),
|
||||
"ANY",
|
||||
thd->priv_user,
|
||||
thd->host_or_ip,
|
||||
tbl->real_name);
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
/* mark this table as table which will be checked after preparation */
|
||||
tbl->table_in_first_from_clause= 1;
|
||||
|
||||
/*
|
||||
We need to check only SELECT_ACL for all normal fields, fields
|
||||
where we need any privilege will be pmarked later
|
||||
*/
|
||||
tbl->grant.want_privilege= SELECT_ACL;
|
||||
/*
|
||||
Make sure that all rights are loaded to table 'grant' field.
|
||||
|
||||
tbl->real_name will be correct name of table because VIEWs are
|
||||
not opened yet.
|
||||
*/
|
||||
fill_effective_table_privileges(thd, &tbl->grant, tbl->db,
|
||||
tbl->real_name);
|
||||
}
|
||||
/* mark this table as table which will be checked after preparation */
|
||||
tbl->table_in_first_from_clause= 1;
|
||||
|
||||
/*
|
||||
We need to check only SELECT_ACL for all normal fields, fields
|
||||
where we need any privilege will be pmarked later
|
||||
*/
|
||||
tbl->grant.want_privilege= SELECT_ACL;
|
||||
/*
|
||||
Make sure that all rights are loaded to table 'grant' field.
|
||||
|
||||
tbl->real_name will be correct name of table because VIEWs are
|
||||
not opened yet.
|
||||
*/
|
||||
fill_effective_table_privileges(thd, &tbl->grant, tbl->db,
|
||||
tbl->real_name);
|
||||
}
|
||||
|
||||
if (&lex->select_lex != lex->all_selects_list)
|
||||
|
@ -145,12 +148,10 @@ int mysql_create_view(THD *thd,
|
|||
}
|
||||
/*
|
||||
Mark fields for special privilege check (any privilege)
|
||||
|
||||
'if' should be changed if we made updateable UNION.
|
||||
*/
|
||||
if (lex->select_lex.next_select() == 0)
|
||||
for (sl= select_lex; sl; sl= sl->next_select())
|
||||
{
|
||||
List_iterator_fast<Item> it(lex->select_lex.item_list);
|
||||
List_iterator_fast<Item> it(sl->item_list);
|
||||
Item *item;
|
||||
while ((item= it++))
|
||||
{
|
||||
|
@ -235,9 +236,10 @@ int mysql_create_view(THD *thd,
|
|||
/*
|
||||
Compare/check grants on view with grants of underlaying tables
|
||||
*/
|
||||
for (sl= select_lex; sl; sl= sl->next_select())
|
||||
{
|
||||
char *db= view->db ? view->db : thd->db;
|
||||
List_iterator_fast<Item> it(select_lex->item_list);
|
||||
List_iterator_fast<Item> it(sl->item_list);
|
||||
Item *item;
|
||||
fill_effective_table_privileges(thd, &view->grant, db,
|
||||
view->real_name);
|
||||
|
|
Loading…
Reference in a new issue