Loading mysql-test/r/read_only.result 0 → 100644 +41 −0 Original line number Diff line number Diff line DROP TABLE IF EXISTS t1,t2,t3; grant CREATE, SELECT, DROP on *.* to test@localhost; set global read_only=0; create table t1 (a int); insert into t1 values(1); create table t2 select * from t1; set global read_only=1; create table t3 (a int); drop table t3; select @@global.read_only; @@global.read_only 1 create table t3 (a int); ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement insert into t1 values(1); ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement delete t1,t2 from t1,t2 where t1.a=t2.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement create temporary table t3 (a int); create temporary table t4 (a int) select * from t3; insert into t3 values(1); insert into t4 select * from t3; update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a; update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a; delete t1 from t1,t3 where t1.a=t3.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement delete t3 from t1,t3 where t1.a=t3.a; delete t4 from t3,t4 where t4.a=t3.a; create temporary table t1 (a int); insert into t1 values(1); update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; delete t1 from t1,t3 where t1.a=t3.a; drop table t1; insert into t1 values(1); ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement drop table t1,t2; drop user test@localhost; mysql-test/t/read_only.test 0 → 100644 +103 −0 Original line number Diff line number Diff line # Test of the READ_ONLY global variable: # check that it blocks updates unless they are only on temporary tables. --disable_warnings DROP TABLE IF EXISTS t1,t2,t3; --enable_warnings # READ_ONLY does nothing to SUPER users # so we use a non-SUPER one: grant CREATE, SELECT, DROP on *.* to test@localhost; connect (con1,localhost,test,,test); connection default; set global read_only=0; connection con1; create table t1 (a int); insert into t1 values(1); create table t2 select * from t1; connection default; set global read_only=1; # We check that SUPER can: create table t3 (a int); drop table t3; connection con1; select @@global.read_only; --error 1290 create table t3 (a int); --error 1290 insert into t1 values(1); # if a statement, after parse stage, looks like it will update a # non-temp table, it will be rejected, even if at execution it would # have turned out that 0 rows would be updated --error 1290 update t1 set a=1 where 1=0; # multi-update is special (see sql_parse.cc) so we test it --error 1290 update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a; # check multi-delete to be sure --error 1290 delete t1,t2 from t1,t2 where t1.a=t2.a; # With temp tables updates should be accepted: create temporary table t3 (a int); create temporary table t4 (a int) select * from t3; insert into t3 values(1); insert into t4 select * from t3; # a non-temp table updated: --error 1290 update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; # no non-temp table updated (just swapped): update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a; update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a; --error 1290 delete t1 from t1,t3 where t1.a=t3.a; delete t3 from t1,t3 where t1.a=t3.a; delete t4 from t3,t4 where t4.a=t3.a; # and even homonymous ones create temporary table t1 (a int); insert into t1 values(1); update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; delete t1 from t1,t3 where t1.a=t3.a; drop table t1; --error 1290 insert into t1 values(1); connection default; drop table t1,t2; drop user test@localhost; sql/sql_parse.cc +37 −10 Original line number Diff line number Diff line Loading @@ -194,6 +194,18 @@ inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) #endif static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables) { for (TABLE_LIST *table= tables; table; table= table->next_global) { DBUG_ASSERT(table->db && table->table_name); if (table->updating && !find_temporary_table(thd, table->db, table->table_name)) return 1; } return 0; } static HASH hash_user_connections; static int get_or_create_user_conn(THD *thd, const char *user, Loading Loading @@ -2365,7 +2377,7 @@ mysql_execute_command(THD *thd) mysql_reset_errors(thd, 0); #ifdef HAVE_REPLICATION if (thd->slave_thread) if (unlikely(thd->slave_thread)) { /* Check if statment should be skipped because of slave filtering Loading Loading @@ -2404,16 +2416,20 @@ mysql_execute_command(THD *thd) } #endif } else #endif /* HAVE_REPLICATION */ /* When option readonly is set deny operations which change tables. Except for the replication thread and the 'super' users. When option readonly is set deny operations which change non-temporary tables. Except for the replication thread and the 'super' users. */ if (opt_readonly && !(thd->slave_thread || (thd->security_ctx->master_access & SUPER_ACL)) && uc_update_queries[lex->sql_command]) !(thd->security_ctx->master_access & SUPER_ACL) && uc_update_queries[lex->sql_command] && !((lex->sql_command == SQLCOM_CREATE_TABLE) && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && ((lex->sql_command != SQLCOM_UPDATE_MULTI) && some_non_temp_table_to_be_updated(thd, all_tables))) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); DBUG_RETURN(-1); Loading Loading @@ -3212,13 +3228,24 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION /* Check slave filtering rules */ if (thd->slave_thread && all_tables_not_ok(thd, all_tables)) if (unlikely(thd->slave_thread)) { if (all_tables_not_ok(thd, all_tables)) { /* we warn the slave SQL thread */ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); break; } } else #endif /* HAVE_REPLICATION */ if (opt_readonly && !(thd->security_ctx->master_access & SUPER_ACL) && some_non_temp_table_to_be_updated(thd, all_tables)) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); break; } res= mysql_multi_update(thd, all_tables, &select_lex->item_list, Loading Loading
mysql-test/r/read_only.result 0 → 100644 +41 −0 Original line number Diff line number Diff line DROP TABLE IF EXISTS t1,t2,t3; grant CREATE, SELECT, DROP on *.* to test@localhost; set global read_only=0; create table t1 (a int); insert into t1 values(1); create table t2 select * from t1; set global read_only=1; create table t3 (a int); drop table t3; select @@global.read_only; @@global.read_only 1 create table t3 (a int); ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement insert into t1 values(1); ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement delete t1,t2 from t1,t2 where t1.a=t2.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement create temporary table t3 (a int); create temporary table t4 (a int) select * from t3; insert into t3 values(1); insert into t4 select * from t3; update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a; update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a; delete t1 from t1,t3 where t1.a=t3.a; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement delete t3 from t1,t3 where t1.a=t3.a; delete t4 from t3,t4 where t4.a=t3.a; create temporary table t1 (a int); insert into t1 values(1); update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; delete t1 from t1,t3 where t1.a=t3.a; drop table t1; insert into t1 values(1); ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement drop table t1,t2; drop user test@localhost;
mysql-test/t/read_only.test 0 → 100644 +103 −0 Original line number Diff line number Diff line # Test of the READ_ONLY global variable: # check that it blocks updates unless they are only on temporary tables. --disable_warnings DROP TABLE IF EXISTS t1,t2,t3; --enable_warnings # READ_ONLY does nothing to SUPER users # so we use a non-SUPER one: grant CREATE, SELECT, DROP on *.* to test@localhost; connect (con1,localhost,test,,test); connection default; set global read_only=0; connection con1; create table t1 (a int); insert into t1 values(1); create table t2 select * from t1; connection default; set global read_only=1; # We check that SUPER can: create table t3 (a int); drop table t3; connection con1; select @@global.read_only; --error 1290 create table t3 (a int); --error 1290 insert into t1 values(1); # if a statement, after parse stage, looks like it will update a # non-temp table, it will be rejected, even if at execution it would # have turned out that 0 rows would be updated --error 1290 update t1 set a=1 where 1=0; # multi-update is special (see sql_parse.cc) so we test it --error 1290 update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a; # check multi-delete to be sure --error 1290 delete t1,t2 from t1,t2 where t1.a=t2.a; # With temp tables updates should be accepted: create temporary table t3 (a int); create temporary table t4 (a int) select * from t3; insert into t3 values(1); insert into t4 select * from t3; # a non-temp table updated: --error 1290 update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; # no non-temp table updated (just swapped): update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a; update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a; --error 1290 delete t1 from t1,t3 where t1.a=t3.a; delete t3 from t1,t3 where t1.a=t3.a; delete t4 from t3,t4 where t4.a=t3.a; # and even homonymous ones create temporary table t1 (a int); insert into t1 values(1); update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; delete t1 from t1,t3 where t1.a=t3.a; drop table t1; --error 1290 insert into t1 values(1); connection default; drop table t1,t2; drop user test@localhost;
sql/sql_parse.cc +37 −10 Original line number Diff line number Diff line Loading @@ -194,6 +194,18 @@ inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables) #endif static bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables) { for (TABLE_LIST *table= tables; table; table= table->next_global) { DBUG_ASSERT(table->db && table->table_name); if (table->updating && !find_temporary_table(thd, table->db, table->table_name)) return 1; } return 0; } static HASH hash_user_connections; static int get_or_create_user_conn(THD *thd, const char *user, Loading Loading @@ -2365,7 +2377,7 @@ mysql_execute_command(THD *thd) mysql_reset_errors(thd, 0); #ifdef HAVE_REPLICATION if (thd->slave_thread) if (unlikely(thd->slave_thread)) { /* Check if statment should be skipped because of slave filtering Loading Loading @@ -2404,16 +2416,20 @@ mysql_execute_command(THD *thd) } #endif } else #endif /* HAVE_REPLICATION */ /* When option readonly is set deny operations which change tables. Except for the replication thread and the 'super' users. When option readonly is set deny operations which change non-temporary tables. Except for the replication thread and the 'super' users. */ if (opt_readonly && !(thd->slave_thread || (thd->security_ctx->master_access & SUPER_ACL)) && uc_update_queries[lex->sql_command]) !(thd->security_ctx->master_access & SUPER_ACL) && uc_update_queries[lex->sql_command] && !((lex->sql_command == SQLCOM_CREATE_TABLE) && (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && ((lex->sql_command != SQLCOM_UPDATE_MULTI) && some_non_temp_table_to_be_updated(thd, all_tables))) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); DBUG_RETURN(-1); Loading Loading @@ -3212,13 +3228,24 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION /* Check slave filtering rules */ if (thd->slave_thread && all_tables_not_ok(thd, all_tables)) if (unlikely(thd->slave_thread)) { if (all_tables_not_ok(thd, all_tables)) { /* we warn the slave SQL thread */ my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); break; } } else #endif /* HAVE_REPLICATION */ if (opt_readonly && !(thd->security_ctx->master_access & SUPER_ACL) && some_non_temp_table_to_be_updated(thd, all_tables)) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); break; } res= mysql_multi_update(thd, all_tables, &select_lex->item_list, Loading