From: Jorgen Loland Date: November 15 2010 3:35pm Subject: bzr commit into mysql-trunk branch (jorgen.loland:3341) Bug#54812 List-Archive: http://lists.mysql.com/commits/123932 X-Bug: 54812 Message-Id: <20101115153505.66EF41EE1@atum21.norway.sun.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///export/home/jl208045/mysql/mysql-trunk-bugfixing/ based on revid:alexander.nozdrin@stripped 3341 Jorgen Loland 2010-11-15 [merge] Merge BUG#54812 from 5.5-bugteam to trunk-bugfixing. No conflicts. modified: mysql-test/r/not_embedded_server.result mysql-test/t/not_embedded_server.test sql/sql_class.cc sql/sql_insert.cc sql/sql_prepare.cc sql/sql_update.cc === modified file 'mysql-test/r/not_embedded_server.result' --- a/mysql-test/r/not_embedded_server.result 2009-12-04 23:02:48 +0000 +++ b/mysql-test/r/not_embedded_server.result 2010-11-15 15:18:04 +0000 @@ -14,3 +14,32 @@ flush privileges; ERROR HY000: Table 'host' was not locked with LOCK TABLES unlock tables; drop table t1; +# +# Bug#54812: assert in Diagnostics_area::set_ok_status during EXPLAIN +# +CREATE USER nopriv_user@localhost; +connection: default +DROP TABLE IF EXISTS t1,t2,t3; +DROP FUNCTION IF EXISTS f; +CREATE TABLE t1 (key1 INT PRIMARY KEY); +CREATE TABLE t2 (key2 INT); +INSERT INTO t1 VALUES (1),(2); +CREATE FUNCTION f() RETURNS INT RETURN 1; +GRANT FILE ON *.* TO 'nopriv_user'@'localhost'; +FLUSH PRIVILEGES; +connection: con1 +SELECT MAX(key1) FROM t1 WHERE f() < 1 INTO OUTFILE 'mytest'; +ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f' +INSERT INTO t2 SELECT MAX(key1) FROM t1 WHERE f() < 1; +ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f' +SELECT MAX(key1) INTO @dummy FROM t1 WHERE f() < 1; +ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f' +CREATE TABLE t3 (i INT) AS SELECT MAX(key1) FROM t1 WHERE f() < 1; +ERROR 42000: execute command denied to user 'nopriv_user'@'localhost' for routine 'test.f' +connection: default +DROP TABLE t1,t2; +DROP FUNCTION f; +DROP USER nopriv_user@localhost; +# +# End Bug#54812 +# === modified file 'mysql-test/t/not_embedded_server.test' --- a/mysql-test/t/not_embedded_server.test 2009-12-04 23:02:48 +0000 +++ b/mysql-test/t/not_embedded_server.test 2010-11-15 15:18:04 +0000 @@ -54,3 +54,57 @@ lock tables t1 read; flush privileges; unlock tables; drop table t1; + +--echo # +--echo # Bug#54812: assert in Diagnostics_area::set_ok_status during EXPLAIN +--echo # + +CREATE USER nopriv_user@localhost; + +connection default; +--echo connection: default + +--disable_warnings +DROP TABLE IF EXISTS t1,t2,t3; +DROP FUNCTION IF EXISTS f; +--enable_warnings + +CREATE TABLE t1 (key1 INT PRIMARY KEY); +CREATE TABLE t2 (key2 INT); +INSERT INTO t1 VALUES (1),(2); + +CREATE FUNCTION f() RETURNS INT RETURN 1; + +GRANT FILE ON *.* TO 'nopriv_user'@'localhost'; + +FLUSH PRIVILEGES; + +connect (con1,localhost,nopriv_user,,); +connection con1; +--echo connection: con1 + +--error ER_PROCACCESS_DENIED_ERROR +SELECT MAX(key1) FROM t1 WHERE f() < 1 INTO OUTFILE 'mytest'; + +--error ER_PROCACCESS_DENIED_ERROR +INSERT INTO t2 SELECT MAX(key1) FROM t1 WHERE f() < 1; + +--error ER_PROCACCESS_DENIED_ERROR +SELECT MAX(key1) INTO @dummy FROM t1 WHERE f() < 1; + +--error ER_PROCACCESS_DENIED_ERROR +CREATE TABLE t3 (i INT) AS SELECT MAX(key1) FROM t1 WHERE f() < 1; + +disconnect con1; +--source include/wait_until_disconnected.inc + +connection default; +--echo connection: default + +DROP TABLE t1,t2; +DROP FUNCTION f; +DROP USER nopriv_user@localhost; + +--echo # +--echo # End Bug#54812 +--echo # === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2010-10-25 12:13:13 +0000 +++ b/sql/sql_class.cc 2010-11-15 15:34:57 +0000 @@ -1846,8 +1846,9 @@ void select_to_file::send_error(uint err bool select_to_file::send_eof() { int error= test(end_io_cache(&cache)); - if (mysql_file_close(file, MYF(MY_WME))) - error= 1; + if (mysql_file_close(file, MYF(MY_WME)) || thd->is_error()) + error= true; + if (!error) { ::my_ok(thd,row_count); @@ -2888,6 +2889,13 @@ bool select_dumpvar::send_eof() if (! row_count) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA)); + /* + Don't send EOF if we're in error condition (which implies we've already + sent or are sending an error) + */ + if (thd->is_error()) + return true; + ::my_ok(thd,row_count); return 0; } === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2010-11-04 15:40:18 +0000 +++ b/sql/sql_insert.cc 2010-11-15 15:34:57 +0000 @@ -3540,6 +3540,9 @@ bool select_insert::send_eof() error= (thd->locked_tables_mode <= LTM_LOCK_TABLES ? table->file->ha_end_bulk_insert() : 0); + if (!error && thd->is_error()) + error= thd->stmt_da->sql_errno(); + table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); @@ -4083,7 +4086,7 @@ bool select_create::send_eof() { bool tmp=select_insert::send_eof(); if (tmp) - abort(); + abort_result_set(); else { /* @@ -4115,7 +4118,7 @@ void select_create::abort_result_set() DBUG_ENTER("select_create::abort_result_set"); /* - In select_insert::abort() we roll back the statement, including + In select_insert::abort_result_set() we roll back the statement, including truncating the transaction cache of the binary log. To do this, we pretend that the statement is transactional, even though it might be the case that it was not. === modified file 'sql/sql_prepare.cc' --- a/sql/sql_prepare.cc 2010-11-14 18:09:32 +0000 +++ b/sql/sql_prepare.cc 2010-11-15 15:34:57 +0000 @@ -2899,8 +2899,15 @@ bool Select_fetch_protocol_binary::send_ bool Select_fetch_protocol_binary::send_eof() { + /* + Don't send EOF if we're in error condition (which implies we've already + sent or are sending an error) + */ + if (thd->is_error()) + return true; + ::my_eof(thd); - return FALSE; + return false; } === modified file 'sql/sql_update.cc' --- a/sql/sql_update.cc 2010-10-21 12:18:25 +0000 +++ b/sql/sql_update.cc 2010-11-15 15:34:57 +0000 @@ -2065,7 +2065,9 @@ bool multi_update::send_eof() Does updates for the last n - 1 tables, returns 0 if ok; error takes into account killed status gained in do_updates() */ - int local_error = (table_count) ? do_updates() : 0; + int local_error= thd->is_error(); + if (!local_error) + local_error = (table_count) ? do_updates() : 0; /* if local_error is not set ON until after do_updates() then later carried out killing should not affect binlogging. No bundle (reason: revision is a merge).