MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:March 28 2008 3:59pm
Subject:bk commit into 5.0 tree (anozdrin:1.2601) BUG#35469
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of anozdrin.  When anozdrin does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-03-28 18:59:13+03:00, anozdrin@stripped +5 -0
  Fix for Bug#35469: server crash with LOAD DATA INFILE to a VIEW.
  
  The problem was that LOAD DATA code (sql_load.cc) didn't take into
  account that there may be items, representing references to other
  columns. This is a usual case in views. The crash happened because
  Item_direct_view_ref was casted to Item_user_var_as_out_param,
  which is not a base class.
  
  The fix is to
    1) Handle references properly;
    2) Ensure that an item is treated as a user variable only when
       it is a user variable indeed;
    3) Report an error if LOAD DATA is used to load data into
       non-updatable column.

  mysql-test/r/loaddata.result@stripped, 2008-03-28 18:59:13+03:00, anozdrin@stripped +76 -0
    Update result file.

  mysql-test/std_data/bug35649.data@stripped, 2008-03-28 18:59:13+03:00, anozdrin@stripped +3 -0
    Add a data file for the test case.

  mysql-test/std_data/bug35649.data@stripped, 2008-03-28 18:59:13+03:00, anozdrin@stripped +0 -0

  mysql-test/t/loaddata.test@stripped, 2008-03-28 18:59:13+03:00, anozdrin@stripped +82 -0
    Add a test case form Bug#35469: server crash with
    LOAD DATA INFILE to a VIEW.

  sql/share/errmsg.txt@stripped, 2008-03-28 18:59:13+03:00, anozdrin@stripped +4 -0
    Introduce a new error.

  sql/sql_load.cc@stripped, 2008-03-28 18:59:13+03:00, anozdrin@stripped +42 -14
    Handle reference-items properly.

diff -Nrup a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
--- a/mysql-test/r/loaddata.result	2007-07-06 02:43:11 +04:00
+++ b/mysql-test/r/loaddata.result	2008-03-28 18:59:13 +03:00
@@ -252,3 +252,79 @@ SELECT * FROM t1;
 c1	c2	c3	c4
 10	1970-02-01 01:02:03	1.1e-100	1.1e+100
 DROP TABLE t1;
+
+# --
+# -- Bug#35469: server crash with LOAD DATA INFILE to a VIEW.
+# --
+
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+DROP VIEW IF EXISTS v2;
+DROP VIEW IF EXISTS v3;
+
+CREATE TABLE t1(c1 INT, c2 VARCHAR(255));
+
+CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE VIEW v2 AS SELECT 1 + 2 AS c0, c1, c2 FROM t1;
+CREATE VIEW v3 AS SELECT 1 AS d1, 2 AS d2;
+
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v1
+FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (c1, c2);
+
+SELECT * FROM t1;
+c1	c2
+1	 "string1"
+2	 "string2"
+3	 "string3"
+
+SELECT * FROM v1;
+c1	c2
+1	 "string1"
+2	 "string2"
+3	 "string3"
+
+DELETE FROM t1;
+
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v2
+FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (c1, c2);
+
+SELECT * FROM t1;
+c1	c2
+1	 "string1"
+2	 "string2"
+3	 "string3"
+
+SELECT * FROM v2;
+c0	c1	c2
+3	1	 "string1"
+3	2	 "string2"
+3	3	 "string3"
+
+DELETE FROM t1;
+
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v2
+FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (c0, c2);
+ERROR HY000: Invalid column reference (v2.c0) in LOAD DATA
+
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v3
+FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (d1, d2);
+ERROR HY000: The target table v3 of the LOAD is not updatable
+
+DROP TABLE t1;
+DROP VIEW v1;
+DROP VIEW v2;
+DROP VIEW v3;
+
+# -- End of Bug#35469.
diff -Nrup a/mysql-test/std_data/bug35649.data b/mysql-test/std_data/bug35649.data
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/mysql-test/std_data/bug35649.data	2008-03-28 18:59:13 +03:00
@@ -0,0 +1,3 @@
+"1", "string1"
+"2", "string2"
+"3", "string3"
diff -Nrup a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
--- a/mysql-test/t/loaddata.test	2007-08-28 18:44:30 +04:00
+++ b/mysql-test/t/loaddata.test	2008-03-28 18:59:13 +03:00
@@ -236,4 +236,86 @@ SELECT * FROM t1;
 remove_file $MYSQLTEST_VARDIR/tmp/t1;
 DROP TABLE t1;
 
+###########################################################################
+
+--echo
+--echo # --
+--echo # -- Bug#35469: server crash with LOAD DATA INFILE to a VIEW.
+--echo # --
+
+--echo
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP VIEW IF EXISTS v1;
+DROP VIEW IF EXISTS v2;
+DROP VIEW IF EXISTS v3;
+--enable_warnings
+
+--echo
+CREATE TABLE t1(c1 INT, c2 VARCHAR(255));
+
+--echo
+CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE VIEW v2 AS SELECT 1 + 2 AS c0, c1, c2 FROM t1;
+CREATE VIEW v3 AS SELECT 1 AS d1, 2 AS d2;
+
+--echo
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v1
+  FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (c1, c2);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+SELECT * FROM v1;
+
+--echo
+DELETE FROM t1;
+
+--echo
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v2
+  FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (c1, c2);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+SELECT * FROM v2;
+
+--echo
+DELETE FROM t1;
+
+--echo
+--error ER_LOAD_DATA_INVALID_COLUMN
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v2
+  FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (c0, c2);
+
+--echo
+--error ER_NON_UPDATABLE_TABLE
+LOAD DATA INFILE '../std_data_ln/bug35649.data' INTO TABLE v3
+  FIELDS ESCAPED BY '\\'
+  TERMINATED BY ','
+  ENCLOSED BY '"'
+  LINES TERMINATED BY '\n' (d1, d2);
+
+--echo
+DROP TABLE t1;
+DROP VIEW v1;
+DROP VIEW v2;
+DROP VIEW v3;
+
+--echo
+--echo # -- End of Bug#35469.
+
+###########################################################################
+
 # End of 5.0 tests
diff -Nrup a/sql/share/errmsg.txt b/sql/share/errmsg.txt
--- a/sql/share/errmsg.txt	2007-10-23 15:15:27 +04:00
+++ b/sql/share/errmsg.txt	2008-03-28 18:59:13 +03:00
@@ -5641,3 +5641,7 @@ ER_NAME_BECOMES_EMPTY
         eng "Name '%-.64s' has become ''"
 ER_AMBIGUOUS_FIELD_TERM
 	eng "First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY"
+
+ER_LOAD_DATA_INVALID_COLUMN
+  eng "Invalid column reference (%-.64s) in LOAD DATA"
+
diff -Nrup a/sql/sql_load.cc b/sql/sql_load.cc
--- a/sql/sql_load.cc	2008-03-21 18:23:14 +03:00
+++ b/sql/sql_load.cc	2008-03-28 18:59:13 +03:00
@@ -233,9 +233,11 @@ int mysql_load(THD *thd,sql_exchange *ex
 
   while ((item= it++))
   {
-    if (item->type() == Item::FIELD_ITEM)
+    Item *real_item= item->real_item();
+
+    if (real_item->type() == Item::FIELD_ITEM)
     {
-      Field *field= ((Item_field*)item)->field;
+      Field *field= ((Item_field*)real_item)->field;
       if (field->flags & BLOB_FLAG)
       {
         use_blobs= 1;
@@ -244,7 +246,7 @@ int mysql_load(THD *thd,sql_exchange *ex
       else
         tot_length+= field->field_length;
     }
-    else
+    else if (item->type() == Item::STRING_ITEM)
       use_vars= 1;
   }
   if (use_blobs && !ex->line_term->length() && !field_term->length())
@@ -705,6 +707,7 @@ read_sep_field(THD *thd, COPY_INFO &info
     {
       uint length;
       byte *pos;
+      Item *real_item;
 
       if (read_info.read_field())
 	break;
@@ -716,14 +719,17 @@ read_sep_field(THD *thd, COPY_INFO &info
       pos=read_info.row_start;
       length=(uint) (read_info.row_end-pos);
 
+      real_item= item->real_item();
+
       if (!read_info.enclosed &&
 	  (enclosed_length && length == 4 &&
            !memcmp(pos, STRING_WITH_LEN("NULL"))) ||
 	  (length == 1 && read_info.found_null))
       {
-        if (item->type() == Item::FIELD_ITEM)
+
+        if (real_item->type() == Item::FIELD_ITEM)
         {
-          Field *field= ((Item_field *)item)->field;
+          Field *field= ((Item_field *)real_item)->field;
           if (field->reset())
           {
             my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
@@ -740,25 +746,39 @@ read_sep_field(THD *thd, COPY_INFO &info
                                  ER_WARN_NULL_TO_NOTNULL, 1);
           }
 	}
-        else
+        else if (item->type() == Item::STRING_ITEM)
+        {
           ((Item_user_var_as_out_param *)item)->set_null_value(
                                                   read_info.read_charset);
+        }
+        else
+        {
+          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
+          DBUG_RETURN(1);
+        }
+
 	continue;
       }
 
-      if (item->type() == Item::FIELD_ITEM)
+      if (real_item->type() == Item::FIELD_ITEM)
       {
-
-        Field *field= ((Item_field *)item)->field;
+        Field *field= ((Item_field *)real_item)->field;
         field->set_notnull();
         read_info.row_end[0]=0;			// Safe to change end marker
         if (field == table->next_number_field)
           table->auto_increment_field_not_null= TRUE;
         field->store((char*) pos, length, read_info.read_charset);
       }
-      else
+      else if (item->type() == Item::STRING_ITEM)
+      {
         ((Item_user_var_as_out_param *)item)->set_value((char*) pos, length,
-                                                read_info.read_charset);
+                                                        read_info.read_charset);
+      }
+      else
+      {
+        my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
+        DBUG_RETURN(1);
+      }
     }
     if (read_info.error)
       break;
@@ -774,9 +794,10 @@ read_sep_field(THD *thd, COPY_INFO &info
 	break;
       for (; item ; item= it++)
       {
-        if (item->type() == Item::FIELD_ITEM)
+        Item *real_item= item->real_item();
+        if (real_item->type() == Item::FIELD_ITEM)
         {
-          Field *field= ((Item_field *)item)->field;
+          Field *field= ((Item_field *)real_item)->field;
           if (field->reset())
           {
             my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
@@ -796,9 +817,16 @@ read_sep_field(THD *thd, COPY_INFO &info
                               ER_WARN_TOO_FEW_RECORDS,
                               ER(ER_WARN_TOO_FEW_RECORDS), thd->row_count);
         }
-        else
+        else if (item->type() == Item::STRING_ITEM)
+        {
           ((Item_user_var_as_out_param *)item)->set_null_value(
                                                   read_info.read_charset);
+        }
+        else
+        {
+          my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
+          DBUG_RETURN(1);
+        }
       }
     }
 
Thread
bk commit into 5.0 tree (anozdrin:1.2601) BUG#35469Alexander Nozdrin28 Mar