List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:July 19 2010 9:22am
Subject:bzr push into mysql-5.1-bugteam branch (jon.hauglid:3490 to 3491) Bug#54734
View as plain text  
 3491 Jon Olav Hauglid	2010-07-19
      Bug #54734 assert in Diagnostics_area::set_ok_status
      
      This assert checks that the server does not try to send OK to the
      client if there has been some error during processing. This is done
      to make sure that the error is in fact sent to the client.
      
      The problem was that view errors during processing of WHERE conditions
      in UPDATE statements where not detected by the update code. It therefore
      tried to send OK to the client, triggering the assert.
      The bug was only noticeable in debug builds.
      
      This patch fixes the problem by making sure that the update code
      checks for errors during condition processing and acts accordingly.

    modified:
      mysql-test/r/update.result
      mysql-test/t/update.test
      sql/filesort.cc
      sql/opt_range.h
      sql/sql_delete.cc
      sql/sql_select.cc
      sql/sql_update.cc
 3490 Davi Arnaut	2010-07-16
      Bug#48327: Some crashes specific to FreeBSD ("embedded")
      Bug#47139: Test "merge" crashes in "embedded" run
      
      Backport patch for Bug#47139

    modified:
      storage/myisam/mi_dynrec.c
=== modified file 'mysql-test/r/update.result'
--- a/mysql-test/r/update.result	2010-03-10 16:10:05 +0000
+++ b/mysql-test/r/update.result	2010-07-19 09:03:52 +0000
@@ -527,3 +527,17 @@ ERROR HY000: You are using safe update m
 SET SESSION sql_safe_updates = DEFAULT;
 DROP TABLE t1;
 DROP VIEW v1;
+#
+# Bug#54734 assert in Diagnostics_area::set_ok_status
+#
+DROP TABLE IF EXISTS t1, not_exists;
+DROP FUNCTION IF EXISTS f1;
+DROP VIEW IF EXISTS v1;
+CREATE TABLE t1 (PRIMARY KEY(pk)) AS SELECT 1 AS pk;
+CREATE FUNCTION f1() RETURNS INTEGER RETURN (SELECT 1 FROM not_exists);
+CREATE VIEW v1 AS SELECT pk FROM t1 WHERE f1() = 13;
+UPDATE v1 SET pk = 7 WHERE pk > 0;
+ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+DROP VIEW v1;
+DROP FUNCTION f1;
+DROP TABLE t1;

=== modified file 'mysql-test/t/update.test'
--- a/mysql-test/t/update.test	2010-03-10 16:10:05 +0000
+++ b/mysql-test/t/update.test	2010-07-19 09:03:52 +0000
@@ -483,3 +483,23 @@ UPDATE IGNORE v1 SET a = 1;
 SET SESSION sql_safe_updates = DEFAULT;
 DROP TABLE t1;
 DROP VIEW v1;
+
+--echo #
+--echo # Bug#54734 assert in Diagnostics_area::set_ok_status
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, not_exists;
+DROP FUNCTION IF EXISTS f1;
+DROP VIEW IF EXISTS v1;
+--enable_warnings
+
+CREATE TABLE t1 (PRIMARY KEY(pk)) AS SELECT 1 AS pk;
+CREATE FUNCTION f1() RETURNS INTEGER RETURN (SELECT 1 FROM not_exists);
+CREATE VIEW v1 AS SELECT pk FROM t1 WHERE f1() = 13;
+--error ER_VIEW_INVALID
+UPDATE v1 SET pk = 7 WHERE pk > 0;
+
+DROP VIEW v1;
+DROP FUNCTION f1;
+DROP TABLE t1;

=== modified file 'sql/filesort.cc'
--- a/sql/filesort.cc	2010-04-12 10:12:20 +0000
+++ b/sql/filesort.cc	2010-07-19 09:03:52 +0000
@@ -514,6 +514,7 @@ static ha_rows find_all_keys(SORTPARAM *
   volatile THD::killed_state *killed= &thd->killed;
   handler *file;
   MY_BITMAP *save_read_set, *save_write_set;
+  bool skip_record;
   DBUG_ENTER("find_all_keys");
   DBUG_PRINT("info",("using: %s",
                      (select ? select->quick ? "ranges" : "where":
@@ -606,7 +607,8 @@ static ha_rows find_all_keys(SORTPARAM *
     }
     if (error == 0)
       param->examined_rows++;
-    if (error == 0 && (!select || select->skip_record() == 0))
+    if (!error && (!select ||
+                   (!select->skip_record(thd, &skip_record) && !skip_record)))
     {
       if (idx == param->keys)
       {

=== modified file 'sql/opt_range.h'
--- a/sql/opt_range.h	2010-06-24 13:21:23 +0000
+++ b/sql/opt_range.h	2010-07-19 09:03:52 +0000
@@ -788,7 +788,11 @@ class SQL_SELECT :public Sql_alloc {
     tmp.set_all();
     return test_quick_select(thd, tmp, 0, limit, force_quick_range) < 0;
   }
-  inline bool skip_record() { return cond ? cond->val_int() == 0 : 0; }
+  inline bool skip_record(THD *thd, bool *skip_record)
+  {
+    *skip_record= cond ? cond->val_int() == FALSE : FALSE;
+    return thd->is_error();
+  }
   int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
 			ha_rows limit, bool force_quick_range);
 };

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2010-06-10 20:45:22 +0000
+++ b/sql/sql_delete.cc	2010-07-19 09:03:52 +0000
@@ -51,6 +51,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   THD::killed_state killed_status= THD::NOT_KILLED;
   DBUG_ENTER("mysql_delete");
   bool save_binlog_row_based;
+  bool skip_record;
 
   THD::enum_binlog_query_type query_type=
     thd->lex->sql_command == SQLCOM_TRUNCATE ?
@@ -307,7 +308,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   {
     thd->examined_row_count++;
     // thd->is_error() is tested to disallow delete row on error
-    if (!(select && select->skip_record())&& ! thd->is_error() )
+    if (!select || (!select->skip_record(thd, &skip_record) && !skip_record))
     {
 
       if (triggers_applicable &&

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2010-07-09 10:39:47 +0000
+++ b/sql/sql_select.cc	2010-07-19 09:03:52 +0000
@@ -11657,38 +11657,30 @@ flush_cached_records(JOIN *join,JOIN_TAB
     SQL_SELECT *select=join_tab->select;
     if (rc == NESTED_LOOP_OK)
     {
-      bool consider_record= !join_tab->cache.select || 
-        !join_tab->cache.select->skip_record();
-
-      /*
-        Check for error: skip_record() can execute code by calling
-        Item_subselect::val_*. We need to check for errors (if any)
-        after such call.
-      */
-      if (join->thd->is_error())
+      bool skip_record= FALSE;
+      if (join_tab->cache.select &&
+          join_tab->cache.select->skip_record(join->thd, &skip_record))
       {
         reset_cache_write(&join_tab->cache);
         return NESTED_LOOP_ERROR;
       }
 
-      if (consider_record)  
+      if (!skip_record)
       {
         uint i;
         reset_cache_read(&join_tab->cache);
         for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
         {
           read_cached_record(join_tab);
-          if (!select || !select->skip_record())
+          skip_record= FALSE;
+          if (select && select->skip_record(join->thd, &skip_record))
           {
-            /*
-              Check for error: skip_record() can execute code by calling
-              Item_subselect::val_*. We need to check for errors (if any)
-              after such call.
-              */
-            if (join->thd->is_error())
-              rc= NESTED_LOOP_ERROR;
-            else
-              rc= (join_tab->next_select)(join,join_tab+1,0);
+            reset_cache_write(&join_tab->cache);
+            return NESTED_LOOP_ERROR;
+          }
+          if (!skip_record)
+          {
+            rc= (join_tab->next_select)(join,join_tab+1,0);
             if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
             {
               reset_cache_write(&join_tab->cache);

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2010-06-10 20:45:22 +0000
+++ b/sql/sql_update.cc	2010-07-19 09:03:52 +0000
@@ -473,7 +473,14 @@ int mysql_update(THD *thd,
       while (!(error=info.read_record(&info)) && !thd->killed)
       {
         thd->examined_row_count++;
-	if (!(select && select->skip_record()))
+        bool skip_record= FALSE;
+        if (select && select->skip_record(thd, &skip_record))
+        {
+          error= 1;
+          table->file->unlock_row();
+          break;
+        }
+        if (!skip_record)
 	{
           if (table->file->was_semi_consistent_read())
 	    continue;  /* repeat the read of the same row if it still exists */
@@ -580,7 +587,8 @@ int mysql_update(THD *thd,
   while (!(error=info.read_record(&info)) && !thd->killed)
   {
     thd->examined_row_count++;
-    if (!(select && select->skip_record()))
+    bool skip_record;
+    if (!select || (!select->skip_record(thd, &skip_record) && !skip_record))
     {
       if (table->file->was_semi_consistent_read())
         continue;  /* repeat the read of the same row if it still exists */


Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20100719090352-40qkjnfs1ikcktpv.bundle
Thread
bzr push into mysql-5.1-bugteam branch (jon.hauglid:3490 to 3491) Bug#54734Jon Olav Hauglid19 Jul