mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 18:20:07 +01:00
MDEV-8701 Crash on derived query
MDEV-8938 Server Crash on Update with joins Make unique table check after setup_fields of update because unique table can materialize table and we do not need field resolving after materialization.
This commit is contained in:
parent
df80420865
commit
c88ca2c227
5 changed files with 158 additions and 10 deletions
|
@ -618,3 +618,62 @@ Variable_name Value
|
||||||
Handler_update 5
|
Handler_update 5
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
#
|
||||||
|
# MDEV-8938: Server Crash on Update with joins
|
||||||
|
#
|
||||||
|
CREATE TABLE `t1` (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` varchar(4095) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`name`)
|
||||||
|
);
|
||||||
|
UPDATE `t1` SET value = CONCAT("*.",(SELECT `temptable`.`value` FROM (SELECT * FROM `t1` WHERE `name`="consoleproxy.url.domain") AS `temptable` WHERE `temptable`.`name`="consoleproxy.url.domain")) WHERE `name`="consoleproxy.url.domain";
|
||||||
|
drop table t1;
|
||||||
|
CREATE TABLE `t1` (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` varchar(4095) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`name`)
|
||||||
|
);
|
||||||
|
create table t2 (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` varchar(4095) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`name`)
|
||||||
|
);
|
||||||
|
UPDATE t1
|
||||||
|
SET value = (SELECT value FROM t2 WHERE `name`= t1.name)
|
||||||
|
WHERE value is null ;
|
||||||
|
drop table t1,t2;
|
||||||
|
#
|
||||||
|
#MDEV-8701: Crash on derived query
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
data_exit_entry_id int(11) NOT NULL,
|
||||||
|
data_entry_id int(11) NOT NULL,
|
||||||
|
data_entry_exit_id int(11) NOT NULL,
|
||||||
|
data_exit_entry_quantity double NOT NULL
|
||||||
|
) DEFAULT CHARSET=utf8;
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
data_entry_id int(11) NOT NULL,
|
||||||
|
data_entry_cost double NOT NULL,
|
||||||
|
data_entry_quantity double NOT NULL
|
||||||
|
) DEFAULT CHARSET=utf8;
|
||||||
|
create algorithm=temptable view v1 as SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost
|
||||||
|
FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id;
|
||||||
|
UPDATE t2
|
||||||
|
SET data_entry_cost
|
||||||
|
= ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost)
|
||||||
|
FROM
|
||||||
|
v1 AS query
|
||||||
|
WHERE data_entry_exit_id = t2.data_entry_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
UPDATE t2
|
||||||
|
SET data_entry_cost
|
||||||
|
= ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost)
|
||||||
|
FROM
|
||||||
|
( SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost
|
||||||
|
FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id) AS query
|
||||||
|
WHERE data_entry_exit_id = t2.data_entry_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
drop view v1;
|
||||||
|
drop table t1, t2;
|
||||||
|
|
|
@ -559,3 +559,76 @@ SHOW STATUS LIKE 'HANDLER_UPDATE';
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-8938: Server Crash on Update with joins
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE `t1` (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` varchar(4095) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`name`)
|
||||||
|
);
|
||||||
|
|
||||||
|
UPDATE `t1` SET value = CONCAT("*.",(SELECT `temptable`.`value` FROM (SELECT * FROM `t1` WHERE `name`="consoleproxy.url.domain") AS `temptable` WHERE `temptable`.`name`="consoleproxy.url.domain")) WHERE `name`="consoleproxy.url.domain";
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
CREATE TABLE `t1` (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` varchar(4095) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`name`)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table t2 (
|
||||||
|
`name` varchar(255) NOT NULL,
|
||||||
|
`value` varchar(4095) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`name`)
|
||||||
|
);
|
||||||
|
|
||||||
|
UPDATE t1
|
||||||
|
SET value = (SELECT value FROM t2 WHERE `name`= t1.name)
|
||||||
|
WHERE value is null ;
|
||||||
|
|
||||||
|
drop table t1,t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo #MDEV-8701: Crash on derived query
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
data_exit_entry_id int(11) NOT NULL,
|
||||||
|
data_entry_id int(11) NOT NULL,
|
||||||
|
data_entry_exit_id int(11) NOT NULL,
|
||||||
|
data_exit_entry_quantity double NOT NULL
|
||||||
|
) DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
data_entry_id int(11) NOT NULL,
|
||||||
|
data_entry_cost double NOT NULL,
|
||||||
|
data_entry_quantity double NOT NULL
|
||||||
|
) DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
create algorithm=temptable view v1 as SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost
|
||||||
|
FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id;
|
||||||
|
|
||||||
|
UPDATE t2
|
||||||
|
SET data_entry_cost
|
||||||
|
= ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost)
|
||||||
|
FROM
|
||||||
|
v1 AS query
|
||||||
|
WHERE data_entry_exit_id = t2.data_entry_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
UPDATE t2
|
||||||
|
SET data_entry_cost
|
||||||
|
= ( ( SELECT SUM(data_exit_entry_quantity * data_entry_cost)
|
||||||
|
FROM
|
||||||
|
( SELECT data_entry_exit_id, data_exit_entry_quantity, data_entry_cost
|
||||||
|
FROM t1 INNER JOIN t2 as dt ON dt.data_entry_id = t1.data_entry_id) AS query
|
||||||
|
WHERE data_entry_exit_id = t2.data_entry_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
drop view v1;
|
||||||
|
drop table t1, t2;
|
||||||
|
|
|
@ -1408,7 +1408,8 @@ static int mysql_test_update(Prepared_statement *stmt,
|
||||||
(SELECT_ACL & ~table_list->table->grant.privilege);
|
(SELECT_ACL & ~table_list->table->grant.privilege);
|
||||||
table_list->register_want_access(SELECT_ACL);
|
table_list->register_want_access(SELECT_ACL);
|
||||||
#endif
|
#endif
|
||||||
if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0))
|
if (setup_fields(thd, 0, stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) ||
|
||||||
|
check_unique_table(thd, table_list))
|
||||||
goto error;
|
goto error;
|
||||||
/* TODO: here we should send types of placeholders to the client. */
|
/* TODO: here we should send types of placeholders to the client. */
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
|
@ -367,6 +367,9 @@ int mysql_update(THD *thd,
|
||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_unique_table(thd, table_list))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */
|
/* Apply the IN=>EXISTS transformation to all subqueries and optimize them. */
|
||||||
if (select_lex->optimize_unflattened_subqueries(false))
|
if (select_lex->optimize_unflattened_subqueries(false))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
@ -1036,20 +1039,31 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||||
setup_ftfuncs(select_lex))
|
setup_ftfuncs(select_lex))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/* Check that we are not using table that we are updating in a sub select */
|
select_lex->fix_prepare_information(thd, conds, &fake_conds);
|
||||||
{
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check that we are not using table that we are updating in a sub select
|
||||||
|
|
||||||
|
@param thd Thread handle
|
||||||
|
@param table_list List of table with first to check
|
||||||
|
|
||||||
|
@retval TRUE Error
|
||||||
|
@retval FALSE OK
|
||||||
|
*/
|
||||||
|
bool check_unique_table(THD *thd, TABLE_LIST *table_list)
|
||||||
|
{
|
||||||
TABLE_LIST *duplicate;
|
TABLE_LIST *duplicate;
|
||||||
|
DBUG_ENTER("check_unique_table");
|
||||||
if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
|
if ((duplicate= unique_table(thd, table_list, table_list->next_global, 0)))
|
||||||
{
|
{
|
||||||
update_non_unique_table_error(table_list, "UPDATE", duplicate);
|
update_non_unique_table_error(table_list, "UPDATE", duplicate);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
select_lex->fix_prepare_information(thd, conds, &fake_conds);
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
Update multiple tables from join
|
Update multiple tables from join
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
|
@ -27,6 +27,7 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
||||||
|
|
||||||
bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||||
Item **conds, uint order_num, ORDER *order);
|
Item **conds, uint order_num, ORDER *order);
|
||||||
|
bool check_unique_table(THD *thd, TABLE_LIST *table_list);
|
||||||
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||||
List<Item> &values,COND *conds,
|
List<Item> &values,COND *conds,
|
||||||
uint order_num, ORDER *order, ha_rows limit,
|
uint order_num, ORDER *order, ha_rows limit,
|
||||||
|
|
Loading…
Add table
Reference in a new issue