List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:March 22 2011 10:06am
Subject:bzr commit into mysql-5.5 branch (alexander.nozdrin:3390) Bug#11763413
View as plain text  
#At file:///home/alik/MySQL/bzr/00/bug56115/mysql-5.5-bug56115/ based on revid:vinay.fisrekar@stripped

 3390 Alexander Nozdrin	2011-03-22
      A patch for Bug#11763413 (56115: SELECT doesn't work in
      prepared statements with cursor protocol).
      
      The problem was a bug in Materialized-cursor implementation.
      Materialized_cursor::open() called send_result_metadata()
      with items pointing to already closed table.
      
      The fix is to send metadata when the table is still open.
      
      NOTE: this is a "partial" fix: metadata are different with
      and without --cursor-protocol, but that's a different large
      problem, one indication of which is reported as Bug 24176.

    modified:
      mysql-test/r/ps.result
      mysql-test/t/ps.test
      sql/sql_cursor.cc
      tests/mysql_client_test.c
=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result	2010-11-13 15:05:02 +0000
+++ b/mysql-test/r/ps.result	2011-03-22 10:06:54 +0000
@@ -3731,5 +3731,19 @@ CREATE TABLE t1 (a INT);
 BEGIN;
 PREPARE stmt1 FROM "SELECT * FROM t1";
 DROP TABLE t1;
+
 #
-# End of 6.0 tests.
+# Bug#56115: invalid memory reads when PS selecting from
+#            information_schema tables
+# Bug#58701: crash in Field::make_field, cursor-protocol
+#
+# NOTE: MTR should be run both with --ps-protocol and --cursor-protocol.
+#
+
+SELECT *
+FROM (SELECT 1 UNION SELECT 2) t;
+1
+1
+2
+#
+# End of 5.5 tests.

=== modified file 'mysql-test/t/ps.test'
--- a/mysql-test/t/ps.test	2010-11-13 15:05:02 +0000
+++ b/mysql-test/t/ps.test	2011-03-22 10:06:54 +0000
@@ -3344,7 +3344,21 @@ connection default;
 DROP TABLE t1;
 disconnect con1;
 
+--echo
 --echo #
---echo # End of 6.0 tests.
+--echo # Bug#56115: invalid memory reads when PS selecting from
+--echo #            information_schema tables
+--echo # Bug#58701: crash in Field::make_field, cursor-protocol
+--echo #
+--echo # NOTE: MTR should be run both with --ps-protocol and --cursor-protocol.
+--echo #
+--echo
+
+SELECT *
+FROM (SELECT 1 UNION SELECT 2) t;
+
+
+--echo #
+--echo # End of 5.5 tests.
 
 ###########################################################################

=== modified file 'sql/sql_cursor.cc'
--- a/sql/sql_cursor.cc	2010-12-08 16:47:21 +0000
+++ b/sql/sql_cursor.cc	2011-03-22 10:06:54 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2006 MySQL AB
+/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -46,7 +46,7 @@ class Materialized_cursor: public Server
 public:
   Materialized_cursor(select_result *result, TABLE *table);
 
-  int fill_item_list(THD *thd, List<Item> &send_result_set_metadata);
+  int send_result_set_metadata(THD *thd, List<Item> &send_result_set_metadata);
   virtual bool is_open() const { return table != 0; }
   virtual int open(JOIN *join __attribute__((unused)));
   virtual void fetch(ulong num_rows);
@@ -133,7 +133,13 @@ int mysql_open_cursor(THD *thd, select_r
   if (rc)
   {
     if (result_materialize->materialized_cursor)
+    {
+      /* Rollback metadata in the client-server protocol. */
+      result_materialize->abort_result_set();
+
       delete result_materialize->materialized_cursor;
+    }
+
     goto end;
   }
 
@@ -142,6 +148,12 @@ int mysql_open_cursor(THD *thd, select_r
     Materialized_cursor *materialized_cursor=
       result_materialize->materialized_cursor;
 
+    /*
+      NOTE: close_thread_tables() has been called in
+      mysql_execute_command(), so all tables except from the cursor
+      temporary table have been closed.
+    */
+
     if ((rc= materialized_cursor->open(0)))
     {
       delete materialized_cursor;
@@ -202,14 +214,16 @@ Materialized_cursor::Materialized_cursor
 
 
 /**
-  Preserve the original metadata that would be sent to the client.
+  Preserve the original metadata to be sent to the client.
+  Initiate sending of the original metadata to the client
+  (call Protocol::send_result_set_metadata()).
 
   @param thd Thread identifier.
   @param send_result_set_metadata List of fields that would be sent.
 */
 
-int Materialized_cursor::fill_item_list(THD *thd,
-                                        List<Item> &send_result_set_metadata)
+int Materialized_cursor::send_result_set_metadata(
+  THD *thd, List<Item> &send_result_set_metadata)
 {
   Query_arena backup_arena;
   int rc;
@@ -241,6 +255,14 @@ int Materialized_cursor::fill_item_list(
     ident->db_name=    thd->strdup(send_field.db_name);
     ident->table_name= thd->strdup(send_field.table_name);
   }
+
+  /*
+    Original metadata result set should be sent here. After
+    mysql_execute_command() is finished, item_list can not be used for
+    sending metadata, because it references closed table.
+  */
+  rc= result->send_result_set_metadata(item_list, Protocol::SEND_NUM_ROWS);
+
 end:
   thd->restore_active_arena(this, &backup_arena);
   /* Check for thd->is_error() in case of OOM */
@@ -253,31 +275,29 @@ int Materialized_cursor::open(JOIN *join
   THD *thd= fake_unit.thd;
   int rc;
   Query_arena backup_arena;
+
   thd->set_n_backup_active_arena(this, &backup_arena);
-  /* Create a list of fields and start sequential scan */
+
+  /* Create a list of fields and start sequential scan. */
+
   rc= result->prepare(item_list, &fake_unit);
-  if (!rc && !(rc= table->file->ha_rnd_init(TRUE)))
-    is_rnd_inited= 1;
+  rc= !rc && table->file->ha_rnd_init(TRUE);
+  is_rnd_inited= !rc;
 
   thd->restore_active_arena(this, &backup_arena);
-  if (rc == 0)
-  {
-    /*
-      Now send the result set metadata to the client. We need to
-      do it here, as in Select_materialize::send_result_set_metadata the items
-      for column types are not yet created (send_result_set_metadata requires
-      a list of items). The new types may differ from the original
-      ones sent at prepare if some of them were altered by MySQL
-      HEAP tables mechanism -- used when create_tmp_field_from_item
-      may alter the original column type.
 
-      We can't simply supply SEND_EOF flag to send_result_set_metadata, because
-      send_result_set_metadata doesn't flush the network buffer.
-    */
-    rc= result->send_result_set_metadata(item_list, Protocol::SEND_NUM_ROWS);
+  /* Commit or rollback metadata in the client-server protocol. */
+
+  if (!rc)
+  {
     thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
     result->send_eof();
   }
+  else
+  {
+    result->abort_result_set();
+  }
+
   return rc;
 }
 
@@ -370,13 +390,14 @@ bool Select_materialize::send_result_set
   materialized_cursor= new (&table->mem_root)
                        Materialized_cursor(result, table);
 
-  if (! materialized_cursor)
+  if (!materialized_cursor)
   {
     free_tmp_table(table->in_use, table);
     table= 0;
     return TRUE;
   }
-  if (materialized_cursor->fill_item_list(unit->thd, list))
+
+  if (materialized_cursor->send_result_set_metadata(unit->thd, list))
   {
     delete materialized_cursor;
     table= 0;

=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c	2011-03-17 13:52:49 +0000
+++ b/tests/mysql_client_test.c	2011-03-22 10:06:54 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -15694,8 +15694,11 @@ static void test_bug13488()
   check_execute(stmt1, rc);
 
   if (!opt_silent)
-    printf("data is: %s", (f1 == 1 && f2 == 1 && f3 == 2)?"OK":
-           "wrong");
+  {
+    printf("data: f1: %d; f2: %d; f3: %d\n", f1, f2, f3);
+    printf("data is: %s\n",
+           (f1 == 1 && f2 == 1 && f3 == 2) ? "OK" : "wrong");
+  }
   DIE_UNLESS(f1 == 1 && f2 == 1 && f3 == 2);
   rc= mysql_query(mysql, "drop table t1, t2");
   myquery(rc);


Attachment: [text/bzr-bundle] bzr/alexander.nozdrin@oracle.com-20110322100654-942i7q14ipz9y6aj.bundle
Thread
bzr commit into mysql-5.5 branch (alexander.nozdrin:3390) Bug#11763413Alexander Nozdrin22 Mar