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:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user