Commit abb5e74d authored by Konstantin Osipov's avatar Konstantin Osipov

Backport of:

----------------------------------------------------------
revno: 2630.13.6
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-3288
timestamp: Fri 2008-07-11 20:22:44 +0400
message:
  WL#3288, step 1: ensure that the SQL layer always closes an open
  cursor (rnd or index read) before closing a handler.


sql/handler.h:
  Assert that the read is closed in handler destructor.
sql/sql_select.cc:
  Remove JOIN::table which was a piece of redundancy. The problem was
  that JOIN::cleanup() works only if JOIN::table is not null,
  but JOIN::cleanup also assigns JOIN::table to NULL. This assignment
  is apparently there for safety, from the times when we had no support for correlated
  subqueries. Indeed, in case of a evaluation of a correlated subquery more than once it led
  to JOIN::cleanup doing nothing, and leaving the rnd or index read open.
      
  In do_select(), make sure we call JOIN::join_free() even in case of an
  error.
sql/sql_select.h:
  Remove JOIN::table, JOIN::all_tables has the same functionality.
parent 3138ee3b
...@@ -1152,7 +1152,7 @@ public: ...@@ -1152,7 +1152,7 @@ public:
virtual ~handler(void) virtual ~handler(void)
{ {
DBUG_ASSERT(locked == FALSE); DBUG_ASSERT(locked == FALSE);
/* TODO: DBUG_ASSERT(inited == NONE); */ DBUG_ASSERT(inited == NONE);
} }
virtual handler *clone(MEM_ROOT *mem_root); virtual handler *clone(MEM_ROOT *mem_root);
/** This is called after create to allow us to set up cached variables */ /** This is called after create to allow us to set up cached variables */
......
...@@ -1966,7 +1966,11 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) ...@@ -1966,7 +1966,11 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!thd->in_sub_stmt) if (!thd->in_sub_stmt)
{ {
thd->lex->unit.cleanup(); thd->lex->unit.cleanup();
thd_proc_info(thd, "closing tables");
close_thread_tables(thd); close_thread_tables(thd);
thd_proc_info(thd, 0);
thd->rollback_item_tree_changes(); thd->rollback_item_tree_changes();
} }
......
...@@ -991,13 +991,13 @@ JOIN::optimize() ...@@ -991,13 +991,13 @@ JOIN::optimize()
} }
if (const_tables && !thd->locked_tables && if (const_tables && !thd->locked_tables &&
!(select_options & SELECT_NO_UNLOCK)) !(select_options & SELECT_NO_UNLOCK))
mysql_unlock_some_tables(thd, table, const_tables); mysql_unlock_some_tables(thd, all_tables, const_tables);
if (!conds && outer_join) if (!conds && outer_join)
{ {
/* Handle the case where we have an OUTER JOIN without a WHERE */ /* Handle the case where we have an OUTER JOIN without a WHERE */
conds=new Item_int((longlong) 1,1); // Always true conds=new Item_int((longlong) 1,1); // Always true
} }
select= make_select(*table, const_table_map, select= make_select(*all_tables, const_table_map,
const_table_map, conds, 1, &error); const_table_map, conds, 1, &error);
if (error) if (error)
{ /* purecov: inspected */ { /* purecov: inspected */
...@@ -2905,7 +2905,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, ...@@ -2905,7 +2905,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
join->join_tab=stat; join->join_tab=stat;
join->map2table=stat_ref; join->map2table=stat_ref;
join->table= join->all_tables=table_vector; join->all_tables= table_vector;
join->const_tables=const_count; join->const_tables=const_count;
join->found_const_table_map=found_const_table_map; join->found_const_table_map=found_const_table_map;
...@@ -5595,7 +5595,7 @@ get_best_combination(JOIN *join) ...@@ -5595,7 +5595,7 @@ get_best_combination(JOIN *join)
{ {
TABLE *form; TABLE *form;
*j= *join->best_positions[tablenr].table; *j= *join->best_positions[tablenr].table;
form=join->table[tablenr]=j->table; form=join->all_tables[tablenr]=j->table;
used_tables|= form->map; used_tables|= form->map;
form->reginfo.join_tab=j; form->reginfo.join_tab=j;
if (!*j->on_expr_ref) if (!*j->on_expr_ref)
...@@ -5867,7 +5867,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) ...@@ -5867,7 +5867,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
DBUG_RETURN(TRUE); /* purecov: inspected */ DBUG_RETURN(TRUE); /* purecov: inspected */
join_tab= parent->join_tab_reexec; join_tab= parent->join_tab_reexec;
table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table; parent->table_reexec[0]= tmp_table;
tables= 1; tables= 1;
const_tables= 0; const_tables= 0;
const_table_map= 0; const_table_map= 0;
...@@ -6899,24 +6899,23 @@ void JOIN::cleanup(bool full) ...@@ -6899,24 +6899,23 @@ void JOIN::cleanup(bool full)
{ {
DBUG_ENTER("JOIN::cleanup"); DBUG_ENTER("JOIN::cleanup");
if (table) if (all_tables)
{ {
JOIN_TAB *tab,*end; JOIN_TAB *tab,*end;
/* /*
Only a sorted table may be cached. This sorted table is always the Only a sorted table may be cached. This sorted table is always the
first non const table in join->table first non const table in join->all_tables
*/ */
if (tables > const_tables) // Test for not-const tables if (tables > const_tables) // Test for not-const tables
{ {
free_io_cache(table[const_tables]); free_io_cache(all_tables[const_tables]);
filesort_free_buffers(table[const_tables],full); filesort_free_buffers(all_tables[const_tables],full);
} }
if (full) if (full)
{ {
for (tab= join_tab, end= tab+tables; tab != end; tab++) for (tab= join_tab, end= tab+tables; tab != end; tab++)
tab->cleanup(); tab->cleanup();
table= 0;
} }
else else
{ {
...@@ -7245,7 +7244,7 @@ static void clear_tables(JOIN *join) ...@@ -7245,7 +7244,7 @@ static void clear_tables(JOIN *join)
are not re-calculated. are not re-calculated.
*/ */
for (uint i=join->const_tables ; i < join->tables ; i++) for (uint i=join->const_tables ; i < join->tables ; i++)
mark_as_null_row(join->table[i]); // All fields are NULL mark_as_null_row(join->all_tables[i]); // All fields are NULL
} }
/***************************************************************************** /*****************************************************************************
...@@ -10995,26 +10994,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -10995,26 +10994,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (error == NESTED_LOOP_NO_MORE_ROWS) if (error == NESTED_LOOP_NO_MORE_ROWS)
error= NESTED_LOOP_OK; error= NESTED_LOOP_OK;
if (error == NESTED_LOOP_OK)
{
/*
Sic: this branch works even if rc != 0, e.g. when
send_data above returns an error.
*/
if (!table) // If sending data to client
{
/*
The following will unlock all cursors if the command wasn't an
update command
*/
join->join_free(); // Unlock all cursors
if (join->result->send_eof())
rc= 1; // Don't send error
}
DBUG_PRINT("info",("%ld records output", (long) join->send_records));
}
else
rc= -1;
if (table) if (table)
{ {
int tmp, new_errno= 0; int tmp, new_errno= 0;
...@@ -11031,6 +11011,29 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) ...@@ -11031,6 +11011,29 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
if (new_errno) if (new_errno)
table->file->print_error(new_errno,MYF(0)); table->file->print_error(new_errno,MYF(0));
} }
else
{
/*
The following will unlock all cursors if the command wasn't an
update command
*/
join->join_free(); // Unlock all cursors
}
if (error == NESTED_LOOP_OK)
{
/*
Sic: this branch works even if rc != 0, e.g. when
send_data above returns an error.
*/
if (!table) // If sending data to client
{
if (join->result->send_eof())
rc= 1; // Don't send error
}
DBUG_PRINT("info",("%ld records output", (long) join->send_records));
}
else
rc= -1;
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (rc) if (rc)
{ {
......
...@@ -280,7 +280,7 @@ public: ...@@ -280,7 +280,7 @@ public:
JOIN_TAB *join_tab,**best_ref; JOIN_TAB *join_tab,**best_ref;
JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs
JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
TABLE **table,**all_tables,*sort_by_table; TABLE **all_tables,*sort_by_table;
uint tables,const_tables; uint tables,const_tables;
uint send_group_parts; uint send_group_parts;
bool sort_and_group,first_record,full_join,group, no_field_update; bool sort_and_group,first_record,full_join,group, no_field_update;
...@@ -427,7 +427,7 @@ public: ...@@ -427,7 +427,7 @@ public:
select_result *result_arg) select_result *result_arg)
{ {
join_tab= join_tab_save= 0; join_tab= join_tab_save= 0;
table= 0; all_tables= 0;
tables= 0; tables= 0;
const_tables= 0; const_tables= 0;
join_list= 0; join_list= 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment