mirror of
https://github.com/MariaDB/server.git
synced 2025-06-17 22:23:05 +03:00
MDEV-12696 Crash with LOAD XML and non-updatable VIEW column
This commit is contained in:
@ -123,3 +123,14 @@ col1 col2 col3
|
|||||||
ABC DEF NULL
|
ABC DEF NULL
|
||||||
GHI NULL 123
|
GHI NULL 123
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# MDEV-12696 Crash with LOAD XML and non-updatable VIEW column
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (c1 TEXT);
|
||||||
|
CREATE VIEW v1 AS SELECT CONCAT(c1,'') AS c1, NULL AS c2 FROM t1;
|
||||||
|
LOAD XML INFILE '../../std_data/loaddata/mdev12696.xml' INTO TABLE v1 (c1);
|
||||||
|
ERROR HY000: Invalid column reference (v1.c1) in LOAD DATA
|
||||||
|
LOAD XML INFILE '../../std_data/loaddata/mdev12696.xml' INTO TABLE v1 (c2);
|
||||||
|
ERROR HY000: Invalid column reference (v1.c2) in LOAD DATA
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
9
mysql-test/std_data/loaddata/mdev12696.xml
Normal file
9
mysql-test/std_data/loaddata/mdev12696.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<resultset statement="SELECT 'test' AS c1, NULL AS c2
|
||||||
|
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<row>
|
||||||
|
<field name="c1">test</field>
|
||||||
|
<field name="c2" xsi:nil="true" />
|
||||||
|
</row>
|
||||||
|
</resultset>
|
@ -130,3 +130,16 @@ CREATE TABLE t1 (col1 VARCHAR(3), col2 VARCHAR(3), col3 INTEGER);
|
|||||||
LOAD XML INFILE '../../std_data/bug16171518_2.dat' INTO TABLE t1;
|
LOAD XML INFILE '../../std_data/bug16171518_2.dat' INTO TABLE t1;
|
||||||
SELECT * FROM t1 ORDER BY col1, col2, col3;
|
SELECT * FROM t1 ORDER BY col1, col2, col3;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-12696 Crash with LOAD XML and non-updatable VIEW column
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (c1 TEXT);
|
||||||
|
CREATE VIEW v1 AS SELECT CONCAT(c1,'') AS c1, NULL AS c2 FROM t1;
|
||||||
|
--error ER_LOAD_DATA_INVALID_COLUMN
|
||||||
|
LOAD XML INFILE '../../std_data/loaddata/mdev12696.xml' INTO TABLE v1 (c1);
|
||||||
|
--error ER_LOAD_DATA_INVALID_COLUMN,
|
||||||
|
LOAD XML INFILE '../../std_data/loaddata/mdev12696.xml' INTO TABLE v1 (c2);
|
||||||
|
DROP VIEW v1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
21
sql/item.h
21
sql/item.h
@ -439,6 +439,19 @@ typedef struct replace_equal_field_arg
|
|||||||
struct st_join_table *context_tab;
|
struct st_join_table *context_tab;
|
||||||
} REPLACE_EQUAL_FIELD_ARG;
|
} REPLACE_EQUAL_FIELD_ARG;
|
||||||
|
|
||||||
|
|
||||||
|
class Load_data_out_param
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Load_data_out_param() { }
|
||||||
|
virtual ~Load_data_out_param() { }
|
||||||
|
virtual void load_data_set_null_value(CHARSET_INFO *cs) = 0;
|
||||||
|
virtual void load_data_set_value(const char *str, uint length,
|
||||||
|
CHARSET_INFO *cs) = 0;
|
||||||
|
virtual void load_data_print(THD *thd, String *str) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Settable_routine_parameter
|
class Settable_routine_parameter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1789,6 +1802,14 @@ public:
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual Load_data_out_param *get_load_data_out_param() { return 0; }
|
||||||
|
Load_data_out_param *get_load_data_out_param_or_error()
|
||||||
|
{
|
||||||
|
Load_data_out_param *res= get_load_data_out_param();
|
||||||
|
if (!res)
|
||||||
|
my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), full_name());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
virtual Item_splocal *get_item_splocal() { return 0; }
|
virtual Item_splocal *get_item_splocal() { return 0; }
|
||||||
virtual Rewritable_query_parameter *get_rewritable_query_parameter()
|
virtual Rewritable_query_parameter *get_rewritable_query_parameter()
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
@ -5675,13 +5675,14 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
|
void Item_user_var_as_out_param::load_data_set_null_value(CHARSET_INFO* cs)
|
||||||
{
|
{
|
||||||
::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, 0 /* unsigned_arg */);
|
::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, 0 /* unsigned_arg */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_user_var_as_out_param::set_value(const char *str, uint length,
|
void Item_user_var_as_out_param::load_data_set_value(const char *str,
|
||||||
|
uint length,
|
||||||
CHARSET_INFO* cs)
|
CHARSET_INFO* cs)
|
||||||
{
|
{
|
||||||
::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
|
::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
|
||||||
@ -5717,7 +5718,7 @@ my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_user_var_as_out_param::print_for_load(THD *thd, String *str)
|
void Item_user_var_as_out_param::load_data_print(THD *thd, String *str)
|
||||||
{
|
{
|
||||||
str->append('@');
|
str->append('@');
|
||||||
append_identifier(thd, str, name.str, name.length);
|
append_identifier(thd, str, name.str, name.length);
|
||||||
|
@ -2006,7 +2006,8 @@ public:
|
|||||||
in List<Item> and desire to place this code somewhere near other functions
|
in List<Item> and desire to place this code somewhere near other functions
|
||||||
working with user variables.
|
working with user variables.
|
||||||
*/
|
*/
|
||||||
class Item_user_var_as_out_param :public Item
|
class Item_user_var_as_out_param :public Item,
|
||||||
|
public Load_data_out_param
|
||||||
{
|
{
|
||||||
LEX_STRING name;
|
LEX_STRING name;
|
||||||
user_var_entry *entry;
|
user_var_entry *entry;
|
||||||
@ -2021,9 +2022,10 @@ public:
|
|||||||
my_decimal *val_decimal(my_decimal *decimal_buffer);
|
my_decimal *val_decimal(my_decimal *decimal_buffer);
|
||||||
/* fix_fields() binds variable name with its entry structure */
|
/* fix_fields() binds variable name with its entry structure */
|
||||||
bool fix_fields(THD *thd, Item **ref);
|
bool fix_fields(THD *thd, Item **ref);
|
||||||
void print_for_load(THD *thd, String *str);
|
Load_data_out_param *get_load_data_out_param() { return this; }
|
||||||
void set_null_value(CHARSET_INFO* cs);
|
void load_data_print(THD *thd, String *str);
|
||||||
void set_value(const char *str, uint length, CHARSET_INFO* cs);
|
void load_data_set_null_value(CHARSET_INFO* cs);
|
||||||
|
void load_data_set_value(const char *str, uint length, CHARSET_INFO* cs);
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
|
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_user_var_as_out_param>(thd, mem_root, this); }
|
{ return get_item_copy<Item_user_var_as_out_param>(thd, mem_root, this); }
|
||||||
|
@ -431,7 +431,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
else
|
else
|
||||||
tot_length+= field->field_length;
|
tot_length+= field->field_length;
|
||||||
}
|
}
|
||||||
else if (item->type() == Item::STRING_ITEM)
|
else if (item->get_load_data_out_param())
|
||||||
use_vars= 1;
|
use_vars= 1;
|
||||||
}
|
}
|
||||||
if (use_blobs && !ex->line_term->length() && !field_term->length())
|
if (use_blobs && !ex->line_term->length() && !field_term->length())
|
||||||
@ -814,11 +814,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
|
|||||||
if (item->real_type() == Item::FIELD_ITEM)
|
if (item->real_type() == Item::FIELD_ITEM)
|
||||||
append_identifier(thd, &query_str, item->name, strlen(item->name));
|
append_identifier(thd, &query_str, item->name, strlen(item->name));
|
||||||
else
|
else
|
||||||
{
|
item->get_load_data_out_param()->load_data_print(thd, &query_str);
|
||||||
/* Actually Item_user_var_as_out_param despite claiming STRING_ITEM. */
|
|
||||||
DBUG_ASSERT(item->type() == Item::STRING_ITEM);
|
|
||||||
((Item_user_var_as_out_param *)item)->print_for_load(thd, &query_str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
query_str.append(")");
|
query_str.append(")");
|
||||||
}
|
}
|
||||||
@ -1062,6 +1058,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
uint length;
|
uint length;
|
||||||
uchar *pos;
|
uchar *pos;
|
||||||
Item *real_item;
|
Item *real_item;
|
||||||
|
Load_data_out_param *out_param;
|
||||||
|
|
||||||
if (read_info.read_field())
|
if (read_info.read_field())
|
||||||
break;
|
break;
|
||||||
@ -1105,17 +1102,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
/* Do not auto-update this field. */
|
/* Do not auto-update this field. */
|
||||||
field->set_has_explicit_value();
|
field->set_has_explicit_value();
|
||||||
}
|
}
|
||||||
else if (item->type() == Item::STRING_ITEM)
|
else if ((out_param= item->get_load_data_out_param_or_error()))
|
||||||
{
|
out_param->load_data_set_null_value(read_info.read_charset);
|
||||||
((Item_user_var_as_out_param *)item)->set_null_value(
|
|
||||||
read_info.read_charset);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1129,17 +1119,12 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
field->store((char*) pos, length, read_info.read_charset);
|
field->store((char*) pos, length, read_info.read_charset);
|
||||||
field->set_has_explicit_value();
|
field->set_has_explicit_value();
|
||||||
}
|
}
|
||||||
else if (item->type() == Item::STRING_ITEM)
|
else if ((out_param= item->get_load_data_out_param_or_error()))
|
||||||
{
|
out_param->load_data_set_value((const char *) pos, length,
|
||||||
((Item_user_var_as_out_param *)item)->set_value((char*) pos, length,
|
|
||||||
read_info.read_charset);
|
read_info.read_charset);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (thd->is_error())
|
if (thd->is_error())
|
||||||
read_info.error= 1;
|
read_info.error= 1;
|
||||||
@ -1158,6 +1143,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
break;
|
break;
|
||||||
for (; item ; item= it++)
|
for (; item ; item= it++)
|
||||||
{
|
{
|
||||||
|
Load_data_out_param *out_param;
|
||||||
Item *real_item= item->real_item();
|
Item *real_item= item->real_item();
|
||||||
if (real_item->type() == Item::FIELD_ITEM)
|
if (real_item->type() == Item::FIELD_ITEM)
|
||||||
{
|
{
|
||||||
@ -1183,18 +1169,12 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
ER_THD(thd, ER_WARN_TOO_FEW_RECORDS),
|
ER_THD(thd, ER_WARN_TOO_FEW_RECORDS),
|
||||||
thd->get_stmt_da()->current_row_for_warning());
|
thd->get_stmt_da()->current_row_for_warning());
|
||||||
}
|
}
|
||||||
else if (item->type() == Item::STRING_ITEM)
|
else if ((out_param= item->get_load_data_out_param_or_error()))
|
||||||
{
|
out_param->load_data_set_null_value(read_info.read_charset);
|
||||||
((Item_user_var_as_out_param *)item)->set_null_value(
|
|
||||||
read_info.read_charset);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
my_error(ER_LOAD_DATA_INVALID_COLUMN, MYF(0), item->full_name());
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (thd->killed ||
|
if (thd->killed ||
|
||||||
fill_record_n_invoke_before_triggers(thd, table, set_fields,
|
fill_record_n_invoke_before_triggers(thd, table, set_fields,
|
||||||
@ -1288,6 +1268,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
|
|
||||||
while ((item= it++))
|
while ((item= it++))
|
||||||
{
|
{
|
||||||
|
Load_data_out_param *out_param;
|
||||||
/* If this line is to be skipped we don't want to fill field or var */
|
/* If this line is to be skipped we don't want to fill field or var */
|
||||||
if (skip_lines)
|
if (skip_lines)
|
||||||
continue;
|
continue;
|
||||||
@ -1319,14 +1300,15 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
/* Do not auto-update this field. */
|
/* Do not auto-update this field. */
|
||||||
field->set_has_explicit_value();
|
field->set_has_explicit_value();
|
||||||
}
|
}
|
||||||
|
else if ((out_param= item->get_load_data_out_param_or_error()))
|
||||||
|
out_param->load_data_set_null_value(cs);
|
||||||
else
|
else
|
||||||
((Item_user_var_as_out_param *) item)->set_null_value(cs);
|
DBUG_RETURN(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->type() == Item::FIELD_ITEM)
|
if (item->type() == Item::FIELD_ITEM)
|
||||||
{
|
{
|
||||||
|
|
||||||
Field *field= ((Item_field *)item)->field;
|
Field *field= ((Item_field *)item)->field;
|
||||||
field->set_notnull();
|
field->set_notnull();
|
||||||
if (field == table->next_number_field)
|
if (field == table->next_number_field)
|
||||||
@ -1334,10 +1316,12 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
field->store((char *) tag->value.ptr(), tag->value.length(), cs);
|
field->store((char *) tag->value.ptr(), tag->value.length(), cs);
|
||||||
field->set_has_explicit_value();
|
field->set_has_explicit_value();
|
||||||
}
|
}
|
||||||
else
|
else if ((out_param= item->get_load_data_out_param_or_error()))
|
||||||
((Item_user_var_as_out_param *) item)->set_value(
|
out_param->load_data_set_value((const char *) tag->value.ptr(),
|
||||||
(char *) tag->value.ptr(),
|
|
||||||
tag->value.length(), cs);
|
tag->value.length(), cs);
|
||||||
|
else
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_info.error)
|
if (read_info.error)
|
||||||
@ -1357,6 +1341,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
|
|
||||||
for ( ; item; item= it++)
|
for ( ; item; item= it++)
|
||||||
{
|
{
|
||||||
|
Load_data_out_param *out_param;
|
||||||
if (item->type() == Item::FIELD_ITEM)
|
if (item->type() == Item::FIELD_ITEM)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1371,8 +1356,10 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||||||
ER_THD(thd, ER_WARN_TOO_FEW_RECORDS),
|
ER_THD(thd, ER_WARN_TOO_FEW_RECORDS),
|
||||||
thd->get_stmt_da()->current_row_for_warning());
|
thd->get_stmt_da()->current_row_for_warning());
|
||||||
}
|
}
|
||||||
|
else if ((out_param= item->get_load_data_out_param_or_error()))
|
||||||
|
out_param->load_data_set_null_value(cs);
|
||||||
else
|
else
|
||||||
((Item_user_var_as_out_param *)item)->set_null_value(cs);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user