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