List:Commits« Previous MessageNext Message »
From:Dmitry Shulga Date:September 25 2012 1:01pm
Subject:bzr push into mysql-trunk branch (Dmitry.Shulga:4215 to 4216)
View as plain text  
 4216 Dmitry Shulga	2012-09-25
      Fixed bug related to duplicate warnings about NOT_NULL column value.

    modified:
      mysql-test/r/wl6030.result
      sql/field.cc
      sql/field.h
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_insert.cc
      sql/sql_insert.h
      sql/sql_load.cc
      sql/sql_update.cc
 4215 Alexander Nozdrin	2012-09-25
      Fix various failures.

    modified:
      mysql-test/r/wl6030.result
      sql/field.cc
      sql/field.h
      sql/sql_base.cc
      sql/sql_trigger.cc
=== modified file 'mysql-test/r/wl6030.result'
--- a/mysql-test/r/wl6030.result	2012-09-25 12:34:49 +0000
+++ b/mysql-test/r/wl6030.result	2012-09-25 13:00:18 +0000
@@ -556,6 +556,7 @@ END IF;
 END|
 INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5), (6);
 Warnings:
+Warning	1048	Column 'b' cannot be null
 Warning	1364	Field 'b' doesn't have a default value
 SELECT * FROM t1;
 a	b

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2012-09-25 12:34:49 +0000
+++ b/sql/field.cc	2012-09-25 13:00:18 +0000
@@ -1377,7 +1377,7 @@ Field::Field(uchar *ptr_arg,uint32 lengt
   @return TYPE_OK if the value is Ok, or corresponding error code from
   the type_conversion_status enum.
 */
-type_conversion_status Field::check_constraints(int warning_no) const
+type_conversion_status Field::check_constraints(bool *got_warning) const
 {
   /*
     Ensure that Field::check_constraints() is called only when temporary
@@ -1386,6 +1386,7 @@ type_conversion_status Field::check_cons
 
   DBUG_ASSERT(!is_tmp_nullable());
 
+  *got_warning= false;
   if (real_maybe_null())
     return TYPE_OK; // If the field is nullable, we're Ok.
 
@@ -1412,7 +1413,7 @@ type_conversion_status Field::check_cons
 
   switch (m_count_cuted_fields_saved) {
   case CHECK_FIELD_WARN:
-    set_warning(Sql_condition::WARN_LEVEL_WARN, warning_no, 1);
+    *got_warning= true;
     /* fall through */
   case CHECK_FIELD_IGNORE:
     return TYPE_OK;

=== modified file 'sql/field.h'
--- a/sql/field.h	2012-09-25 12:34:49 +0000
+++ b/sql/field.h	2012-09-25 13:00:18 +0000
@@ -985,7 +985,7 @@ public:
 
   void set_notnull(my_ptrdiff_t row_offset= 0);
 
-  type_conversion_status check_constraints(int warning_no) const;
+  type_conversion_status check_constraints(bool *got_warning) const;
 
   /**
     Remember the value of THD::count_cuted_fields to handle possible

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2012-09-25 12:34:49 +0000
+++ b/sql/sql_base.cc	2012-09-25 13:00:18 +0000
@@ -8894,6 +8894,18 @@ err:
 }
 
 
+void Not_Null_Warning_Handler::report_field_warning(const Field *field,
+                                                    int warning_no)
+{
+  if (!bitmap_is_set(&fields_keeper, field->field_index))
+  {
+    bitmap_set_bit(&fields_keeper, field->field_index);
+    field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+                       warning_no, 1);
+  }
+}
+
+
 /**
   Check the NOT NULL constraint on all the fields of the current record.
 
@@ -8903,7 +8915,8 @@ err:
 
   @return Error status.
 */
-static bool check_record(THD *thd, List<Item> &fields, bool ignore_errors)
+static bool check_record(THD *thd, List<Item> &fields, bool ignore_errors,
+                         Not_Null_Warning_Handler *not_null_warning_handler)
 {
   List_iterator_fast<Item> f(fields);
   Item *fld;
@@ -8912,12 +8925,28 @@ static bool check_record(THD *thd, List<
   while ((fld= f++))
   {
     field= fld->field_for_view_update();
-    if (field &&
-        field->field->check_constraints(ER_BAD_NULL_ERROR) != TYPE_OK &&
-        !ignore_errors)
+    if (field)
     {
-      my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
-      return true;
+      if (not_null_warning_handler &&
+          not_null_warning_handler->have_been_reported_field_warning(field->field))
+        continue;
+
+      bool got_warning;
+      if (field->field->check_constraints(&got_warning) != TYPE_OK &&
+          !ignore_errors)
+      {
+        my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
+        return true;
+      }
+      if (got_warning)
+      {
+        if (not_null_warning_handler)
+          not_null_warning_handler->report_field_warning(field->field,
+                                                         ER_BAD_NULL_ERROR);
+        else
+          field->field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+                                    ER_BAD_NULL_ERROR, 1);
+      }
     }
   }
   return thd->is_error();
@@ -8932,13 +8961,25 @@ static bool check_record(THD *thd, List<
 
   @return Error status.
 */
-static bool check_record(THD *thd, Field **ptr)
+static bool check_record(THD *thd, Field **ptr,
+                         Not_Null_Warning_Handler *not_null_warning_handler)
 {
   Field *field;
   while ((field = *ptr++) && !thd->is_error())
   {
-    if (field->check_constraints(ER_BAD_NULL_ERROR) != TYPE_OK)
+    if (not_null_warning_handler &&
+        not_null_warning_handler->have_been_reported_field_warning(field))
+      continue;
+    bool got_warning;
+    if (field->check_constraints(&got_warning) != TYPE_OK)
       return true;
+    if (got_warning)
+    {
+      if (not_null_warning_handler)
+        not_null_warning_handler->report_field_warning(field, ER_BAD_NULL_ERROR);
+      else
+        field->set_warning(Sql_condition::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1);
+    }
   }
   return thd->is_error();
 }
@@ -8970,7 +9011,8 @@ fill_record_n_invoke_before_triggers(THD
                                      List<Item> &values, bool ignore_errors,
                                      Table_triggers_list *triggers,
                                      enum trg_event_type event,
-                                     uint bitmap_size)
+                                     uint bitmap_size,
+                                     Not_Null_Warning_Handler *null_warn_hndl)
 {
   if (triggers)
     triggers->enable_fields_temporary_nullability(thd);
@@ -9033,8 +9075,8 @@ fill_record_n_invoke_before_triggers(THD
     return true;
 
   return triggers ?
-         check_record(thd, triggers->trigger_table->field) :
-         check_record(thd, fields, ignore_errors);
+         check_record(thd, triggers->trigger_table->field, null_warn_hndl) :
+         check_record(thd, fields, ignore_errors, null_warn_hndl);
 }
 
 
@@ -9137,7 +9179,8 @@ fill_record_n_invoke_before_triggers(THD
                                      List<Item> &values, bool ignore_errors,
                                      Table_triggers_list *triggers,
                                      enum trg_event_type event,
-                                     uint bitmap_size)
+                                     uint bitmap_size,
+                                     Not_Null_Warning_Handler *null_warn_hndl)
 {
   if (triggers)
     triggers->enable_fields_temporary_nullability(thd);
@@ -9201,7 +9244,7 @@ fill_record_n_invoke_before_triggers(THD
   if (rc)
     return true;
 
-  return check_record(thd, ptr);
+  return check_record(thd, ptr, null_warn_hndl);
 }
 
 

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2012-09-24 14:54:55 +0000
+++ b/sql/sql_base.h	2012-09-25 13:00:18 +0000
@@ -165,18 +165,45 @@ TABLE *find_temporary_table(THD *thd, co
 TABLE *find_temporary_table(THD *thd, const char *table_key,
                             uint table_key_length);
 void close_thread_tables(THD *thd);
+
+class Not_Null_Warning_Handler
+{
+public:
+  explicit Not_Null_Warning_Handler(uint number_of_fields)
+  {
+    // number_of_fields is equal to 0 when select_create class is executed
+    if (number_of_fields)
+      bitmap_init(&fields_keeper,
+                  NULL,
+                  number_of_fields,
+                  false);
+  }
+
+  bool have_been_reported_field_warning(const Field *field)
+  {
+    return bitmap_is_set(&fields_keeper, field->field_index);
+  }
+
+  void report_field_warning(const Field *field, int warning_no);
+
+private:
+  MY_BITMAP fields_keeper;
+};
+
 bool fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
                                           List<Item> &values,
                                           bool ignore_errors,
                                           Table_triggers_list *triggers,
                                           enum trg_event_type event,
-                                          uint bitmap_size);
+                                          uint bitmap_size,
+                                          Not_Null_Warning_Handler *handler);
 bool fill_record_n_invoke_before_triggers(THD *thd, Field **field,
                                           List<Item> &values,
                                           bool ignore_errors,
                                           Table_triggers_list *triggers,
                                           enum trg_event_type event,
-                                          uint bitmap_size);
+                                          uint bitmap_size,
+                                          Not_Null_Warning_Handler *handler);
 bool insert_fields(THD *thd, Name_resolution_context *context,
 		   const char *db_name, const char *table_name,
                    List_iterator<Item> *it, bool any_privileges);

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2012-09-24 14:54:55 +0000
+++ b/sql/sql_insert.cc	2012-09-25 13:00:18 +0000
@@ -1092,6 +1092,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       table_list->prepare_check_option(thd))
     error= 1;
 
+  Not_Null_Warning_Handler not_null_warn_handler(table->s->fields);
   while ((values= its++))
   {
     if (fields.elements || !value_count)
@@ -1100,7 +1101,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0,
                                                table->triggers,
                                                TRG_EVENT_INSERT,
-                                               table->s->fields))
+                                               table->s->fields,
+                                               &not_null_warn_handler))
       {
 	if (values_list.elements != 1 && ! thd->is_error())
 	{
@@ -1163,7 +1165,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0,
                                                table->triggers,
                                                TRG_EVENT_INSERT,
-                                               table->s->fields))
+                                               table->s->fields,
+                                               &not_null_warn_handler))
       {
 	if (values_list.elements != 1 && ! thd->is_error())
 	{
@@ -1197,7 +1200,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
     }
     else
 #endif
-      error= write_record(thd, table, &info, &update);
+      error= write_record(thd, table, &info, &update, &not_null_warn_handler);
     if (error)
       break;
     thd->get_stmt_da()->inc_current_row_for_warning();
@@ -1754,7 +1757,8 @@ static int last_uniq_key(TABLE *table,ui
     non-0 - error
 */
 
-int write_record(THD *thd, TABLE *table, COPY_INFO *info, COPY_INFO *update)
+int write_record(THD *thd, TABLE *table, COPY_INFO *info, COPY_INFO *update,
+                 Not_Null_Warning_Handler *not_null_warn_handler)
 {
   int error, trg_error= 0;
   char *key=0;
@@ -1869,7 +1873,8 @@ int write_record(THD *thd, TABLE *table,
                                                  *update->update_values,
                                                  ignore_errors,
                                                  table->triggers,
-                                                 TRG_EVENT_UPDATE, 0))
+                                                 TRG_EVENT_UPDATE, 0,
+                                                 not_null_warn_handler))
           goto before_trg_err;
 
         /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
@@ -3329,7 +3334,7 @@ bool Delayed_insert::handle_inserts(void
     if (duplicate_handling == DUP_UPDATE)
       table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
     thd.clear_error(); // reset error for binlog
-    if (write_record(&thd, table, &d_info, NULL))
+    if (write_record(&thd, table, &d_info, NULL, NULL))
     {
       d_info.stats.error_count++;               // Ignore errors
       thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status);
@@ -3754,7 +3759,7 @@ bool select_insert::send_data(List<Item>
   // Release latches in case bulk insert takes a long time
   ha_release_temporary_latches(thd);
 
-  error= write_record(thd, table, &info, &update);
+  error= write_record(thd, table, &info, &update, &not_null_warn_handler);
   table->auto_increment_field_not_null= FALSE;
   
   if (!error)
@@ -3796,11 +3801,13 @@ void select_insert::store_values(List<It
   if (fields->elements)
     fill_record_n_invoke_before_triggers(thd, *fields, values, ignore_err,
                                          table->triggers, TRG_EVENT_INSERT,
-                                         table->s->fields);
+                                         table->s->fields,
+                                         &not_null_warn_handler);
   else
     fill_record_n_invoke_before_triggers(thd, table->field, values, ignore_err,
                                          table->triggers, TRG_EVENT_INSERT,
-                                         table->s->fields);
+                                         table->s->fields,
+                                         &not_null_warn_handler);
 
   check_that_all_fields_are_given_values(thd, table_list->table, table_list,
                                           &missed_fields_handler);
@@ -4405,7 +4412,8 @@ void select_create::store_values(List<It
   const bool ignore_err= true;
   fill_record_n_invoke_before_triggers(thd, field, values, ignore_err,
                                        table->triggers, TRG_EVENT_INSERT,
-                                       table->s->fields);
+                                       table->s->fields,
+                                       NULL);
 }
 
 

=== modified file 'sql/sql_insert.h'
--- a/sql/sql_insert.h	2012-09-17 15:26:51 +0000
+++ b/sql/sql_insert.h	2012-09-25 13:00:18 +0000
@@ -18,6 +18,7 @@
 
 #include "sql_class.h"                          /* enum_duplicates */
 #include "sql_list.h"
+#include "sql_base.h"
 
 /* Instead of including sql_lex.h we add this typedef here */
 typedef List<Item> List_item;
@@ -120,6 +121,9 @@ private:
 
   Missed_fields_handler_impl missed_fields_handler;
 
+protected:
+  Not_Null_Warning_Handler not_null_warn_handler;
+
 public:
   ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
   COPY_INFO info;
@@ -190,6 +194,7 @@ public:
      missed_fields_handler(thd, ignore,
                            (table ? table->s->column_bitmap_size : 0),
                            (table ? table->s->fields : 0)),
+     not_null_warn_handler(table ? table->s->fields : 0), // TODO: fix possible bug for select_create
      autoinc_value_of_last_inserted_row(0),
      info(COPY_INFO::INSERT_OPERATION,
           target_columns,
@@ -301,7 +306,8 @@ int check_that_all_fields_are_given_valu
                                            Missed_fields_handler *handler);
 void prepare_triggers_for_insert_stmt(TABLE *table);
 int write_record(THD *thd, TABLE *table,
-                 COPY_INFO *info, COPY_INFO *update);
+                 COPY_INFO *info, COPY_INFO *update,
+                 Not_Null_Warning_Handler *not_null_warn_handler);
 void kill_delayed_threads(void);
 
 #ifdef EMBEDDED_LIBRARY

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2012-09-24 14:54:55 +0000
+++ b/sql/sql_load.cc	2012-09-25 13:00:18 +0000
@@ -887,7 +887,8 @@ read_fixed_length(THD *thd, COPY_INFO &i
                                              ignore_check_option_errors,
                                              table->triggers,
                                              TRG_EVENT_INSERT,
-                                             table->s->fields))
+                                             table->s->fields,
+                                             NULL))
       DBUG_RETURN(1);
 
     switch (table_list->view_check_option(thd,
@@ -899,7 +900,7 @@ read_fixed_length(THD *thd, COPY_INFO &i
       DBUG_RETURN(-1);
     }
 
-    err= write_record(thd, table, &info, NULL);
+    err= write_record(thd, table, &info, NULL, NULL);
     table->auto_increment_field_not_null= FALSE;
     if (err)
       DBUG_RETURN(1);
@@ -1119,7 +1120,8 @@ read_sep_field(THD *thd, COPY_INFO &info
                                              ignore_check_option_errors,
                                              table->triggers,
                                              TRG_EVENT_INSERT,
-                                             table->s->fields))
+                                             table->s->fields,
+                                             NULL))
       DBUG_RETURN(1);
 
     if (!table->triggers)
@@ -1133,8 +1135,12 @@ read_sep_field(THD *thd, COPY_INFO &info
       while ((item= it++))
       {
         real_item= item->real_item();
+        bool got_warning;
         if (real_item->type() == Item::FIELD_ITEM)
-          ((Item_field *) real_item)->field->check_constraints(ER_WARN_NULL_TO_NOTNULL);
+          ((Item_field *) real_item)->field->check_constraints(&got_warning);
+        if (got_warning)
+          ((Item_field *) real_item)->field->set_warning(Sql_condition::WARN_LEVEL_WARN,
+                                                         ER_WARN_NULL_TO_NOTNULL, 1);
       }
     }
 
@@ -1147,7 +1153,7 @@ read_sep_field(THD *thd, COPY_INFO &info
       DBUG_RETURN(-1);
     }
 
-    err= write_record(thd, table, &info, NULL);
+    err= write_record(thd, table, &info, NULL, NULL);
     table->auto_increment_field_not_null= FALSE;
     if (err)
       DBUG_RETURN(1);
@@ -1310,7 +1316,8 @@ read_xml_field(THD *thd, COPY_INFO &info
                                              ignore_check_option_errors,
                                              table->triggers,
                                              TRG_EVENT_INSERT,
-                                             table->s->fields))
+                                             table->s->fields,
+                                             NULL))
       DBUG_RETURN(1);
 
     switch (table_list->view_check_option(thd,
@@ -1322,7 +1329,7 @@ read_xml_field(THD *thd, COPY_INFO &info
       DBUG_RETURN(-1);
     }
     
-    if (write_record(thd, table, &info, NULL))
+    if (write_record(thd, table, &info, NULL, NULL))
       DBUG_RETURN(1);
     
     /*

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2012-09-24 14:54:55 +0000
+++ b/sql/sql_update.cc	2012-09-25 13:00:18 +0000
@@ -809,7 +809,8 @@ int mysql_update(THD *thd,
       store_record(table,record[1]);
       if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
                                                table->triggers,
-                                               TRG_EVENT_UPDATE, 0))
+                                               TRG_EVENT_UPDATE, 0,
+                                               NULL))
         break; /* purecov: inspected */
 
       found++;
@@ -2086,7 +2087,7 @@ bool multi_update::send_data(List<Item> 
                                                *values_for_table[offset],
                                                false, // ignore_errors
                                                table->triggers,
-                                               TRG_EVENT_UPDATE, 0))
+                                               TRG_EVENT_UPDATE, 0, NULL))
 	DBUG_RETURN(1);
 
       /*

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (Dmitry.Shulga:4215 to 4216) Dmitry Shulga26 Sep