[Commits] bzr commit into Mariadb 5.2, with Maria 2.0:maria/5.2 branch (igor:2823) Bug#603186

Igor Babaev igor at askmonty.org
Fri Jul 16 02:51:17 EEST 2010


#At lp:maria/5.2 based on revid:igor at askmonty.org-20100713174523-mjvsvvp6ow8dc81x

 2823 Igor Babaev	2010-07-15
      Fixed bug #603186.
      There were two problems that caused wrong results reported with this bug.
      1. In some cases stored(persistent) virtual columns were not marked
      in the write_set and in the vcol_set bitmaps.
      2. If the list of fields in an insert command was empty then the values of
      the stored virtual columns were set to default.
      
      To fix the first problem the function st_table::mark_virtual_columns_for_write
      was modified. Now the function has a parameter that says whether the virtual 
      columns are to be marked for insert or for update.  
      To fix the second problem a special handling of empty insert lists is
      added in the function fill_record().
      modified:
        mysql-test/suite/vcol/r/vcol_misc.result
        mysql-test/suite/vcol/t/vcol_misc.test
        sql/sql_base.cc
        sql/sql_insert.cc
        sql/sql_lex.cc
        sql/sql_lex.h
        sql/sql_table.cc
        sql/table.cc
        sql/table.h

=== modified file 'mysql-test/suite/vcol/r/vcol_misc.result'
--- a/mysql-test/suite/vcol/r/vcol_misc.result	2010-07-13 17:45:23 +0000
+++ b/mysql-test/suite/vcol/r/vcol_misc.result	2010-07-15 23:51:05 +0000
@@ -45,3 +45,20 @@ C
 1
 1
 DROP TABLE t1;
+CREATE TABLE t1(a int, b int DEFAULT 0, v INT AS (b+10) PERSISTENT);
+INSERT INTO t1(a) VALUES (1);
+SELECT b, v FROM t1;
+b	v
+0	10
+DROP TABLE t1;
+CREATE TABLE t1(a int DEFAULT 100, v int AS (a+1) PERSISTENT);
+INSERT INTO t1 () VALUES ();
+CREATE TABLE t2(a int DEFAULT 100 , v int AS (a+1));
+INSERT INTO t2 () VALUES ();
+SELECT a, v FROM t1;
+a	v
+100	101
+SELECT a, v FROM t2;
+a	v
+100	101
+DROP TABLE t1,t2;

=== modified file 'mysql-test/suite/vcol/t/vcol_misc.test'
--- a/mysql-test/suite/vcol/t/vcol_misc.test	2010-07-13 17:45:23 +0000
+++ b/mysql-test/suite/vcol/t/vcol_misc.test	2010-07-15 23:51:05 +0000
@@ -43,5 +43,22 @@ SELECT 1 AS C FROM t1 ORDER BY v;
 
 DROP TABLE t1;
 
+#
+# Bug#603186: Insert for a table with stored vurtual columns
+#             
 
+CREATE TABLE t1(a int, b int DEFAULT 0, v INT AS (b+10) PERSISTENT);
+INSERT INTO t1(a) VALUES (1);
+SELECT b, v FROM t1;
 
+DROP TABLE t1;
+
+CREATE TABLE t1(a int DEFAULT 100, v int AS (a+1) PERSISTENT);
+INSERT INTO t1 () VALUES ();
+CREATE TABLE t2(a int DEFAULT 100 , v int AS (a+1));
+INSERT INTO t2 () VALUES ();
+
+SELECT a, v FROM t1;
+SELECT a, v FROM t2;
+
+DROP TABLE t1,t2;

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-06-01 19:52:20 +0000
+++ b/sql/sql_base.cc	2010-07-15 23:51:05 +0000
@@ -8204,6 +8204,8 @@ fill_record(THD * thd, List<Item> &field
     table->auto_increment_field_not_null= FALSE;
     f.rewind();
   }
+  else if (thd->lex->unit.insert_table_with_stored_vcol)
+    tbl_list.push_back(thd->lex->unit.insert_table_with_stored_vcol);
   while ((fld= f++))
   {
     if (!(field= fld->filed_for_view_update()))

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2010-06-01 19:52:20 +0000
+++ b/sql/sql_insert.cc	2010-07-15 23:51:05 +0000
@@ -273,7 +273,7 @@ static int check_insert_fields(THD *thd,
   }
   /* Mark virtual columns used in the insert statement */
   if (table->vfield)
-    table->mark_virtual_columns_for_write();
+    table->mark_virtual_columns_for_write(TRUE);
   // For the values we need select_priv
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
@@ -1267,7 +1267,6 @@ bool mysql_prepare_insert(THD *thd, TABL
   if (mysql_prepare_insert_check_table(thd, table_list, fields, select_insert))
     DBUG_RETURN(TRUE);
 
-
   /* Prepare the fields in the statement. */
   if (values)
   {
@@ -1320,6 +1319,18 @@ bool mysql_prepare_insert(THD *thd, TABL
   if (!table)
     table= table_list->table;
 
+  if (!fields.elements && table->vfield)
+  {
+    for (Field **vfield_ptr= table->vfield; *vfield_ptr; vfield_ptr++)
+    {
+      if ((*vfield_ptr)->stored_in_db)
+      {
+        thd->lex->unit.insert_table_with_stored_vcol= table;
+        break;
+      }
+    }
+  }
+
   if (!select_insert)
   {
     Item *fake_conds= 0;

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2010-06-01 19:52:20 +0000
+++ b/sql/sql_lex.cc	2010-07-15 23:51:05 +0000
@@ -1590,6 +1590,7 @@ void st_select_lex_unit::init_query()
   item_list.empty();
   describe= 0;
   found_rows_for_union= 0;
+  insert_table_with_stored_vcol= 0;
 }
 
 void st_select_lex::init_query()

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2010-06-01 19:52:20 +0000
+++ b/sql/sql_lex.h	2010-07-15 23:51:05 +0000
@@ -532,6 +532,13 @@ public:
   bool describe; /* union exec() called for EXPLAIN */
   Procedure *last_procedure;	 /* Pointer to procedure, if such exists */
 
+  /* 
+    Insert table with stored virtual columns.
+    This is used only in those rare cases 
+    when the list of inserted values is empty.
+  */
+  TABLE *insert_table_with_stored_vcol;
+
   void init_query();
   st_select_lex_unit* master_unit();
   st_select_lex* outer_select();

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-06-05 14:53:36 +0000
+++ b/sql/sql_table.cc	2010-07-15 23:51:05 +0000
@@ -7876,7 +7876,7 @@ copy_data_between_tables(TABLE *from,TAB
 
   /* Tell handler that we have values for all columns in the to table */
   to->use_all_columns();
-  to->mark_virtual_columns_for_write();
+  to->mark_virtual_columns_for_write(TRUE);
   init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
   errpos= 4;
   if (ignore)

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2010-07-13 14:34:14 +0000
+++ b/sql/table.cc	2010-07-15 23:51:05 +0000
@@ -5024,7 +5024,7 @@ void st_table::mark_columns_needed_for_u
     }
   }
   /* Mark all virtual columns needed for update */
-  mark_virtual_columns_for_write();
+  mark_virtual_columns_for_write(FALSE);
   DBUG_VOID_RETURN;
 }
 
@@ -5052,7 +5052,7 @@ void st_table::mark_columns_needed_for_i
   if (found_next_number_field)
     mark_auto_increment_column();
   /* Mark virtual columns for insert */
-  mark_virtual_columns_for_write();
+  mark_virtual_columns_for_write(TRUE);
 }
 
 
@@ -5090,10 +5090,14 @@ bool st_table::mark_virtual_col(Field *f
 
 /* 
   @brief Mark virtual columns for update/insert commands
+    
+  @param insert_fl    <-> virtual columns are marked for insert command 
 
   @details
     The function marks virtual columns used in a update/insert commands
     in the vcol_set bitmap.
+    For an insert command a virtual column is always marked in write_set if
+    it is a stored column.
     If a virtual column is from  write_set it is always marked in vcol_set.
     If a stored virtual column is not from write_set but it is computed
     through columns from write_set it is also marked in vcol_set, and,
@@ -5112,7 +5116,7 @@ bool st_table::mark_virtual_col(Field *f
     be added to read_set either.           
 */
 
-void st_table::mark_virtual_columns_for_write(void)
+void st_table::mark_virtual_columns_for_write(bool insert_fl)
 {
   Field **vfield_ptr, *tmp_vfield;
   bool bitmap_updated= FALSE;
@@ -5124,16 +5128,21 @@ void st_table::mark_virtual_columns_for_
       bitmap_updated= mark_virtual_col(tmp_vfield);
     else if (tmp_vfield->stored_in_db)
     {
-      MY_BITMAP *save_read_set;
-      Item *vcol_item= tmp_vfield->vcol_info->expr_item;
-      DBUG_ASSERT(vcol_item);
-      bitmap_clear_all(&tmp_set);
-      save_read_set= read_set;
-      read_set= &tmp_set;
-      vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
-      read_set= save_read_set;
-      bitmap_intersect(&tmp_set, write_set);
-      if (!bitmap_is_clear_all(&tmp_set))
+      bool mark_fl= insert_fl;
+      if (!mark_fl)
+      {
+        MY_BITMAP *save_read_set;
+        Item *vcol_item= tmp_vfield->vcol_info->expr_item;
+        DBUG_ASSERT(vcol_item);
+        bitmap_clear_all(&tmp_set);
+        save_read_set= read_set;
+        read_set= &tmp_set;
+        vcol_item->walk(&Item::register_field_in_read_map, 1, (uchar *) 0);
+        read_set= save_read_set;
+        bitmap_intersect(&tmp_set, write_set);
+        mark_fl= !bitmap_is_clear_all(&tmp_set);
+      }
+      if (mark_fl)
       {
         bitmap_set_bit(write_set, tmp_vfield->field_index);
         mark_virtual_col(tmp_vfield);

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-06-03 09:28:54 +0000
+++ b/sql/table.h	2010-07-15 23:51:05 +0000
@@ -886,7 +886,7 @@ struct st_table {
   void mark_columns_needed_for_delete(void);
   void mark_columns_needed_for_insert(void);
   bool mark_virtual_col(Field *field);
-  void mark_virtual_columns_for_write(void);
+  void mark_virtual_columns_for_write(bool insert_fl);
   inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
                                  MY_BITMAP *write_set_arg)
   {



More information about the commits mailing list