List:Commits« Previous MessageNext Message »
From:Konstantin Osipov Date:November 14 2008 9:45pm
Subject:bzr commit into mysql-6.0-runtime branch (kostja:2745) WL#4264
View as plain text  
#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#4264Konstantin Osipov14 Nov