summaryrefslogtreecommitdiff
path: root/sql/sql_cursor.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2011-07-02 22:08:51 +0200
committerSergei Golubchik <sergii@pisem.net>2011-07-02 22:08:51 +0200
commit9809f05199aeb0b67991fac41bd86f38730768dc (patch)
treefa2792ff86d0da014b535d743759810612338042 /sql/sql_cursor.cc
parent0accbd0364e0333e0b119aa9ce93e34ded9df6cb (diff)
parent5a0e7394a5ae0c7b6a1ea35b7ea3a8985325987a (diff)
downloadmariadb-git-9809f05199aeb0b67991fac41bd86f38730768dc.tar.gz
5.5-merge
Diffstat (limited to 'sql/sql_cursor.cc')
-rw-r--r--sql/sql_cursor.cc74
1 files changed, 46 insertions, 28 deletions
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 5bd5f9df680..96a2d50538b 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -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_side_cursor
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);
@@ -111,7 +111,7 @@ int mysql_open_cursor(THD *thd, select_result *result,
MYSQL_QUERY_EXEC_START(thd->query(),
thd->thread_id,
(char *) (thd->db ? thd->db : ""),
- thd->security_ctx->priv_user,
+ &thd->security_ctx->priv_user[0],
(char *) thd->security_ctx->host_or_ip,
2);
rc= mysql_execute_command(thd);
@@ -133,7 +133,13 @@ int mysql_open_cursor(THD *thd, select_result *result,
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_result *result,
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(select_result *result_arg,
/**
- 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(THD *thd,
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,32 +275,29 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused)))
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_with_error(TRUE)))
- is_rnd_inited= 1;
+ rc= !rc && table->file->ha_rnd_init_with_error(TRUE);
+ is_rnd_inited= !rc;
thd->restore_active_arena(this, &backup_arena);
- if (rc == 0)
+
+ /* Commit or rollback metadata in the client-server protocol. */
+
+ if (!rc)
{
- /*
- 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);
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
result->send_eof();
- thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
}
+ else
+ {
+ result->abort_result_set();
+ }
+
return rc;
}
@@ -318,12 +337,10 @@ void Materialized_cursor::fetch(ulong num_rows)
case 0:
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
result->send_eof();
- thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
break;
case HA_ERR_END_OF_FILE:
thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
result->send_eof();
- thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
close();
break;
default:
@@ -375,13 +392,14 @@ bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags)
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;