3391 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
3390 Georgi Kodinov 2011-03-22 [merge]
merge mysql-5.1->mysql-5.5
modified:
plugin/fulltext/plugin_example.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 11:48:56 +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 11:48:56 +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 11:48:56 +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 11:48:56 +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);
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-5.5 branch (alexander.nozdrin:3390 to 3391) Bug#11763413 | Alexander Nozdrin | 22 Mar |