#At file:///opt/local/work/mysql-6.0-warn_list/
2745 Konstantin Osipov 2008-11-14
A pre-requisite patch for WL#4264 "Backup: Stabilize Service Interface"
Move all warning-related information to Warning_info structure,
to be able to reset and restore this structure.
modified:
libmysqld/emb_qcache.cc
libmysqld/lib_sql.cc
mysql-test/r/query_cache.result
sql/backup/kernel.cc
sql/event_scheduler.cc
sql/field.cc
sql/ha_ndbcluster_binlog.cc
sql/handler.cc
sql/log.cc
sql/log_event.cc
sql/mysqld.cc
sql/protocol.cc
sql/set_var.cc
sql/slave.cc
sql/sp.cc
sql/sp_rcontext.cc
sql/sp_rcontext.h
sql/sql_acl.cc
sql/sql_base.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_error.cc
sql/sql_error.h
sql/sql_insert.cc
sql/sql_load.cc
sql/sql_parse.cc
sql/sql_prepare.cc
sql/sql_select.cc
sql/sql_show.cc
sql/sql_table.cc
sql/sql_update.cc
sql/time.cc
sql/unireg.cc
per-file messages:
libmysqld/emb_qcache.cc
Move total_warn_count and rename to statement_warn_count,
since it is what it really is - the number of warnings
generated by the current statement.
libmysqld/lib_sql.cc
Move total_warn_count and rename to statement_warn_count,
since it is what it really is - the number of warnings
generated by the current statement.
mysql-test/r/query_cache.result
This is Bug#40747. We report two warnings for the same row. Previously
the first warning had wrong row id, this has been fixed by the current
patch. But the bug istelf needs to be fixed separately.
sql/backup/kernel.cc
Use Warning_info methods to work with warnings.
sql/event_scheduler.cc
Use Warning_info getters instead of direct access to THD
to work with warning information.
sql/field.cc
Move thd->row_count to Warning_info::current_row_for_warning,
since it is simply a number used to print in warnings, like,
"Data truncated in row 5".
sql/ha_ndbcluster_binlog.cc
Use Warning_info getters to work with warning information
instead of direct manipulation with THD members.
sql/handler.cc
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of Internal_error_handler::handle_error().
sql/log.cc
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of Internal_error_handler::handle_error().
sql/log_event.cc
Use Warning_info interface to work with warnings.
sql/mysqld.cc
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of Internal_error_handler::handle_error().
sql/protocol.cc
Use Warning_info getters to work with warning information.
sql/set_var.cc
Use Warning_info getters to access warning information.
sql/slave.cc
Use Warning_info interface to access warning list.
sql/sp.cc
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of Internal_error_handler::handle_error().
Use Warning_info methods to work with warnings.
sql/sp_rcontext.cc
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of sp_rcontext::handle_error().
sql/sp_rcontext.h
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of sp_rcontext::handle_error().
sql/sql_acl.cc
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of Internal_error_handler::handle_error().
sql/sql_base.cc
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of Internal_error_handler::handle_error().
Use Warning_info methods to work with warning information.
sql/sql_class.cc
Move all warning-related data (except got_warning, which is a
hack and will be removed in a separate patch), to class Warning_info.
sql/sql_class.h
Introduce class Warning_info - an are that stores all warning-related information.
Make sure that in all cases where we work with warning information
the order of arguments is the same: thd, level, code, message.
In particular, change signature of Internal_error_handler::handle_error().
sql/sql_error.cc
Remove mysql_reset_errors(). It used to reset warnings, actually, not
errors. In any case, now a method of Warning_info is used for that.
In all places where we work with warning properties use the same
order of parameters: thd, level, code, message.
Move bits of push_warning functionality to class Warning_info.
sql/sql_error.h
Update MYSQL_ERROR to not require THD in constructor (it wasn't used).
Remove declaration of mysql_reset_errors().
sql/sql_insert.cc
Use Warning_info method to work with warning-related data.
sql/sql_load.cc
Use Warning_info methods to work with warning-related data.
sql/sql_parse.cc
Use Warning_info method to work with warning-related data.
Remove dead code that would clear total_warn_count, it was obsolete
(warnings are no longer cleared inside stored procedures, and wherever
they are cleared, total_warn_count, which has become statement_warn_count,
is updated).
sql/sql_prepare.cc
Use Warning_info methods to work with warnings.
sql/sql_select.cc
Use Warning_info methods to work with warnings.
Sic: since now we always initialize current_row_for_warning to 1,
it's important to not increment it too early in evaluate_join_record().
It must be incremented only after calling next_select(), so that
if a warning happens there, a correct row number is used.
sql/sql_show.cc
Use Warning_info method to work with warnings.
sql/sql_table.cc
Use Warning_info methods to work with warnings.
sql/sql_update.cc
Use Warning_info methods to work with warnings.
sql/time.cc
Use Warning_info methods to work with warnings.
sql/unireg.cc
Use new signature of Internal_error_handler (thd, level, code, message).
=== modified file 'libmysqld/emb_qcache.cc'
--- a/libmysqld/emb_qcache.cc 2008-07-10 23:45:24 +0000
+++ b/libmysqld/emb_qcache.cc 2008-11-14 20:45:00 +0000
@@ -483,7 +483,8 @@ int emb_load_querycache_result(THD *thd,
*prev_row= NULL;
data->embedded_info->prev_ptr= prev_row;
return_ok:
- net_send_eof(thd, thd->server_status, thd->total_warn_count);
+ net_send_eof(thd, thd->server_status,
+ thd->warning_info.statement_warn_count());
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc 2008-09-04 18:30:34 +0000
+++ b/libmysqld/lib_sql.cc 2008-11-14 20:45:00 +0000
@@ -208,7 +208,7 @@ static my_bool emb_read_prepare_result(M
stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count;
stmt->field_count= 0;
- mysql->warning_count= thd->total_warn_count;
+ mysql->warning_count= thd->warning_info.statement_warn_count();
if (thd->first_data)
{
@@ -797,7 +797,7 @@ MYSQL_DATA *THD::alloc_new_dataset()
static
void
-write_eof_packet(THD *thd, uint server_status, uint total_warn_count)
+write_eof_packet(THD *thd, uint server_status, uint statement_warn_count)
{
if (!thd->mysql) // bootstrap file handling
return;
@@ -814,7 +814,7 @@ write_eof_packet(THD *thd, uint server_s
is cleared between substatements, and mysqltest gets confused
*/
thd->cur_data->embedded_info->warning_count=
- (thd->spcont ? 0 : min(total_warn_count, 65535));
+ (thd->spcont ? 0 : min(statement_warn_count, 65535));
}
@@ -970,7 +970,8 @@ bool Protocol::send_result_set_metadata(
}
if (flags & SEND_EOF)
- write_eof_packet(thd, thd->server_status, thd->total_warn_count);
+ write_eof_packet(thd, thd->server_status,
+ thd->warning_info.statement_warn_count());
DBUG_RETURN(prepare_for_send(list->elements));
err:
@@ -1030,7 +1031,7 @@ bool Protocol_binary::write()
void
net_send_ok(THD *thd,
- uint server_status, uint total_warn_count,
+ uint server_status, uint statement_warn_count,
ha_rows affected_rows, ulonglong id, const char *message)
{
DBUG_ENTER("emb_net_send_ok");
@@ -1047,7 +1048,7 @@ net_send_ok(THD *thd,
strmake(data->embedded_info->info, message,
sizeof(data->embedded_info->info)-1);
- write_eof_packet(thd, server_status, total_warn_count);
+ write_eof_packet(thd, server_status, statement_warn_count);
thd->cur_data= 0;
DBUG_VOID_RETURN;
}
@@ -1062,9 +1063,9 @@ net_send_ok(THD *thd,
*/
void
-net_send_eof(THD *thd, uint server_status, uint total_warn_count)
+net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
{
- write_eof_packet(thd, server_status, total_warn_count);
+ write_eof_packet(thd, server_status, statement_warn_count);
thd->cur_data= 0;
}
=== modified file 'mysql-test/r/query_cache.result'
--- a/mysql-test/r/query_cache.result 2008-10-20 09:16:47 +0000
+++ b/mysql-test/r/query_cache.result 2008-11-14 20:45:00 +0000
@@ -942,19 +942,19 @@ COUNT(*)
0
Warnings:
Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
-Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 0
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid';
COUNT(*)
0
Warnings:
Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1
-Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 0
+Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1
SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid';
COUNT(*)
0
Warnings:
Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
-Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 0
+Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2008-11-06 18:39:27 +0000
+++ b/sql/backup/kernel.cc 2008-11-14 20:45:00 +0000
@@ -490,7 +490,7 @@ int Backup_restore_ctx::prepare(String *
// Prepare error reporting context.
- mysql_reset_errors(m_thd, 0); // Never errors
+ m_thd->warning_info.opt_clear_warning_info(m_thd->query_id); // Never errors
m_thd->no_warnings_for_error= FALSE;
save_errors(); // Never errors
=== modified file 'sql/event_scheduler.cc'
--- a/sql/event_scheduler.cc 2008-10-21 08:51:31 +0000
+++ b/sql/event_scheduler.cc 2008-11-14 20:45:00 +0000
@@ -74,7 +74,7 @@ Event_worker_thread::print_warnings(THD
{
MYSQL_ERROR *err;
DBUG_ENTER("evex_print_warnings");
- if (!thd->warn_list.elements)
+ if (thd->warning_info.is_empty())
DBUG_VOID_RETURN;
char msg_buf[10 * STRING_BUFFER_USUAL_SIZE];
@@ -90,7 +90,7 @@ Event_worker_thread::print_warnings(THD
prefix.append(et->name.str, et->name.length, system_charset_info);
prefix.append("] ", 2);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
while ((err= it++))
{
String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2008-11-06 18:39:27 +0000
+++ b/sql/field.cc 2008-11-14 20:45:00 +0000
@@ -1116,7 +1116,7 @@ int Field_num::check_int(CHARSET_INFO *c
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"integer", tmp.c_ptr(), field_name,
- (ulong) table->in_use->row_count);
+ table->in_use->warning_info.current_row_for_warning());
return 1;
}
/* Test if we have garbage at the end of the given string. */
@@ -2599,7 +2599,7 @@ int Field_new_decimal::store(const char
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", from_as_str.c_ptr(), field_name,
- (ulong) table->in_use->row_count);
+ table->in_use->warning_info.current_row_for_warning());
DBUG_RETURN(err);
}
@@ -2622,7 +2622,7 @@ int Field_new_decimal::store(const char
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", from_as_str.c_ptr(), field_name,
- (ulong) table->in_use->row_count);
+ table->in_use->warning_info.current_row_for_warning());
my_decimal_set_zero(&decimal_value);
break;
@@ -2659,7 +2659,7 @@ int Field_new_decimal::store(double nr)
if (check_overflow(err))
set_value_on_overflow(&decimal_value, decimal_value.sign());
/* Only issue a warning if store_value doesn't issue an warning */
- table->in_use->got_warning= 0;
+ table->in_use->got_warning= FALSE;
}
if (store_value(&decimal_value))
err= 1;
@@ -2681,7 +2681,7 @@ int Field_new_decimal::store(longlong nr
if (check_overflow(err))
set_value_on_overflow(&decimal_value, decimal_value.sign());
/* Only issue a warning if store_value doesn't issue an warning */
- table->in_use->got_warning= 0;
+ table->in_use->got_warning= FALSE;
}
if (store_value(&decimal_value))
err= 1;
@@ -5168,7 +5168,7 @@ bool Field_time::get_date(MYSQL_TIME *lt
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE), field_name,
- thd->row_count);
+ thd->warning_info.current_row_for_warning());
return 1;
}
tmp=(long) sint3korr(ptr);
@@ -6158,6 +6158,7 @@ check_string_copy_error(Field_str *field
{
const char *pos, *end_orig;
char tmp[64], *t;
+ THD *thd= field->table->in_use;
if (!(pos= well_formed_error_pos) &&
!(pos= cannot_convert_error_pos))
@@ -6198,12 +6199,12 @@ check_string_copy_error(Field_str *field
*t++= '.';
}
*t= '\0';
- push_warning_printf(field->table->in_use,
+ push_warning_printf(thd,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", tmp, field->field_name,
- (ulong) field->table->in_use->row_count);
+ thd->warning_info.current_row_for_warning());
return TRUE;
}
@@ -10107,7 +10108,7 @@ Field::set_warning(MYSQL_ERROR::enum_war
{
thd->cuted_fields+= cuted_increment;
push_warning_printf(thd, level, code, ER(code), field_name,
- thd->row_count);
+ thd->warning_info.current_row_for_warning());
return 0;
}
return level >= MYSQL_ERROR::WARN_LEVEL_WARN;
=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc 2008-07-14 12:49:19 +0000
+++ b/sql/ha_ndbcluster_binlog.cc 2008-11-14 20:45:00 +0000
@@ -1899,7 +1899,7 @@ ndb_binlog_thread_handle_schema_event(TH
"my_errno: %d",
schema->db, schema->name, schema->query,
schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
MYSQL_ERROR *err;
while ((err= it++))
sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
@@ -2259,7 +2259,7 @@ ndb_binlog_thread_handle_schema_event_po
"binlog schema event '%s' from node %d. my_errno: %d",
schema->db, schema->name, schema->query,
schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
MYSQL_ERROR *err;
while ((err= it++))
sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
@@ -2438,7 +2438,7 @@ ndb_binlog_thread_handle_schema_event_po
"binlog schema event '%s' from node %d. my_errno: %d",
schema->db, schema->name, schema->query,
schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
MYSQL_ERROR *err;
while ((err= it++))
sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2008-11-06 18:46:03 +0000
+++ b/sql/handler.cc 2008-11-14 20:45:00 +0000
@@ -1862,20 +1862,20 @@ const char *get_canonical_filename(handl
struct Ha_delete_table_error_handler: public Internal_error_handler
{
public:
- virtual bool handle_error(uint sql_errno,
- const char *message,
+ virtual bool handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ uint sql_errno,
+ const char *message);
char buff[MYSQL_ERRMSG_SIZE];
};
bool
Ha_delete_table_error_handler::
-handle_error(uint sql_errno,
- const char *message,
+handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+ uint sql_errno,
+ const char *message)
{
/* Grab the error message */
strmake(buff, message, sizeof(buff)-1);
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2008-11-06 18:39:27 +0000
+++ b/sql/log.cc 2008-11-14 20:45:00 +0000
@@ -83,17 +83,18 @@ public:
virtual ~Silence_log_table_errors() {}
- virtual bool handle_error(uint sql_errno, const char *message,
+ virtual bool handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ uint sql_errno, const char *message);
const char *message() const { return m_message; }
};
bool
-Silence_log_table_errors::handle_error(uint /* sql_errno */,
- const char *message_arg,
- MYSQL_ERROR::enum_warning_level /* level */,
- THD * /* thd */)
+Silence_log_table_errors::
+handle_error(THD * /* thd */,
+ MYSQL_ERROR::enum_warning_level /* level */,
+ uint /* sql_errno */,
+ const char *message_arg)
{
strmake(m_message, message_arg, sizeof(m_message)-1);
return TRUE;
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2008-11-06 18:46:03 +0000
+++ b/sql/log_event.cc 2008-11-14 20:45:00 +0000
@@ -133,7 +133,7 @@ static void inline slave_rows_error_repo
char buff[MAX_SLAVE_ERRMSG], *slider;
const char *buff_end= buff + sizeof(buff);
uint len;
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
MYSQL_ERROR *err;
buff[0]= 0;
@@ -4369,13 +4369,7 @@ int Load_log_event::do_apply_event(NET*
pthread_mutex_lock(&LOCK_thread_count);
thd->query_id = next_query_id();
pthread_mutex_unlock(&LOCK_thread_count);
- /*
- Initing thd->row_count is not necessary in theory as this variable has no
- influence in the case of the slave SQL thread (it is used to generate a
- "data truncated" warning but which is absorbed and never gets to the
- error log); still we init it to avoid a Valgrind message.
- */
- mysql_reset_errors(thd, 0);
+ thd->warning_info.opt_clear_warning_info(thd->query_id);
TABLE_LIST tables;
bzero((char*) &tables,sizeof(tables));
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2008-11-10 09:53:30 +0000
+++ b/sql/mysqld.cc 2008-11-14 20:45:00 +0000
@@ -3022,7 +3022,7 @@ void my_message_sql(uint error, const ch
TODO: There are two exceptions mechanism (THD and sp_rcontext),
this could be improved by having a common stack of handlers.
*/
- if (thd->handle_error(error, str, level))
+ if (thd->handle_error(level, error, str))
DBUG_VOID_RETURN;
if (level == MYSQL_ERROR::WARN_LEVEL_WARN)
@@ -3060,7 +3060,7 @@ void my_message_sql(uint error, const ch
*/
if (!thd->is_fatal_error && thd->spcont &&
! (MyFlags & ME_NO_SP_HANDLER) &&
- thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
+ thd->spcont->handle_error(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error))
{
/*
Do not push any warnings, a handled error must be completely
=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc 2008-10-20 09:16:47 +0000
+++ b/sql/protocol.cc 2008-11-14 20:45:00 +0000
@@ -31,10 +31,10 @@ static const unsigned int PACKET_BUFFER_
/* Declared non-static only because of the embedded library. */
void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
void net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *);
-void net_send_eof(THD *thd, uint server_status, uint total_warn_count);
+void net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
#ifndef EMBEDDED_LIBRARY
static void write_eof_packet(THD *thd, NET *net,
- uint server_status, uint total_warn_count);
+ uint server_status, uint statement_warn_count);
#endif
#ifndef EMBEDDED_LIBRARY
@@ -178,7 +178,7 @@ void net_send_error(THD *thd, uint sql_e
#ifndef EMBEDDED_LIBRARY
void
net_send_ok(THD *thd,
- uint server_status, uint total_warn_count,
+ uint server_status, uint statement_warn_count,
ha_rows affected_rows, ulonglong id, const char *message)
{
NET *net= &thd->net;
@@ -201,12 +201,12 @@ net_send_ok(THD *thd,
(ulong) affected_rows,
(ulong) id,
(uint) (server_status & 0xffff),
- (uint) total_warn_count));
+ (uint) statement_warn_count));
int2store(pos, server_status);
pos+=2;
/* We can only return up to 65535 warnings in two bytes */
- uint tmp= min(total_warn_count, 65535);
+ uint tmp= min(statement_warn_count, 65535);
int2store(pos, tmp);
pos+= 2;
}
@@ -250,7 +250,7 @@ static uchar eof_buff[1]= { (uchar) 254
*/
void
-net_send_eof(THD *thd, uint server_status, uint total_warn_count)
+net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
{
NET *net= &thd->net;
DBUG_ENTER("net_send_eof");
@@ -258,7 +258,7 @@ net_send_eof(THD *thd, uint server_statu
if (net->vio != 0)
{
thd->main_da.can_overwrite_status= TRUE;
- write_eof_packet(thd, net, server_status, total_warn_count);
+ write_eof_packet(thd, net, server_status, statement_warn_count);
(void) net_flush(net);
thd->main_da.can_overwrite_status= FALSE;
DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
@@ -274,7 +274,7 @@ net_send_eof(THD *thd, uint server_statu
static void write_eof_packet(THD *thd, NET *net,
uint server_status,
- uint total_warn_count)
+ uint statement_warn_count)
{
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
@@ -283,7 +283,7 @@ static void write_eof_packet(THD *thd, N
Don't send warn count during SP execution, as the warn_list
is cleared between substatements, and mysqltest gets confused
*/
- uint tmp= min(total_warn_count, 65535);
+ uint tmp= min(statement_warn_count, 65535);
buff[0]= 254;
int2store(buff+1, tmp);
/*
@@ -450,12 +450,12 @@ void net_end_statement(THD *thd)
case Diagnostics_area::DA_EOF:
net_send_eof(thd,
thd->main_da.server_status(),
- thd->main_da.total_warn_count());
+ thd->main_da.statement_warn_count());
break;
case Diagnostics_area::DA_OK:
net_send_ok(thd,
thd->main_da.server_status(),
- thd->main_da.total_warn_count(),
+ thd->main_da.statement_warn_count(),
thd->main_da.affected_rows(),
thd->main_da.last_insert_id(),
thd->main_da.message());
@@ -465,8 +465,7 @@ void net_end_statement(THD *thd)
case Diagnostics_area::DA_EMPTY:
default:
DBUG_ASSERT(0);
- net_send_ok(thd, thd->server_status, thd->total_warn_count,
- 0, 0, NULL);
+ net_send_ok(thd, thd->server_status, 0, 0, 0, NULL);
break;
}
thd->main_da.is_sent= TRUE;
@@ -702,7 +701,8 @@ bool Protocol::send_result_set_metadata(
to show that there is no cursor.
Send no warning information, as it will be sent at statement end.
*/
- write_eof_packet(thd, &thd->net, thd->server_status,
thd->total_warn_count);
+ write_eof_packet(thd, &thd->net, thd->server_status,
+ thd->warning_info.statement_warn_count());
}
DBUG_RETURN(prepare_for_send(list->elements));
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2008-11-07 14:01:59 +0000
+++ b/sql/set_var.cc 2008-11-14 20:45:00 +0000
@@ -3434,17 +3434,14 @@ static int check_pseudo_thread_id(THD *t
static uchar *get_warning_count(THD *thd)
{
- thd->sys_var_tmp.long_value=
- (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
- thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
- thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
+ thd->sys_var_tmp.long_value= thd->warning_info.warn_count();
+
return (uchar*) &thd->sys_var_tmp.long_value;
}
static uchar *get_error_count(THD *thd)
{
- thd->sys_var_tmp.long_value=
- thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
+ thd->sys_var_tmp.long_value= thd->warning_info.error_count();
return (uchar*) &thd->sys_var_tmp.long_value;
}
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2008-11-06 18:39:27 +0000
+++ b/sql/slave.cc 2008-11-14 20:45:00 +0000
@@ -1670,7 +1670,7 @@ static int has_temporary_error(THD *thd)
/*
currently temporary error set in ndbcluster
*/
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
MYSQL_ERROR *err;
while ((err= it++))
{
@@ -2610,7 +2610,7 @@ Slave SQL thread aborted. Can't execute
}
/* Print any warnings issued */
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
MYSQL_ERROR *err;
/*
Added controlled slave thread cancel for replication
=== modified file 'sql/sp.cc'
--- a/sql/sp.cc 2008-07-15 16:29:51 +0000
+++ b/sql/sp.cc 2008-11-14 20:45:00 +0000
@@ -496,15 +496,15 @@ db_find_routine(THD *thd, int type, sp_n
struct Silence_deprecated_warning : public Internal_error_handler
{
public:
- virtual bool handle_error(uint sql_errno, const char *message,
+ virtual bool handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ uint sql_errno, const char *message);
};
bool
-Silence_deprecated_warning::handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+Silence_deprecated_warning::
+handle_error(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint sql_errno, const char *message)
{
if (sql_errno == ER_WARN_DEPRECATED_SYNTAX &&
level == MYSQL_ERROR::WARN_LEVEL_WARN)
@@ -1329,7 +1329,7 @@ sp_exist_routines(THD *thd, TABLE_LIST *
&thd->sp_proc_cache, FALSE) != NULL ||
sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
&thd->sp_func_cache, FALSE) != NULL;
- mysql_reset_errors(thd, TRUE);
+ thd->warning_info.clear_warning_info(thd->query_id);
if (sp_object_found)
{
if (any)
=== modified file 'sql/sp_rcontext.cc'
--- a/sql/sp_rcontext.cc 2008-08-15 17:31:50 +0000
+++ b/sql/sp_rcontext.cc 2008-11-14 20:45:00 +0000
@@ -293,9 +293,8 @@ sp_rcontext::find_handler(THD *thd, uint
FALSE if no handler was found.
*/
bool
-sp_rcontext::handle_error(uint sql_errno,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+sp_rcontext::handle_error(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint sql_errno)
{
MYSQL_ERROR::enum_warning_level elevated_level= level;
=== modified file 'sql/sp_rcontext.h'
--- a/sql/sp_rcontext.h 2008-08-15 17:31:50 +0000
+++ b/sql/sp_rcontext.h 2008-11-14 20:45:00 +0000
@@ -116,9 +116,8 @@ class sp_rcontext : public Sql_alloc
// If there is an error handler for this error, handle it and return TRUE.
bool
- handle_error(uint sql_errno,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ handle_error(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint sql_errno);
// Returns handler type and sets *ip to location if one was found
inline int
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2008-10-20 19:13:22 +0000
+++ b/sql/sql_acl.cc 2008-11-14 20:45:00 +0000
@@ -6144,9 +6144,9 @@ public:
virtual ~Silence_routine_definer_errors()
{}
- virtual bool handle_error(uint sql_errno, const char *message,
+ virtual bool handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ uint sql_errno, const char *message);
bool has_errors() { return is_grave; }
@@ -6155,10 +6155,9 @@ private:
};
bool
-Silence_routine_definer_errors::handle_error(uint sql_errno,
- const char *message,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+Silence_routine_definer_errors::
+handle_error(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint sql_errno, const char *message)
{
if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
{
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_base.cc 2008-11-14 20:45:00 +0000
@@ -45,9 +45,9 @@ public:
virtual ~Prelock_error_handler() {}
- virtual bool handle_error(uint sql_errno, const char *message,
+ virtual bool handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ uint sql_errno, const char *message);
bool safely_trapped_errors();
@@ -58,10 +58,10 @@ private:
bool
-Prelock_error_handler::handle_error(uint sql_errno,
- const char * /* message */,
+Prelock_error_handler::handle_error(THD * /* thd */,
MYSQL_ERROR::enum_warning_level /* level */,
- THD * /* thd */)
+ uint sql_errno,
+ const char * /* message */)
{
if (sql_errno == ER_NO_SUCH_TABLE)
{
@@ -602,7 +602,7 @@ static TABLE_SHARE
DBUG_RETURN(0);
}
/* Table existed in engine. Let's open it */
- mysql_reset_errors(thd, 1); // Clear warnings
+ thd->warning_info.clear_warning_info(thd->query_id);
thd->clear_error(); // Clear error message
DBUG_RETURN(get_table_share(thd, table_list, key, key_length,
db_flags, error));
@@ -3483,7 +3483,7 @@ recover_from_failed_open_table_attempt(T
ha_create_table_from_engine(thd, table->db, table->table_name);
pthread_mutex_unlock(&LOCK_open);
- mysql_reset_errors(thd, 1); // Clear warnings
+ thd->warning_info.clear_warning_info(thd->query_id);
thd->clear_error(); // Clear error message
mdl_release_lock(&thd->mdl_context, table->mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, table->mdl_lock_data);
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2008-11-07 14:04:18 +0000
+++ b/sql/sql_class.cc 2008-11-14 20:45:00 +0000
@@ -304,7 +304,7 @@ int thd_tx_isolation(const THD *thd)
extern "C"
void thd_inc_row_count(THD *thd)
{
- thd->row_count++;
+ thd->warning_info.inc_current_row_for_warning();
}
@@ -407,7 +407,7 @@ Diagnostics_area::reset_diagnostics_area
m_server_status= 0;
m_affected_rows= 0;
m_last_insert_id= 0;
- m_total_warn_count= 0;
+ m_statement_warn_count= 0;
#endif
is_sent= FALSE;
/** Tiny reset in debug mode to see garbage right away */
@@ -436,7 +436,7 @@ Diagnostics_area::set_ok_status(THD *thd
return;
m_server_status= thd->server_status;
- m_total_warn_count= thd->total_warn_count;
+ m_statement_warn_count= thd->warning_info.statement_warn_count();
m_affected_rows= affected_rows_arg;
m_last_insert_id= last_insert_id_arg;
if (message_arg)
@@ -471,7 +471,8 @@ Diagnostics_area::set_eof_status(THD *th
number of warnings, since they are not available to the client
anyway.
*/
- m_total_warn_count= thd->spcont ? 0 : thd->total_warn_count;
+ m_statement_warn_count= (thd->spcont ?
+ 0 : thd->warning_info.statement_warn_count());
m_status= DA_EOF;
DBUG_VOID_RETURN;
@@ -525,6 +526,59 @@ Diagnostics_area::disable_status()
}
+Warning_info::Warning_info(query_id_t warn_id_arg)
+ :m_statement_warn_count(0),
+ m_current_row_for_warning(1),
+ m_warn_id(warn_id_arg)
+{
+ /* Initialize sub structures */
+ init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+ m_warn_list.empty();
+ bzero((char*) m_warn_count, sizeof(m_warn_count));
+}
+
+
+Warning_info::~Warning_info()
+{
+ free_root(&m_warn_root,MYF(0));
+}
+
+
+/**
+ Reset the warning information of this connection.
+*/
+
+void Warning_info::clear_warning_info(query_id_t warn_id_arg)
+{
+ m_warn_id= warn_id_arg;
+ free_root(&m_warn_root, MYF(0));
+ bzero((char*) m_warn_count, sizeof(m_warn_count));
+ m_warn_list.empty();
+ m_statement_warn_count= 0;
+ m_current_row_for_warning= 1; /* Start counting from the first row */
+}
+
+
+/**
+ Add a warning to the list of warnings. Increment the respective
+ counters.
+*/
+
+void Warning_info::push_warning(THD *thd,
+ MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *msg)
+{
+ if (m_warn_list.elements < thd->variables.max_error_count)
+ {
+ MYSQL_ERROR *err;
+ if ((err= new (&m_warn_root) MYSQL_ERROR(&m_warn_root, level, code, msg)))
+ m_warn_list.push_back(err, &m_warn_root);
+ }
+ m_warn_count[(uint) level]++;
+ m_statement_warn_count++;
+}
+
+
THD::THD()
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
/* statement id */ 0),
@@ -538,6 +592,7 @@ THD::THD()
first_successful_insert_id_in_prev_stmt_for_binlog(0),
first_successful_insert_id_in_cur_stmt(0),
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
+ warning_info(0),
global_read_lock(0),
is_fatal_error(0),
transaction_rollback_request(0),
@@ -584,7 +639,8 @@ THD::THD()
hash_clear(&handler_tables_hash);
tmp_table=0;
used_tables=0;
- cuted_fields= sent_row_count= row_count= 0L;
+ cuted_fields= 0L;
+ sent_row_count= 0L;
limit_found_rows= 0;
row_count_func= -1;
statement_id_counter= 0UL;
@@ -603,7 +659,6 @@ THD::THD()
one_shot_set= 0;
file_id = 0;
query_id= 0;
- warn_id= 0;
db_charset= global_system_variables.collation_database;
bzero(ha_data, sizeof(ha_data));
mysys_var=0;
@@ -644,8 +699,6 @@ THD::THD()
init_open_tables_state(this, refresh_version);
init();
- /* Initialize sub structures */
- init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
#if defined(ENABLED_PROFILING)
profiling.set_thd(this);
#endif
@@ -691,13 +744,11 @@ void THD::push_internal_handler(Internal
}
-bool THD::handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level)
+bool THD::handle_error(MYSQL_ERROR::enum_warning_level level,
+ uint sql_errno, const char *message)
{
if (m_internal_handler)
- {
- return m_internal_handler->handle_error(sql_errno, message, level, this);
- }
+ return m_internal_handler->handle_error(this, level, sql_errno, message);
return FALSE; // 'FALSE', as per coding style
}
@@ -791,9 +842,6 @@ void THD::init(void)
TL_WRITE_LOW_PRIORITY :
TL_WRITE);
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
- warn_list.empty();
- bzero((char*) warn_count, sizeof(warn_count));
- total_warn_count= 0;
update_charset();
reset_current_stmt_binlog_row_based();
bzero((char *) &status_var, sizeof(status_var));
@@ -962,7 +1010,6 @@ THD::~THD()
DBUG_PRINT("info", ("freeing security context"));
main_security_ctx.destroy();
safeFree(db);
- free_root(&warn_root,MYF(0));
free_root(&transaction.mem_root,MYF(0));
mysys_var=0; // Safety (shouldn't be needed)
pthread_mutex_destroy(&LOCK_delete);
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2008-11-06 18:39:27 +0000
+++ b/sql/sql_class.h 2008-11-14 20:45:00 +0000
@@ -1133,10 +1133,10 @@ public:
@param thd the calling thread
@return true if the error is handled
*/
- virtual bool handle_error(uint sql_errno,
- const char *message,
+ virtual bool handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd) = 0;
+ uint sql_errno,
+ const char *message) = 0;
};
@@ -1203,10 +1203,10 @@ public:
ulonglong last_insert_id() const
{ DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
- uint total_warn_count() const
+ uint statement_warn_count() const
{
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
- return m_total_warn_count;
+ return m_statement_warn_count;
}
Diagnostics_area() { reset_diagnostics_area(); }
@@ -1247,8 +1247,13 @@ private:
to implement LAST_INSERT_ID().
*/
ulonglong m_last_insert_id;
- /** The total number of warnings. */
- uint m_total_warn_count;
+ /**
+ Number of warnings of this last statement. May differ from
+ the number of warnings returned by SHOW WARNINGS e.g. in case
+ the statement doesn't clear the warnings, and doesn't generate
+ them.
+ */
+ uint m_statement_warn_count;
enum_diagnostics_status m_status;
/**
@todo: the following THD members belong here:
@@ -1256,6 +1261,120 @@ private:
*/
};
+
+/**
+ Information about warnings of the current connection.
+*/
+
+class Warning_info
+{
+ /** A memory root to allocate warnings and errors */
+ MEM_ROOT m_warn_root;
+ /** List of warnings of all severities (levels). */
+ List <MYSQL_ERROR> m_warn_list;
+ /** A break down of the number of warnings per severity (level). */
+ uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
+ /**
+ The number of warnings of the current statement. Warning_info
+ life cycle differs from statement life cycle -- it may span
+ multiple statements. In that case we get
+ m_statement_warn_count 0, whereas m_warn_list is not empty.
+ */
+ uint m_statement_warn_count;
+ /*
+ Row counter, to print in errors and warnings. Not increased in
+ create_sort_index(); may differ from examined_row_count.
+ */
+ ulong m_current_row_for_warning;
+ /** Used to optionally clear warnings only once per statement. */
+ query_id_t m_warn_id;
+
+private:
+ Warning_info(const Warning_info &rhs); /* Not implemented */
+ Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
+public:
+
+ Warning_info(query_id_t warn_id_arg);
+ /* Do nothing - used to initialize a backup info */
+ Warning_info() { clear_alloc_root(&m_warn_root); }
+ ~Warning_info();
+
+ /**
+ Reset the warning information. Clear all warnings,
+ the number of warnings, reset current row counter
+ to point to the first row.
+ */
+ void clear_warning_info(query_id_t warn_id_arg);
+ /**
+ Only clear warning info if haven't yet done that already
+ for the current query. Allows to be issued at any time
+ during the query, without risk of clearing some warnings
+ that have been generated by the current statement.
+
+ @todo: This is a sign of sloppy coding. Instead we need to
+ designate one place in a statement life cycle where we call
+ clear_warning_info().
+ */
+ void opt_clear_warning_info(query_id_t query_id)
+ {
+ if (query_id != m_warn_id)
+ clear_warning_info(query_id);
+ }
+
+ /**
+ Reset between two COM_ commands. Warnings are preserved
+ between commands, but statement_warn_count indicates
+ the number of warnings of this particular statement only.
+ */
+ void reset_for_next_command() { m_statement_warn_count= 0; }
+
+ /**
+ Used for @@warning_count system variable, which prints
+ the number of rows returned by SHOW WARNINGS.
+ */
+ ulong warn_count() const
+ {
+ /*
+ This may be higher than warn_list.elements if we have
+ had more warnings than thd->variables.max_error_count.
+ */
+ return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
+ m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
+ m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
+ }
+
+ /**
+ This is for iteration purposes. We return a non-constant reference
+ since List doesn't have constant iterators.
+ */
+ List<MYSQL_ERROR> &warn_list() { return m_warn_list; }
+
+ /**
+ The number of errors, or number of rows returned by SHOW ERRORS,
+ also the value of session variable @@error_count.
+ */
+ ulong error_count() const
+ {
+ return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
+ }
+
+ /** Do we have any errors and warnings that we can *show*? */
+ bool is_empty() const { return m_warn_list.elements == 0; }
+
+ /** Increment the current row counter to point at the next row. */
+ void inc_current_row_for_warning() { m_current_row_for_warning++; }
+ /** Reset the current row counter. Start counting from the first row. */
+ void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
+ /** Return the current counter value. */
+ ulong current_row_for_warning() const { return m_current_row_for_warning; }
+
+ ulong statement_warn_count() const { return m_statement_warn_count; }
+
+ /** Add a new warning to the current list. */
+ void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *msg);
+};
+
/**
Tables that were locked with LOCK TABLES statement.
@@ -1380,7 +1499,6 @@ public:
Query_cache_tls query_cache_tls;
#endif
NET net; // client connection descriptor
- MEM_ROOT warn_root; // For warnings and errors
Protocol *protocol; // Current protocol
Protocol_text protocol_text; // Normal protocol
Protocol_binary protocol_binary; // Binary protocol
@@ -1786,15 +1904,7 @@ public:
table_map used_tables;
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
- /*
- FIXME: this, and some other variables like 'count_cuted_fields'
- maybe should be statement/cursor local, that is, moved to Statement
- class. With current implementation warnings produced in each prepared
- statement/cursor settle here.
- */
- List <MYSQL_ERROR> warn_list;
- uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
- uint total_warn_count;
+ Warning_info warning_info;
Diagnostics_area main_da;
#if defined(ENABLED_PROFILING)
PROFILING profiling;
@@ -1808,7 +1918,7 @@ public:
from table are necessary for this select, to check if it's necessary to
update auto-updatable fields (like auto_increment and timestamp).
*/
- query_id_t query_id, warn_id;
+ query_id_t query_id;
ulong col_access;
#ifdef ERROR_INJECT_SUPPORT
@@ -1817,11 +1927,6 @@ public:
/* Statement id is thread-wide. This counter is used to generate ids */
ulong statement_id_counter;
ulong rand_saved_seed1, rand_saved_seed2;
- /*
- Row counter, mainly for errors and warnings. Not increased in
- create_sort_index(); may differ from examined_row_count.
- */
- ulong row_count;
pthread_t real_id; /* For debugging */
my_thread_id thread_id;
uint tmp_table, global_read_lock;
@@ -2393,8 +2498,8 @@ public:
@param level the error level
@return true if the error is handled
*/
- virtual bool handle_error(uint sql_errno, const char *message,
- MYSQL_ERROR::enum_warning_level level);
+ virtual bool handle_error(MYSQL_ERROR::enum_warning_level level,
+ uint sql_errno, const char *message);
/**
Remove the error handler last pushed.
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2008-10-08 15:37:32 +0000
+++ b/sql/sql_error.cc 2008-11-14 20:45:00 +0000
@@ -44,51 +44,15 @@ This file contains the implementation of
#include "mysql_priv.h"
#include "sp_rcontext.h"
-/*
- Store a new message in an error object
-
- This is used to in group_concat() to register how many warnings we actually
- got after the query has been executed.
-*/
+/* Store a new message in an error object. */
-void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
+void MYSQL_ERROR::set_msg(MEM_ROOT *warn_root, const char *msg_arg)
{
- msg= strdup_root(&thd->warn_root, msg_arg);
+ msg= strdup_root(warn_root, msg_arg);
}
/*
- Reset all warnings for the thread
-
- SYNOPSIS
- mysql_reset_errors()
- thd Thread handle
- force Reset warnings even if it has been done before
-
- IMPLEMENTATION
- Don't reset warnings if this has already been called for this query.
- This may happen if one gets a warning during the parsing stage,
- in which case push_warnings() has already called this function.
-*/
-
-void mysql_reset_errors(THD *thd, bool force)
-{
- DBUG_ENTER("mysql_reset_errors");
- if (thd->query_id != thd->warn_id || force)
- {
- thd->warn_id= thd->query_id;
- free_root(&thd->warn_root,MYF(0));
- bzero((char*) thd->warn_count, sizeof(thd->warn_count));
- if (force)
- thd->total_warn_count= 0;
- thd->warn_list.empty();
- thd->row_count= 1; // by default point to row 1
- }
- DBUG_VOID_RETURN;
-}
-
-
-/*
Push the warning/error to error list if there is still room in the list
SYNOPSIS
@@ -102,7 +66,6 @@ void mysql_reset_errors(THD *thd, bool f
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *msg)
{
- MYSQL_ERROR *err= 0;
DBUG_ENTER("push_warning");
DBUG_PRINT("enter", ("code: %d, msg: %s", code, msg));
@@ -113,8 +76,9 @@ void push_warning(THD *thd, MYSQL_ERROR:
!(thd->options & OPTION_SQL_NOTES))
DBUG_VOID_RETURN;
- if (thd->query_id != thd->warn_id && !thd->spcont)
- mysql_reset_errors(thd, 0);
+ if (! thd->spcont)
+ thd->warning_info.opt_clear_warning_info(thd->query_id);
+
thd->got_warning= 1;
/* Abort if we are using strict mode and we are not using IGNORE */
@@ -137,25 +101,18 @@ void push_warning(THD *thd, MYSQL_ERROR:
level= MYSQL_ERROR::WARN_LEVEL_ERROR;
}
- if (thd->handle_error(code, msg, level))
+ if (thd->handle_error(level, code, msg))
DBUG_VOID_RETURN;
if (thd->spcont &&
- thd->spcont->handle_error(code, level, thd))
+ thd->spcont->handle_error(thd, level, code))
{
DBUG_VOID_RETURN;
}
query_cache_abort(&thd->query_cache_tls);
+ thd->warning_info.push_warning(thd, level, code, msg);
- if (thd->warn_list.elements < thd->variables.max_error_count)
- {
- /* We have to use warn_root, as mem_root is freed after each query */
- if ((err= new (&thd->warn_root) MYSQL_ERROR(thd, code, level, msg)))
- thd->warn_list.push_back(err, &thd->warn_root);
- }
- thd->warn_count[(uint) level]++;
- thd->total_warn_count++;
DBUG_VOID_RETURN;
}
@@ -234,7 +191,7 @@ bool mysqld_show_warnings(THD *thd, ulon
unit->set_limit(sel);
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
while ((err= it++))
{
/* Skip levels that the user is not interested in */
=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h 2008-07-29 22:03:57 +0000
+++ b/sql/sql_error.h 2008-11-14 20:45:00 +0000
@@ -19,27 +19,26 @@ public:
enum enum_warning_level
{ WARN_LEVEL_NOTE, WARN_LEVEL_WARN, WARN_LEVEL_ERROR, WARN_LEVEL_END};
- uint code;
enum_warning_level level;
+ uint code;
char *msg;
-
- MYSQL_ERROR(THD *thd, uint code_arg, enum_warning_level level_arg,
- const char *msg_arg)
- :code(code_arg), level(level_arg)
+
+ MYSQL_ERROR(MEM_ROOT *warn_root,
+ enum_warning_level level_arg, uint code_arg, const char *msg_arg)
+ :level(level_arg), code(code_arg)
{
if (msg_arg)
- set_msg(thd, msg_arg);
+ set_msg(warn_root, msg_arg);
}
private:
- void set_msg(THD *thd, const char *msg_arg);
+ void set_msg(MEM_ROOT *warn_root, const char *msg_arg);
};
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *msg);
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *format, ...);
-void mysql_reset_errors(THD *thd, bool force);
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
extern const LEX_STRING warning_level_names[];
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_insert.cc 2008-11-14 20:45:00 +0000
@@ -835,7 +835,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
error=write_record(thd, table ,&info);
if (error)
break;
- thd->row_count++;
+ thd->warning_info.inc_current_row_for_warning();
}
free_underlaid_joins(thd, &thd->lex->select_lex);
=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc 2008-09-17 16:14:21 +0000
+++ b/sql/sql_load.cc 2008-11-14 20:45:00 +0000
@@ -644,7 +644,8 @@ read_fixed_length(THD *thd, COPY_INFO &i
thd->cuted_fields++; /* Not enough fields */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
- ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
+ ER(ER_WARN_TOO_FEW_RECORDS),
+ thd->warning_info.current_row_for_warning());
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
}
@@ -667,7 +668,8 @@ read_fixed_length(THD *thd, COPY_INFO &i
thd->cuted_fields++; /* To long row */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS,
- ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
+ ER(ER_WARN_TOO_MANY_RECORDS),
+ thd->warning_info.current_row_for_warning());
}
if (thd->killed ||
@@ -702,9 +704,10 @@ read_fixed_length(THD *thd, COPY_INFO &i
thd->cuted_fields++; /* To long row */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS,
- ER(ER_WARN_TOO_MANY_RECORDS), thd->row_count);
+ ER(ER_WARN_TOO_MANY_RECORDS),
+ thd->warning_info.current_row_for_warning());
}
- thd->row_count++;
+ thd->warning_info.inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
@@ -768,7 +771,7 @@ read_sep_field(THD *thd, COPY_INFO &info
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
- thd->row_count);
+ thd->warning_info.current_row_for_warning());
DBUG_RETURN(1);
}
field->set_null();
@@ -836,7 +839,7 @@ read_sep_field(THD *thd, COPY_INFO &info
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
- thd->row_count);
+ thd->warning_info.current_row_for_warning());
DBUG_RETURN(1);
}
if (!field->maybe_null() && field->type() ==
FIELD_TYPE_TIMESTAMP)
@@ -850,7 +853,8 @@ read_sep_field(THD *thd, COPY_INFO &info
thd->cuted_fields++;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
- ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
+ ER(ER_WARN_TOO_FEW_RECORDS),
+ thd->warning_info.current_row_for_warning());
}
else if (item->type() == Item::STRING_ITEM)
{
@@ -896,11 +900,11 @@ read_sep_field(THD *thd, COPY_INFO &info
thd->cuted_fields++; /* To long row */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
- thd->row_count);
+ thd->warning_info.current_row_for_warning());
if (thd->killed)
DBUG_RETURN(1);
}
- thd->row_count++;
+ thd->warning_info.inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
@@ -1033,7 +1037,8 @@ read_xml_field(THD *thd, COPY_INFO &info
thd->cuted_fields++;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
- ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
+ ER(ER_WARN_TOO_FEW_RECORDS),
+ thd->warning_info.current_row_for_warning());
}
else
((Item_user_var_as_out_param *)item)->set_null_value(cs);
@@ -1064,7 +1069,7 @@ read_xml_field(THD *thd, COPY_INFO &info
its default value at the beginning of each loop iteration.
*/
thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt;
- thd->row_count++;
+ thd->warning_info.inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_parse.cc 2008-11-14 20:45:00 +0000
@@ -1412,7 +1412,7 @@ bool dispatch_command(enum enum_server_c
0,0,0,0,
thd->query,thd->query_length,
thd->variables.character_set_client,
- thd->row_count);
+ thd->warning_info.current_row_for_warning());
}
log_slow_statement(thd);
@@ -1851,7 +1851,7 @@ mysql_execute_command(THD *thd)
Don't reset warnings when executing a stored routine.
*/
if ((all_tables || !lex->is_single_level_stmt()) && !thd->spcont)
- mysql_reset_errors(thd, 0);
+ thd->warning_info.opt_clear_warning_info(thd->query_id);
#ifdef HAVE_REPLICATION
if (unlikely(thd->slave_thread))
@@ -4126,12 +4126,6 @@ create_sp_error:
So just execute the statement.
*/
res= sp->execute_procedure(thd, &lex->value_list);
- /*
- If warnings have been cleared, we have to clear total_warn_count
- too, otherwise the clients get confused.
- */
- if (thd->warn_list.is_empty())
- thd->total_warn_count= 0;
thd->variables.select_limit= select_limit;
@@ -4162,7 +4156,7 @@ create_sp_error:
else
sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
&thd->sp_func_cache, FALSE);
- mysql_reset_errors(thd, 0);
+ thd->warning_info.opt_clear_warning_info(thd->query_id);
if (! sp)
{
if (lex->spname->m_db.str)
@@ -4282,7 +4276,7 @@ create_sp_error:
}
sp_result= sp_routine_exists_in_table(thd, type, lex->spname);
- mysql_reset_errors(thd, 0);
+ thd->warning_info.opt_clear_warning_info(thd->query_id);
if (sp_result == SP_OK)
{
char *db= lex->spname->m_db.str;
@@ -5373,7 +5367,7 @@ void mysql_reset_thd_for_next_command(TH
}
thd->clear_error();
thd->main_da.reset_diagnostics_area();
- thd->total_warn_count=0; // Warnings for this query
+ thd->warning_info.reset_for_next_command();
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
thd->thd_marker.emb_on_expr_nest= NULL;
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_prepare.cc 2008-11-14 20:45:00 +0000
@@ -248,7 +248,7 @@ static bool send_prep_stmt(Prepared_stat
int2store(buff+5, columns);
int2store(buff+7, stmt->param_count);
buff[9]= 0; // Guard against a 4.1 client
- tmp= min(stmt->thd->total_warn_count, 65535);
+ tmp= min(stmt->thd->warning_info.statement_warn_count(), 65535);
int2store(buff+10, tmp);
/*
@@ -1839,7 +1839,7 @@ static bool check_prepared_statement(Pre
/* Reset warning count for each query that uses tables */
if ((tables || !lex->is_single_level_stmt()) && !thd->spcont)
- mysql_reset_errors(thd, 0);
+ thd->warning_info.opt_clear_warning_info(thd->query_id);
switch (sql_command) {
case SQLCOM_REPLACE:
@@ -3293,12 +3293,12 @@ Prepared_statement::reprepare()
#endif
/*
Clear possible warnings during reprepare, it has to be completely
- transparent to the user. We use mysql_reset_errors() since
+ transparent to the user. We use mysql_reset_warnings() since
there were no separate query id issued for re-prepare.
Sic: we can't simply silence warnings during reprepare, because if
it's failed, we need to return all the warnings to the user.
*/
- mysql_reset_errors(thd, TRUE);
+ thd->warning_info.clear_warning_info(thd->query_id);
}
return error;
}
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_select.cc 2008-11-14 20:45:00 +0000
@@ -13454,7 +13454,6 @@ do_select(JOIN *join,List<Item> *fields,
so we don't touch it here.
*/
join->examined_rows++;
- join->thd->row_count++;
DBUG_ASSERT(join->examined_rows <= 1);
}
else if (join->send_row_on_empty_set())
@@ -13718,7 +13717,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab
/* Set first_unmatched for the last inner table of this group */
join_tab->last_inner->first_unmatched= join_tab;
}
- join->thd->row_count= 0;
+ join->thd->warning_info.reset_current_row_for_warning();
error= (*join_tab->read_first_record)(join_tab);
rc= evaluate_join_record(join, join_tab, error);
@@ -13962,7 +13961,6 @@ evaluate_join_record(JOIN *join, JOIN_TA
(See above join->return_tab= tab).
*/
join->examined_rows++;
- join->thd->row_count++;
DBUG_PRINT("counts", ("join->examined_rows++: %lu",
(ulong) join->examined_rows));
@@ -13971,6 +13969,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
enum enum_nested_loop_state rc;
/* A match from join_tab is found for the current partial join. */
rc= (*join_tab->next_select)(join, join_tab+1, 0);
+ join->thd->warning_info.inc_current_row_for_warning();
if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
return rc;
if (return_tab < join->return_tab)
@@ -13987,7 +13986,10 @@ evaluate_join_record(JOIN *join, JOIN_TA
return NESTED_LOOP_NO_MORE_ROWS;
}
else
+ {
+ join->thd->warning_info.inc_current_row_for_warning();
join_tab->read_record.file->unlock_row();
+ }
}
else
{
@@ -13996,7 +13998,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
with the beginning coinciding with the current partial join.
*/
join->examined_rows++;
- join->thd->row_count++;
+ join->thd->warning_info.inc_current_row_for_warning();
join_tab->read_record.file->unlock_row();
}
return NESTED_LOOP_OK;
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_show.cc 2008-11-14 20:45:00 +0000
@@ -516,7 +516,7 @@ mysqld_show_create(THD *thd, TABLE_LIST
issue a warning with 'warning' level status in
case of invalid view and last error is ER_VIEW_INVALID
*/
- mysql_reset_errors(thd, true);
+ thd->warning_info.clear_warning_info(thd->query_id);
thd->clear_error();
push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_table.cc 2008-11-14 20:45:00 +0000
@@ -4289,7 +4289,7 @@ static bool mysql_admin_table(THD* thd,
if (!table->table)
{
DBUG_PRINT("admin", ("open table failed"));
- if (!thd->warn_list.elements)
+ if (thd->warning_info.is_empty())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
/* if it was a view will check md5 sum */
@@ -4397,7 +4397,7 @@ send_result:
lex->cleanup_after_one_table_open();
thd->clear_error(); // these errors shouldn't get client
{
- List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
MYSQL_ERROR *err;
while ((err= it++))
{
@@ -4411,7 +4411,7 @@ send_result:
if (protocol->write())
goto err;
}
- mysql_reset_errors(thd, true);
+ thd->warning_info.clear_warning_info(thd->query_id);
}
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -7236,7 +7236,8 @@ err:
the table to be altered isn't empty.
Report error here.
*/
- if (alter_info->error_if_not_empty && thd->row_count)
+ if (alter_info->error_if_not_empty &&
+ thd->warning_info.current_row_for_warning())
{
const char *f_val= 0;
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
@@ -7408,7 +7409,7 @@ copy_data_between_tables(TABLE *from,TAB
errpos= 4;
if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- thd->row_count= 0;
+ thd->warning_info.reset_current_row_for_warning();
restore_record(to, s->default_values); // Create empty record
while (!(error=info.read_record(&info)))
{
@@ -7418,7 +7419,6 @@ copy_data_between_tables(TABLE *from,TAB
error= 1;
break;
}
- thd->row_count++;
/* Return error if source table isn't empty. */
if (error_if_not_empty)
{
@@ -7468,6 +7468,7 @@ copy_data_between_tables(TABLE *from,TAB
}
else
found_count++;
+ thd->warning_info.inc_current_row_for_warning();
}
err:
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2008-10-20 19:13:22 +0000
+++ b/sql/sql_update.cc 2008-11-14 20:45:00 +0000
@@ -727,7 +727,7 @@ int mysql_update(THD *thd,
}
else
table->file->unlock_row();
- thd->row_count++;
+ thd->warning_info.inc_current_row_for_warning();
}
dup_key_found= 0;
/*
=== modified file 'sql/time.cc'
--- a/sql/time.cc 2008-02-13 19:27:12 +0000
+++ b/sql/time.cc 2008-11-14 20:45:00 +0000
@@ -748,7 +748,7 @@ void make_truncated_value_warning(THD *t
cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
type_str, str.c_ptr(), field_name,
- (ulong) thd->row_count);
+ (ulong) thd->warning_info.current_row_for_warning());
else
{
if (time_type > MYSQL_TIMESTAMP_ERROR)
=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc 2008-11-04 08:10:49 +0000
+++ b/sql/unireg.cc 2008-11-14 20:45:00 +0000
@@ -56,10 +56,10 @@ static bool make_empty_rec(THD *thd, int
struct Pack_header_error_handler: public Internal_error_handler
{
- virtual bool handle_error(uint sql_errno,
- const char *message,
+ virtual bool handle_error(THD *thd,
MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ uint sql_errno,
+ const char *message);
bool is_handled;
Pack_header_error_handler() :is_handled(FALSE) {}
};
@@ -67,10 +67,10 @@ struct Pack_header_error_handler: public
bool
Pack_header_error_handler::
-handle_error(uint sql_errno,
- const char * /* message */,
+handle_error(THD * /* thd */,
MYSQL_ERROR::enum_warning_level /* level */,
- THD * /* thd */)
+ uint sql_errno,
+ const char * /* message */)
{
is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
return is_handled;
| Thread |
|---|
| • bzr commit into mysql-6.0-runtime branch (kostja:2745) WL#4264 | Konstantin Osipov | 14 Nov |