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.
This commit is contained in:
Konstantin Osipov 2009-10-16 18:37:43 +04:00
parent 8441517b52
commit 2ae359db4a
4 changed files with 45 additions and 38 deletions

View File

@ -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 */

View File

@ -1958,15 +1958,19 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
} }
} }
/* /*
Okay, got values for all arguments. Close tables that might be used by Okay, got values for all arguments. Close tables that might be used by
arguments evaluation. If arguments evaluation required prelocking mode, arguments evaluation. If arguments evaluation required prelocking mode,
we'll leave it here. we'll leave it here.
*/ */
if (!thd->in_sub_stmt) if (!thd->in_sub_stmt)
{ {
thd->lex->unit.cleanup(); thd->lex->unit.cleanup();
close_thread_tables(thd);
thd_proc_info(thd, "closing tables");
close_thread_tables(thd);
thd_proc_info(thd, 0);
thd->rollback_item_tree_changes(); thd->rollback_item_tree_changes();
} }

View File

@ -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,
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)
{ {
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)
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)
{ {
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)
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)
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)
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)
{ {

View File

@ -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:
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;