Commit 5057d463 authored by Sergei Golubchik's avatar Sergei Golubchik

bugfix: multi-update checked privileges on views incorrectly

it always required UPDATE privilege on views, not being able to detect
when a views was not actually updated in multi-update.

fix: instead of marking all tables as "updating" by default,
only set "updating" on tables that will actually be updated
by multi-update. And mark the view "updating" if any of the
view's tables is.
parent 822071ca
......@@ -173,11 +173,14 @@ create table mysqltest.t1 (a int, b int, primary key(a));
insert into mysqltest.t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
create table mysqltest.t2 (x int);
insert into mysqltest.t2 values (3), (4), (5), (6);
create table mysqltest.t3 (x int);
insert into mysqltest.t3 values (3), (4), (5), (6);
create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1;
grant update (a) on mysqltest.v2 to mysqltest_1@localhost;
grant update on mysqltest.v1 to mysqltest_1@localhost;
grant update on mysqltest.t3 to mysqltest_1@localhost;
grant select on mysqltest.* to mysqltest_1@localhost;
use mysqltest;
update t2,v1 set v1.a=v1.a+v1.c where t2.x=v1.c;
......@@ -212,6 +215,7 @@ a b
48 4
62 5
71 10
update t3,v3 set t3.x=t3.x+v3.c where t3.x=v3.c;
update t2,v2 set v2.c=v2.a+v2.c where t2.x=v2.c;
ERROR 42000: UPDATE command denied to user 'mysqltest_1'@'localhost' for column 'c' in table 'v2'
update v2 set c=a+c;
......
......@@ -240,12 +240,15 @@ create table mysqltest.t1 (a int, b int, primary key(a));
insert into mysqltest.t1 values (10,2), (20,3), (30,4), (40,5), (50,10);
create table mysqltest.t2 (x int);
insert into mysqltest.t2 values (3), (4), (5), (6);
create table mysqltest.t3 (x int);
insert into mysqltest.t3 values (3), (4), (5), (6);
create view mysqltest.v1 (a,c) as select a, b+1 from mysqltest.t1;
create view mysqltest.v2 (a,c) as select a, b from mysqltest.t1;
create view mysqltest.v3 (a,c) as select a, b+1 from mysqltest.t1;
grant update (a) on mysqltest.v2 to mysqltest_1@localhost;
grant update on mysqltest.v1 to mysqltest_1@localhost;
grant update on mysqltest.t3 to mysqltest_1@localhost;
grant select on mysqltest.* to mysqltest_1@localhost;
connection user1;
......@@ -260,6 +263,8 @@ update t2,v2 set v2.a=v2.a+v2.c where t2.x=v2.c;
select * from t1;
update v2 set a=a+c;
select * from t1;
# update a table, select only on view
update t3,v3 set t3.x=t3.x+v3.c where t3.x=v3.c;
# no rights on column
--error ER_COLUMNACCESS_DENIED_ERROR
update t2,v2 set v2.c=v2.a+v2.c where t2.x=v2.c;
......
......@@ -589,7 +589,7 @@ class st_select_lex_node {
enum_mdl_type mdl_type= MDL_SHARED_READ,
List<Index_hint> *hints= 0,
LEX_STRING *option= 0);
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
virtual void set_lock_for_tables(thr_lock_type lock_type, bool for_update) {}
friend class st_select_lex_unit;
friend bool mysql_new_select(LEX *lex, bool move_down);
......@@ -960,7 +960,7 @@ class st_select_lex: public st_select_lex_node
TABLE_LIST *convert_right_join();
List<Item>* get_item_list();
ulong get_table_join_options();
void set_lock_for_tables(thr_lock_type lock_type);
void set_lock_for_tables(thr_lock_type lock_type, bool for_update);
inline void init_order()
{
order_list.elements= 0;
......
......@@ -2065,9 +2065,6 @@ mysql_execute_command(THD *thd)
reset_one_shot_variables(thd);
DBUG_RETURN(0);
}
for (table=all_tables; table; table=table->next_global)
table->updating= TRUE;
}
/*
......@@ -6541,9 +6538,8 @@ TABLE_LIST *st_select_lex::convert_right_join()
query
*/
void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
void st_select_lex::set_lock_for_tables(thr_lock_type lock_type, bool for_update)
{
bool for_update= lock_type >= TL_READ_NO_INSERT;
DBUG_ENTER("set_lock_for_tables");
DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
for_update));
......
......@@ -1305,6 +1305,9 @@ int mysql_multi_update_prepare(THD *thd)
If table will be updated we should not downgrade lock for it and
leave it as is.
*/
tl->updating= 1;
if (tl->belong_to_view)
tl->belong_to_view->updating= 1;
}
else
{
......@@ -1323,7 +1326,6 @@ int mysql_multi_update_prepare(THD *thd)
tl->lock_type= read_lock_type_for_table(thd, lex, tl);
else
tl->set_lock_type(thd, read_lock_type_for_table(thd, lex, tl));
tl->updating= 0;
}
}
for (tl= table_list; tl; tl= tl->next_local)
......
......@@ -7676,14 +7676,14 @@ select_lock_type:
| FOR_SYM UPDATE_SYM
{
LEX *lex=Lex;
lex->current_select->set_lock_for_tables(TL_WRITE);
lex->current_select->set_lock_for_tables(TL_WRITE, false);
lex->safe_to_cache_query=0;
}
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
{
LEX *lex=Lex;
lex->current_select->
set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS, false);
lex->safe_to_cache_query=0;
}
;
......@@ -10966,7 +10966,7 @@ insert:
insert_lock_option
opt_ignore insert2
{
Select->set_lock_for_tables($3);
Select->set_lock_for_tables($3, true);
Lex->current_select= &Lex->select_lex;
}
insert_field_spec opt_insert_update
......@@ -10983,7 +10983,7 @@ replace:
}
replace_lock_option insert2
{
Select->set_lock_for_tables($3);
Select->set_lock_for_tables($3, true);
Lex->current_select= &Lex->select_lex;
}
insert_field_spec
......@@ -11174,7 +11174,7 @@ update:
be too pessimistic. We will decrease lock level if possible in
mysql_multi_update().
*/
slex->set_lock_for_tables($3);
slex->set_lock_for_tables($3, slex->table_list.elements == 1);
}
where_clause opt_order_clause delete_limit_clause {}
;
......
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