From: konstantin Date: December 1 2006 10:58am Subject: bk commit into 5.1 tree (kostja:1.2370) List-Archive: http://lists.mysql.com/commits/16297 Message-Id: <20061201105832.3688ACA4@bodhi.local> Below is the list of changes that have just been committed into a local 5.1 repository of kostja. When kostja does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2006-12-01 13:58:22+03:00, kostja@stripped +5 -0 Merge bk-internal.mysql.com:/home/bk/mysql-5.1 into bodhi.local:/opt/local/work/mysql-5.1-runtime MERGE: 1.2364.1.4 server-tools/instance-manager/guardian.cc@stripped, 2006-12-01 13:58:13+03:00, kostja@stripped +0 -0 Auto merged MERGE: 1.33.1.1 sql/handler.cc@stripped, 2006-12-01 13:58:13+03:00, kostja@stripped +0 -0 Auto merged MERGE: 1.283.1.1 sql/set_var.cc@stripped, 2006-12-01 13:58:13+03:00, kostja@stripped +0 -0 Auto merged MERGE: 1.204.1.1 sql/sql_class.h@stripped, 2006-12-01 13:58:13+03:00, kostja@stripped +0 -0 Auto merged MERGE: 1.330.1.1 sql/sql_prepare.cc@stripped, 2006-12-01 13:58:13+03:00, kostja@stripped +0 -0 Auto merged MERGE: 1.184.1.1 # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: kostja # Host: bodhi.local # Root: /opt/local/work/mysql-5.1-runtime/RESYNC --- 1.285/sql/handler.cc 2006-12-01 13:58:31 +03:00 +++ 1.286/sql/handler.cc 2006-12-01 13:58:31 +03:00 @@ -692,6 +692,19 @@ int ha_commit_trans(THD *thd, bool all) ha_rollback_trans(thd, all); DBUG_RETURN(1); } + + if ( is_real_trans + && opt_readonly + && ! (thd->security_ctx->master_access & SUPER_ACL) + && ! thd->slave_thread + ) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); + ha_rollback_trans(thd, all); + error= 1; + goto end; + } + DBUG_EXECUTE_IF("crash_commit_before", abort();); /* Close all cursors that can not survive COMMIT */ --- 1.331/sql/sql_class.h 2006-12-01 13:58:31 +03:00 +++ 1.332/sql/sql_class.h 2006-12-01 13:58:31 +03:00 @@ -1703,7 +1703,14 @@ public: virtual bool initialize_tables (JOIN *join=0) { return 0; } virtual void send_error(uint errcode,const char *err); virtual bool send_eof()=0; - virtual bool simple_select() { return 0; } + /** + Check if this query returns a result set and therefore is allowed in + cursors and set an error message if it is not the case. + + @retval FALSE success + @retval TRUE error, an error message is set + */ + virtual bool check_simple_select() const; virtual void abort() {} /* Cleanup instance of this class for next execution of a prepared @@ -1741,7 +1748,7 @@ public: bool send_fields(List &list, uint flags); bool send_data(List &items); bool send_eof(); - bool simple_select() { return 1; } + virtual bool check_simple_select() const { return FALSE; } void abort(); }; @@ -2189,6 +2196,7 @@ public: int prepare(List &list, SELECT_LEX_UNIT *u); bool send_data(List &items); bool send_eof(); + virtual bool check_simple_select() const; void cleanup(); }; --- 1.205/sql/set_var.cc 2006-12-01 13:58:31 +03:00 +++ 1.206/sql/set_var.cc 2006-12-01 13:58:31 +03:00 @@ -369,7 +369,7 @@ sys_var_thd_ulong sys_preload_buff &SV::preload_buff_size); sys_var_thd_ulong sys_read_buff_size("read_buffer_size", &SV::read_buff_size); -sys_var_bool_ptr sys_readonly("read_only", &opt_readonly); +sys_var_opt_readonly sys_readonly("read_only", &opt_readonly); sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size", &SV::read_rnd_buff_size); sys_var_thd_ulong sys_div_precincrement("div_precision_increment", @@ -3855,6 +3855,70 @@ bool sys_var_trust_routine_creators::upd warn_deprecated(thd); return sys_var_bool_ptr::update(thd, var); } + +bool sys_var_opt_readonly::update(THD *thd, set_var *var) +{ + bool result; + + DBUG_ENTER("sys_var_opt_readonly::update"); + + /* Prevent self dead-lock */ + if (thd->locked_tables || thd->active_transaction()) + { + my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); + DBUG_RETURN(true); + } + + if (thd->global_read_lock) + { + /* + This connection already holds the global read lock. + This can be the case with: + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = 1 + */ + result= sys_var_bool_ptr::update(thd, var); + DBUG_RETURN(result); + } + + /* + Perform a 'FLUSH TABLES WITH READ LOCK'. + This is a 3 step process: + - [1] lock_global_read_lock() + - [2] close_cached_tables() + - [3] make_global_read_lock_block_commit() + [1] prevents new connections from obtaining tables locked for write. + [2] waits until all existing connections close their tables. + [3] prevents transactions from being committed. + */ + + if (lock_global_read_lock(thd)) + DBUG_RETURN(true); + + /* + This call will be blocked by any connection holding a READ or WRITE lock. + Ideally, we want to wait only for pending WRITE locks, but since: + con 1> LOCK TABLE T FOR READ; + con 2> LOCK TABLE T FOR WRITE; (blocked by con 1) + con 3> SET GLOBAL READ ONLY=1; (blocked by con 2) + can cause to wait on a read lock, it's required for the client application + to unlock everything, and acceptable for the server to wait on all locks. + */ + if (close_cached_tables(thd, true, NULL, false)) + goto end_with_read_lock; + + if (result= make_global_read_lock_block_commit(thd)) + goto end_with_read_lock; + + /* Change the opt_readonly system variable, safe because the lock is held */ + result= sys_var_bool_ptr::update(thd, var); + +end_with_read_lock: + /* Release the lock */ + unlock_global_read_lock(thd); + DBUG_RETURN(result); +} + /* even session variable here requires SUPER, because of -#o,file */ bool sys_var_thd_dbug::check(THD *thd, set_var *var) --- 1.186/sql/sql_prepare.cc 2006-12-01 13:58:32 +03:00 +++ 1.187/sql/sql_prepare.cc 2006-12-01 13:58:32 +03:00 @@ -2946,10 +2946,9 @@ bool Prepared_statement::execute(String in INSERT ... SELECT and similar commands. */ - if (open_cursor && lex->result && !lex->result->simple_select()) + if (open_cursor && lex->result && lex->result->check_simple_select()) { DBUG_PRINT("info",("Cursor asked for not SELECT stmt")); - my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0)); return TRUE; }