List:Commits« Previous MessageNext Message »
From:Dmitry Shulga Date:September 24 2012 2:55pm
Subject:bzr push into mysql-trunk branch (Dmitry.Shulga:4212 to 4214)
View as plain text  
 4214 Dmitry Shulga	2012-09-24
      Fixed bug in handling of default values of table fields inside BEFORE-trigger.

    modified:
      sql/field.cc
      sql/field.h
      sql/partition_info.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_executor.cc
      sql/sql_insert.cc
      sql/sql_load.cc
      sql/sql_union.cc
      sql/sql_update.cc
 4213 Dmitry Shulga	2012-09-24
      Fixed bug in multi-update.

    modified:
      mysql-test/r/wl6030.result
      mysql-test/t/wl6030.test
      sql/sql_update.cc
 4212 Alexander Nozdrin	2012-09-21
      Polish wl6030.test.

    modified:
      mysql-test/r/wl6030.result
      mysql-test/t/wl6030.test
=== modified file 'mysql-test/r/wl6030.result'
--- a/mysql-test/r/wl6030.result	2012-09-21 14:30:00 +0000
+++ b/mysql-test/r/wl6030.result	2012-09-24 14:53:23 +0000
@@ -145,8 +145,6 @@ INSERT INTO t1 VALUES (1, 2, 3), (10, 20
 CREATE TABLE t3(a INT, b INT);
 INSERT INTO t3 VALUES (10, -10);
 UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
-Warnings:
-Warning	1048	Column 'a' cannot be null
 
 SELECT * FROM t1;
 a	b	c
@@ -158,8 +156,24 @@ SELECT * FROM t3;
 a	b
 -20	-10
 
-DROP TABLE t3;
 DROP TRIGGER t1_bu;
+DROP TABLE t3;
+DELETE FROM t1;
+CREATE TABLE t3(a INT NOT NULL, b INT);
+CREATE TRIGGER t3_bu BEFORE UPDATE ON t3 FOR EACH ROW SET NEW.a = 999;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+INSERT INTO t3 VALUES (10, -10);
+UPDATE t1, t3 SET t1.a = -20, t3.a = NULL WHERE t1.a = t3.a AND t3.a = 10;
+SELECT * FROM t1;
+a	b	c
+1	2	3
+-20	20	30
+100	200	300
+SELECT * FROM t3;
+a	b
+999	-10
+DROP TRIGGER t3_bu;
+DROP TABLE t3;
 
 #   - Test 2.1: SET to NULL.
 CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW SET NEW.a = NULL;
@@ -494,8 +508,6 @@ INSERT INTO t1(a, b, c) VALUES (1, 2, 3)
 CREATE TABLE t3(a INT, b INT);
 INSERT INTO t3 VALUES (10, -10);
 UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
-Warnings:
-Warning	1048	Column 'a' cannot be null
 
 SELECT * FROM t1;
 a	b	c	a_new_is_null	a_old_is_null	b_new_is_null	b_old_is_null

=== modified file 'mysql-test/t/wl6030.test'
--- a/mysql-test/t/wl6030.test	2012-09-21 14:30:00 +0000
+++ b/mysql-test/t/wl6030.test	2012-09-24 14:53:23 +0000
@@ -136,7 +136,6 @@ INSERT INTO t1 VALUES (1, 2, 3), (10, 20
 CREATE TABLE t3(a INT, b INT);
 INSERT INTO t3 VALUES (10, -10);
 
-# FIXME: there should be no warnings here.
 UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
 
 --echo
@@ -145,8 +144,21 @@ SELECT * FROM t1;
 SELECT * FROM t3;
 --echo
 
-DROP TABLE t3;
 DROP TRIGGER t1_bu;
+DROP TABLE t3;
+DELETE FROM t1;
+
+CREATE TABLE t3(a INT NOT NULL, b INT);
+CREATE TRIGGER t3_bu BEFORE UPDATE ON t3 FOR EACH ROW SET NEW.a = 999;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+INSERT INTO t3 VALUES (10, -10);
+
+UPDATE t1, t3 SET t1.a = -20, t3.a = NULL WHERE t1.a = t3.a AND t3.a = 10;
+
+SELECT * FROM t1;
+SELECT * FROM t3;
+DROP TRIGGER t3_bu;
+DROP TABLE t3;
 
 --echo
 --echo #   - Test 2.1: SET to NULL.
@@ -434,7 +446,6 @@ INSERT INTO t1(a, b, c) VALUES (1, 2, 3)
 CREATE TABLE t3(a INT, b INT);
 INSERT INTO t3 VALUES (10, -10);
 
-# FIXME: there should be no warnings here.
 UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
 
 --echo

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2012-08-27 07:05:07 +0000
+++ b/sql/field.cc	2012-09-24 14:54:55 +0000
@@ -1441,11 +1441,18 @@ void Field::set_null(my_ptrdiff_t row_of
   }
   else if (is_tmp_nullable())
   {
-    m_is_tmp_null= true;
-    m_count_cuted_fields_saved= table->in_use->count_cuted_fields;
+    set_tmp_null();
+//    m_is_tmp_null= true;
+//    m_count_cuted_fields_saved= table->in_use->count_cuted_fields;
   }
 }
 
+void Field::set_tmp_null()
+{
+  m_is_tmp_null= true;
+  m_count_cuted_fields_saved= table->in_use->count_cuted_fields;
+}
+
 
 /**
   Set field to value NOT NULL.

=== modified file 'sql/field.h'
--- a/sql/field.h	2012-08-27 07:05:07 +0000
+++ b/sql/field.h	2012-09-24 14:54:55 +0000
@@ -582,6 +582,8 @@ public:
   void set_tmp_nullable(bool is_tmp_nullable)
   { m_is_tmp_nullable= is_tmp_nullable; }
 
+  void set_tmp_null();
+
   /**
     Return temporary NULLability flag.
 

=== modified file 'sql/partition_info.cc'
--- a/sql/partition_info.cc	2012-08-08 06:31:24 +0000
+++ b/sql/partition_info.cc	2012-09-24 14:54:55 +0000
@@ -442,12 +442,12 @@ bool partition_info::set_used_partition(
 
   if (fields.elements || !values.elements)
   {
-    if (fill_record(thd, fields, values, false, &full_part_field_set))
+    if (fill_record(thd, fields, values, false, &full_part_field_set, NULL))
       goto err;
   }
   else
   {
-    if (fill_record(thd, table->field, values, false, &full_part_field_set))
+    if (fill_record(thd, table->field, values, false, &full_part_field_set, NULL))
       goto err;
   }
   DBUG_ASSERT(!table->auto_increment_field_not_null);

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2012-09-13 09:24:15 +0000
+++ b/sql/sql_base.cc	2012-09-24 14:54:55 +0000
@@ -8833,7 +8833,8 @@ err_no_arena:
 
 bool
 fill_record(THD * thd, List<Item> &fields, List<Item> &values,
-            bool ignore_errors, MY_BITMAP *bitmap)
+            bool ignore_errors, MY_BITMAP *bitmap,
+            MY_BITMAP *insert_into_fields_bitmap)
 {
   List_iterator_fast<Item> f(fields),v(values);
   Item *value, *fld;
@@ -8882,6 +8883,8 @@ fill_record(THD * thd, List<Item> &field
       goto err;
     }
     bitmap_set_bit(table->fields_set_during_insert, rfield->field_index);
+    if (insert_into_fields_bitmap)
+      bitmap_set_bit(insert_into_fields_bitmap, rfield->field_index);
   }
   DBUG_RETURN(thd->is_error());
 err:
@@ -8966,17 +8969,55 @@ 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)
+                                     enum trg_event_type event,
+                                     uint bitmap_size)
 {
   if (triggers)
+  {
     triggers->enable_fields_temporary_nullability(thd);
+  }
+
+  MY_BITMAP insert_into_fields_bitmap;
+  bool rc;
+
+  if (thd->lex->sql_command == SQLCOM_INSERT ||
+      thd->lex->sql_command == SQLCOM_INSERT_SELECT)
+  {
+    bitmap_init(&insert_into_fields_bitmap, NULL, bitmap_size, false);
+    rc= fill_record(thd, fields, values, ignore_errors, NULL,
+                    &insert_into_fields_bitmap);
+  }
+  else
+    rc= fill_record(thd, fields, values, ignore_errors, NULL, NULL);
+
+  if (rc)
+  {
+    // Return error status if fill_record() failed.
 
-  bool rc= fill_record(thd, fields, values, ignore_errors, NULL) ||
-           (triggers &&
-            triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, true));
+    if (triggers)
+      triggers->disable_fields_temporary_nullability();
+
+    return true;
+  }
 
   if (triggers)
+  {
+    if (thd->lex->sql_command == SQLCOM_INSERT ||
+        thd->lex->sql_command == SQLCOM_INSERT_SELECT)
+    {
+      TABLE *tbl= triggers->trigger_table;
+
+      for (Field** f= tbl->field; *f; ++f)
+      {
+        if (!bitmap_is_set(&insert_into_fields_bitmap, (*f)->field_index))
+          (*f)->set_tmp_null();
+      }
+    }
+
+    rc= triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, true);
+
     triggers->disable_fields_temporary_nullability();
+  }
 
   if (rc)
     return true;
@@ -9007,7 +9048,7 @@ fill_record_n_invoke_before_triggers(THD
 
 bool
 fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
-            MY_BITMAP *bitmap)
+            MY_BITMAP *bitmap, MY_BITMAP *insert_into_fields_bitmap)
 {
   List_iterator_fast<Item> v(values);
   Item *value;
@@ -9045,6 +9086,8 @@ fill_record(THD *thd, Field **ptr, List<
     */
     if (table->fields_set_during_insert)
       bitmap_set_bit(table->fields_set_during_insert, field->field_index);
+    if (insert_into_fields_bitmap)
+      bitmap_set_bit(insert_into_fields_bitmap, field->field_index);
   }
   DBUG_ASSERT(thd->is_error() || !v++);      // No extra value!
   DBUG_RETURN(thd->is_error());
@@ -9083,17 +9126,57 @@ bool
 fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
                                      List<Item> &values, bool ignore_errors,
                                      Table_triggers_list *triggers,
-                                     enum trg_event_type event)
+                                     enum trg_event_type event,
+                                     uint bitmap_size)
 {
   if (triggers)
+  {
     triggers->enable_fields_temporary_nullability(thd);
+  }
+
+  MY_BITMAP insert_into_fields_bitmap;
+  bool rc;
+  if (thd->lex->sql_command == SQLCOM_INSERT ||
+      thd->lex->sql_command == SQLCOM_INSERT_SELECT)
+  {
+    bitmap_init(&insert_into_fields_bitmap, NULL, bitmap_size, false);
+
+    rc= fill_record(thd, ptr, values, ignore_errors, NULL,
+                    &insert_into_fields_bitmap);
+  }
+  else
+    rc= fill_record(thd, ptr, values, ignore_errors, NULL,
+                    NULL);
 
-  bool rc= fill_record(thd, ptr, values, ignore_errors, NULL) ||
-           (triggers &&
-            triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, true));
+  if (rc)
+  {
+    // Return error status if fill_record() failed.
+
+    if (triggers)
+      triggers->disable_fields_temporary_nullability();
+
+    return true;
+  }
 
   if (triggers)
+  {
+    if (thd->lex->sql_command == SQLCOM_INSERT ||
+        thd->lex->sql_command == SQLCOM_INSERT_SELECT)
+    {
+      TABLE *tbl= triggers->trigger_table;
+
+      for (Field** f= tbl->field; *f; ++f)
+      {
+        if (!bitmap_is_set(&insert_into_fields_bitmap, (*f)->field_index))
+          (*f)->set_tmp_null();
+      }
+    }
+
+    rc= triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, true);
+
     triggers->disable_fields_temporary_nullability();
+  }
+
 
   if (rc)
     return true;

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2012-07-24 07:09:42 +0000
+++ b/sql/sql_base.h	2012-09-24 14:54:55 +0000
@@ -169,12 +169,14 @@ bool fill_record_n_invoke_before_trigger
                                           List<Item> &values,
                                           bool ignore_errors,
                                           Table_triggers_list *triggers,
-                                          enum trg_event_type event);
+                                          enum trg_event_type event,
+                                          uint bitmap_size);
 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);
+                                          enum trg_event_type event,
+                                          uint bitmap_size);
 bool insert_fields(THD *thd, Name_resolution_context *context,
 		   const char *db_name, const char *table_name,
                    List_iterator<Item> *it, bool any_privileges);
@@ -184,9 +186,11 @@ bool setup_fields(THD *thd, Ref_ptr_arra
                   List<Item> &item, enum_mark_columns mark_used_columns,
                   List<Item> *sum_func_list, bool allow_sum_func);
 bool fill_record(THD * thd, List<Item> &fields, List<Item> &values,
-                 bool ignore_errors, MY_BITMAP *bitmap);
+                 bool ignore_errors, MY_BITMAP *bitmap,
+                 MY_BITMAP *insert_into_fields_bitmap);
 bool fill_record(THD *thd, Field **field, List<Item> &values,
-                 bool ignore_errors, MY_BITMAP *bitmap);
+                 bool ignore_errors, MY_BITMAP *bitmap,
+                 MY_BITMAP *insert_into_fields_bitmap);
 
 Field *
 find_field_in_tables(THD *thd, Item_ident *item,

=== modified file 'sql/sql_executor.cc'
--- a/sql/sql_executor.cc	2012-08-03 12:40:53 +0000
+++ b/sql/sql_executor.cc	2012-09-24 14:54:55 +0000
@@ -614,7 +614,7 @@ end_sj_materialize(JOIN *join, JOIN_TAB 
       if (item->is_null())
         DBUG_RETURN(NESTED_LOOP_OK);
     }
-    fill_record(thd, table->field, sjm->table_cols, 1, NULL);
+    fill_record(thd, table->field, sjm->table_cols, 1, NULL, NULL);
     if (thd->is_error())
       DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
     if ((error= table->file->ha_write_row(table->record[0])))

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2012-09-18 01:50:47 +0000
+++ b/sql/sql_insert.cc	2012-09-24 14:54:55 +0000
@@ -1099,7 +1099,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       restore_record(table,s->default_values);	// Get empty record
       if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0,
                                                table->triggers,
-                                               TRG_EVENT_INSERT))
+                                               TRG_EVENT_INSERT,
+                                               table->s->fields))
       {
 	if (values_list.elements != 1 && ! thd->is_error())
 	{
@@ -1161,7 +1162,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))
+                                               TRG_EVENT_INSERT,
+                                               table->s->fields))
       {
 	if (values_list.elements != 1 && ! thd->is_error())
 	{
@@ -1867,7 +1869,7 @@ int write_record(THD *thd, TABLE *table,
                                                  *update->update_values,
                                                  ignore_errors,
                                                  table->triggers,
-                                                 TRG_EVENT_UPDATE))
+                                                 TRG_EVENT_UPDATE, 0))
           goto before_trg_err;
 
         /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
@@ -3793,10 +3795,12 @@ void select_insert::store_values(List<It
   const bool ignore_err= true;
   if (fields->elements)
     fill_record_n_invoke_before_triggers(thd, *fields, values, ignore_err,
-                                         table->triggers, TRG_EVENT_INSERT);
+                                         table->triggers, TRG_EVENT_INSERT,
+                                         table->s->fields);
   else
     fill_record_n_invoke_before_triggers(thd, table->field, values, ignore_err,
-                                         table->triggers, TRG_EVENT_INSERT);
+                                         table->triggers, TRG_EVENT_INSERT,
+                                         table->s->fields);
 
   check_that_all_fields_are_given_values(thd, table_list->table, table_list,
                                           &missed_fields_handler);
@@ -4400,7 +4404,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->triggers, TRG_EVENT_INSERT,
+                                       table->s->fields);
 }
 
 

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2012-09-17 15:26:51 +0000
+++ b/sql/sql_load.cc	2012-09-24 14:54:55 +0000
@@ -886,7 +886,8 @@ read_fixed_length(THD *thd, COPY_INFO &i
         fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
                                              ignore_check_option_errors,
                                              table->triggers,
-                                             TRG_EVENT_INSERT))
+                                             TRG_EVENT_INSERT,
+                                             table->s->fields))
       DBUG_RETURN(1);
 
     switch (table_list->view_check_option(thd,
@@ -1117,7 +1118,8 @@ read_sep_field(THD *thd, COPY_INFO &info
         fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
                                              ignore_check_option_errors,
                                              table->triggers,
-                                             TRG_EVENT_INSERT))
+                                             TRG_EVENT_INSERT,
+                                             table->s->fields))
       DBUG_RETURN(1);
 
     if (!table->triggers)
@@ -1307,7 +1309,8 @@ read_xml_field(THD *thd, COPY_INFO &info
         fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
                                              ignore_check_option_errors,
                                              table->triggers,
-                                             TRG_EVENT_INSERT))
+                                             TRG_EVENT_INSERT,
+                                             table->s->fields))
       DBUG_RETURN(1);
 
     switch (table_list->view_check_option(thd,

=== modified file 'sql/sql_union.cc'
--- a/sql/sql_union.cc	2012-08-03 11:41:36 +0000
+++ b/sql/sql_union.cc	2012-09-24 14:54:55 +0000
@@ -90,7 +90,7 @@ bool select_union::send_data(List<Item> 
     unit->offset_limit_cnt--;
     return 0;
   }
-  fill_record(thd, table->field, values, 1, NULL);
+  fill_record(thd, table->field, values, 1, NULL, NULL);
   if (thd->is_error())
     return 1;
 

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2012-08-08 06:54:02 +0000
+++ b/sql/sql_update.cc	2012-09-24 14:54:55 +0000
@@ -809,7 +809,7 @@ 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))
+                                               TRG_EVENT_UPDATE, 0))
         break; /* purecov: inspected */
 
       found++;
@@ -2086,7 +2086,7 @@ bool multi_update::send_data(List<Item> 
                                                *values_for_table[offset],
                                                false, // ignore_errors
                                                table->triggers,
-                                               TRG_EVENT_UPDATE))
+                                               TRG_EVENT_UPDATE, 0))
 	DBUG_RETURN(1);
 
       /*
@@ -2188,10 +2188,19 @@ bool multi_update::send_data(List<Item> 
         field_num++;
       } while ((tbl= tbl_it++));
 
+      /*
+        Enable temporary nullability for temporary table fields.
+      */
+      for (Field** modified_fields= tmp_table->field + 1 + unupdated_check_opt_tables.elements;
+           *modified_fields; ++modified_fields)
+      {
+        (*modified_fields)->set_tmp_nullable(true);
+      }
+
       /* Store regular updated fields in the row. */
       fill_record(thd,
                   tmp_table->field + 1 + unupdated_check_opt_tables.elements,
-                  *values_for_table[offset], 1, NULL);
+                  *values_for_table[offset], 1, NULL, NULL);
 
       /* Write row, ignoring duplicated updates to a row */
       error= tmp_table->file->ha_write_row(tmp_table->record[0]);

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