1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00

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:
  Update result file.
mysql-test/t/loaddata.test:
  Add a test case form Bug#35469: server crash with
  LOAD DATA INFILE to a VIEW.
sql/share/errmsg.txt:
  Introduce a new error.
sql/sql_load.cc:
  Handle reference-items properly.
mysql-test/std_data/bug35649.data:
  Add a data file for the test case.
This commit is contained in:
unknown
2008-03-28 18:59:13 +03:00
parent 7c156537cc
commit 4ec65151dc
5 changed files with 207 additions and 14 deletions

View File

@@ -233,9 +233,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
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,TABLE_LIST *table_list,
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, TABLE_LIST *table_list,
{
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, TABLE_LIST *table_list,
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, TABLE_LIST *table_list,
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, TABLE_LIST *table_list,
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, TABLE_LIST *table_list,
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);
}
}
}