Below is the list of changes that have just been committed into a local
6.0 repository of davi. When davi does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2008-03-26 11:01:01-03:00, davi@stripped +13 -0
Bug#15192 "fatal errors" are caught by handlers in stored procedures
The problem is that fatal errors (e.g.: out of memory) were being
caught by stored procedure exception handlers which could cause
the execution to not be stopped (continue handler).
The solution is to not call any exception handler if the error is
fatal and send the fatal error to the client.
include/my_sys.h@stripped, 2008-03-26 11:00:54-03:00, davi@stripped +1 -0
Introduce ME_FATALERROR flag to signal that a error
is fatal.
mysql-test/r/sp-error.result@stripped, 2008-03-26 11:00:54-03:00, davi@stripped +11 -0
Add test case result for Bug#15192
mysql-test/t/sp-error.test@stripped, 2008-03-26 11:00:55-03:00, davi@stripped +21 -0
Add test case for Bug#15192
sql/ha_partition.cc@stripped, 2008-03-26 11:00:55-03:00, davi@stripped +1 -2
Pass flag to signal fatal error instead of calling fatal_error.
sql/mysqld.cc@stripped, 2008-03-26 11:00:55-03:00, davi@stripped +5 -2
Don't call stored procedure error handlers if the error
is fatal. The THD handler is allowed to catch the error
because it might be silencing any kind of error.
sql/opt_sum.cc@stripped, 2008-03-26 11:00:55-03:00, davi@stripped +2 -4
Pass flag to signal fatal error instead of calling fatal_error.
sql/sp_head.cc@stripped, 2008-03-26 11:00:55-03:00, davi@stripped +1 -1
Stop executing stored procedure if a fatal error was signaled.
sql/sql_insert.cc@stripped, 2008-03-26 11:00:55-03:00, davi@stripped +2 -4
Pass flag to signal fatal error instead of calling fatal_error.
sql/sql_parse.cc@stripped, 2008-03-26 11:00:55-03:00, davi@stripped +1 -2
Pass flag to signal fatal error instead of calling fatal_error.
sql/sql_partition.cc@stripped, 2008-03-26 11:00:56-03:00, davi@stripped +2 -6
Pass flag to signal fatal error instead of calling fatal_error.
sql/sql_select.cc@stripped, 2008-03-26 11:00:56-03:00, davi@stripped +1 -2
Pass flag to signal fatal error instead of calling fatal_error.
sql/sql_show.cc@stripped, 2008-03-26 11:00:56-03:00, davi@stripped +1 -2
Pass flag to signal fatal error instead of calling fatal_error.
sql/sql_update.cc@stripped, 2008-03-26 11:00:56-03:00, davi@stripped +10 -8
Pass flag to signal fatal error instead of calling fatal_error.
diff -Nrup a/include/my_sys.h b/include/my_sys.h
--- a/include/my_sys.h 2008-02-22 12:03:41 -03:00
+++ b/include/my_sys.h 2008-03-26 11:00:54 -03:00
@@ -89,6 +89,7 @@ extern int NEAR my_errno; /* Last error
#define ME_COLOUR1 ((1 << ME_HIGHBYTE)) /* Possibly error-colours */
#define ME_COLOUR2 ((2 << ME_HIGHBYTE))
#define ME_COLOUR3 ((3 << ME_HIGHBYTE))
+#define ME_FATALERROR 1024 /* Fatal statement error */
/* Bits in last argument to fn_format */
#define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */
diff -Nrup a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
--- a/mysql-test/r/sp-error.result 2008-02-07 17:13:27 -02:00
+++ b/mysql-test/r/sp-error.result 2008-03-26 11:00:54 -03:00
@@ -1611,3 +1611,14 @@ end loop label1;
end loop;
end|
ERROR 42000: End-label label1 without match
+drop procedure if exists p1;
+set @old_recursion_depth = @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth = 255;
+create procedure p1(a int)
+begin
+declare continue handler for sqlexception select 'exception';
+call p1(a+1);
+end|
+call p1(1);
+set @@max_sp_recursion_depth = @old_recursion_depth;
+drop procedure p1;
diff -Nrup a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
--- a/mysql-test/t/sp-error.test 2008-02-07 17:13:27 -02:00
+++ b/mysql-test/t/sp-error.test 2008-03-26 11:00:55 -03:00
@@ -2372,6 +2372,27 @@ delimiter ;|
#drop procedure p1;
#
+# Bug#15192: "fatal errors" are caught by handlers in stored procedures
+#
+
+--disable_warnings
+drop procedure if exists p1;
+--enable_warnings
+set @old_recursion_depth = @@max_sp_recursion_depth;
+set @@max_sp_recursion_depth = 255;
+delimiter |;
+create procedure p1(a int)
+begin
+ declare continue handler for sqlexception select 'exception';
+ call p1(a+1);
+end|
+delimiter ;|
+--error 0,ER_STACK_OVERRUN_NEED_MORE
+call p1(1);
+set @@max_sp_recursion_depth = @old_recursion_depth;
+drop procedure p1;
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff -Nrup a/sql/ha_partition.cc b/sql/ha_partition.cc
--- a/sql/ha_partition.cc 2008-03-13 06:07:32 -03:00
+++ b/sql/ha_partition.cc 2008-03-26 11:00:55 -03:00
@@ -1768,8 +1768,7 @@ partition_element *ha_partition::find_pa
return part_elem;
}
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error(); // Abort
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
return NULL;
}
diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc 2008-03-19 09:16:03 -03:00
+++ b/sql/mysqld.cc 2008-03-26 11:00:55 -03:00
@@ -2908,6 +2908,9 @@ int my_message_sql(uint error, const cha
*/
if ((thd= current_thd))
{
+ if (MyFlags & ME_FATALERROR)
+ thd->fatal_error();
+
/*
TODO: There are two exceptions mechanism (THD and sp_rcontext),
this could be improved by having a common stack of handlers.
@@ -2948,7 +2951,7 @@ int my_message_sql(uint error, const cha
If a continue handler is found, the error message will be cleared
by the stored procedures code.
*/
- if (thd->spcont &&
+ if (!thd->is_fatal_error && thd->spcont &&
thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
{
/*
@@ -2958,7 +2961,7 @@ int my_message_sql(uint error, const cha
DBUG_RETURN(0);
}
- if (!thd->no_warnings_for_error)
+ if (!thd->no_warnings_for_error && !thd->is_fatal_error)
{
/*
Suppress infinite recursion if there a memory allocation error
diff -Nrup a/sql/opt_sum.cc b/sql/opt_sum.cc
--- a/sql/opt_sum.cc 2007-12-21 17:27:44 -02:00
+++ b/sql/opt_sum.cc 2008-03-26 11:00:55 -03:00
@@ -174,8 +174,7 @@ int opt_sum_query(TABLE_LIST *tables, Li
error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
if(error)
{
- tl->table->file->print_error(error, MYF(0));
- tl->table->in_use->fatal_error();
+ tl->table->file->print_error(error, MYF(ME_FATALERROR));
return error;
}
count*= tl->table->file->stats.records;
@@ -423,8 +422,7 @@ int opt_sum_query(TABLE_LIST *tables, Li
if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE)
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE
/* HA_ERR_LOCK_DEADLOCK or some other error */
- table->file->print_error(error, MYF(0));
- table->in_use->fatal_error();
+ table->file->print_error(error, MYF(ME_FATALERROR));
return(error);
}
removed_tables|= table->map;
diff -Nrup a/sql/sp_head.cc b/sql/sp_head.cc
--- a/sql/sp_head.cc 2008-03-18 07:54:33 -03:00
+++ b/sql/sp_head.cc 2008-03-26 11:00:55 -03:00
@@ -1262,7 +1262,7 @@ sp_head::execute(THD *thd)
continue;
}
}
- } while (!err_status && !thd->killed);
+ } while (!err_status && !thd->killed && !thd->is_fatal_error);
#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc 2008-03-12 07:54:18 -03:00
+++ b/sql/sql_insert.cc 2008-03-26 11:00:55 -03:00
@@ -1901,8 +1901,7 @@ bool delayed_get_table(THD *thd, TABLE_L
pthread_mutex_unlock(&di->mutex);
di->unlock();
delete di;
- my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
- thd->fatal_error();
+ my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error);
goto end_create;
}
@@ -2301,8 +2300,7 @@ pthread_handler_t handle_delayed_insert(
}
if (!(di->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
{
- thd->fatal_error();
- my_error(ER_ILLEGAL_HA, MYF(0), di->table_list.table_name);
+ my_error(ER_ILLEGAL_HA, MYF(ME_FATALERROR), di->table_list.table_name);
goto err;
}
if (di->table->triggers)
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc 2008-03-18 07:54:34 -03:00
+++ b/sql/sql_parse.cc 2008-03-26 11:00:55 -03:00
@@ -5429,8 +5429,7 @@ bool check_stack_overrun(THD *thd, long
{
sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE),
stack_used,thread_stack,margin);
- my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0));
- thd->fatal_error();
+ my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(ME_FATALERROR));
return 1;
}
#ifndef DBUG_OFF
diff -Nrup a/sql/sql_partition.cc b/sql/sql_partition.cc
--- a/sql/sql_partition.cc 2008-02-26 13:45:15 -03:00
+++ b/sql/sql_partition.cc 2008-03-26 11:00:56 -03:00
@@ -2070,8 +2070,7 @@ char *generate_partition_syntax(partitio
default:
DBUG_ASSERT(0);
/* We really shouldn't get here, no use in continuing from here */
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
DBUG_RETURN(NULL);
}
if (part_info->part_expr)
@@ -5106,10 +5105,7 @@ static bool mysql_change_partitions(ALTE
&lpt->deleted, lpt->pack_frm_data,
lpt->pack_frm_len)))
{
- if (error != ER_OUTOFMEMORY)
- file->print_error(error, MYF(0));
- else
- lpt->thd->fatal_error();
+ file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE);
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc 2008-03-12 07:54:19 -03:00
+++ b/sql/sql_select.cc 2008-03-26 11:00:56 -03:00
@@ -17322,8 +17322,7 @@ calc_group_buffer(JOIN *join,ORDER *grou
default:
/* This case should never be choosen */
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- join->thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
}
}
parts++;
diff -Nrup a/sql/sql_show.cc b/sql/sql_show.cc
--- a/sql/sql_show.cc 2008-03-18 07:54:34 -03:00
+++ b/sql/sql_show.cc 2008-03-26 11:00:56 -03:00
@@ -5157,8 +5157,7 @@ static int get_schema_partitions_record(
break;
default:
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- current_thd->fatal_error();
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
DBUG_RETURN(1);
}
table->field[7]->set_notnull();
diff -Nrup a/sql/sql_update.cc b/sql/sql_update.cc
--- a/sql/sql_update.cc 2008-03-12 05:25:24 -03:00
+++ b/sql/sql_update.cc 2008-03-26 11:00:56 -03:00
@@ -653,11 +653,13 @@ int mysql_update(THD *thd,
If (ignore && error is ignorable) we don't have to
do anything; otherwise...
*/
+ myf flags= 0;
+
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
- thd->fatal_error(); /* Other handler errors are fatal */
+ flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error,MYF(flags));
error= 1;
break;
}
@@ -748,9 +750,8 @@ int mysql_update(THD *thd,
*/
{
/* purecov: begin inspected */
- thd->fatal_error();
prepare_record_for_error_message(loc_error, table);
- table->file->print_error(loc_error,MYF(0));
+ table->file->print_error(loc_error,MYF(ME_FATALERROR));
error= 1;
/* purecov: end */
}
@@ -1615,11 +1616,13 @@ bool multi_update::send_data(List<Item>
If (ignore && error == is ignorable) we don't have to
do anything; otherwise...
*/
+ myf flags= 0;
+
if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
- thd->fatal_error(); /* Other handler errors are fatal */
+ flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
- table->file->print_error(error,MYF(0));
+ table->file->print_error(error,MYF(flags));
DBUG_RETURN(1);
}
}
@@ -1897,9 +1900,8 @@ int multi_update::do_updates()
err:
{
- thd->fatal_error();
prepare_record_for_error_message(local_error, table);
- table->file->print_error(local_error,MYF(0));
+ table->file->print_error(local_error,MYF(ME_FATALERROR));
}
err2: