Commit 3e271b82 authored by Igor Babaev's avatar Igor Babaev

Applied Sanja's patch to fix LP bug #784297 in the tree for mwl106.

The patch imposes unconditional materialization for derived tables
used in update and multi-update statements.
Fixed a bug with a wrong order of processing derived tables/views
at the prepare stage that caused a crash for the variant of the 
query from test case for bug 52157.
parent d6d46b01
......@@ -654,6 +654,9 @@ INSERT INTO t3 VALUES (1), (2);
UPDATE IGNORE
( SELECT ( SELECT COUNT(*) FROM t1 GROUP BY a, @v ) a FROM t2 ) x, t3
SET t3.a = 0;
Warnings:
Error 1242 Subquery returns more than 1 row
Error 1242 Subquery returns more than 1 row
DROP TABLE t1, t2, t3;
SET SESSION sql_safe_updates = DEFAULT;
#
......@@ -662,6 +665,14 @@ SET SESSION sql_safe_updates = DEFAULT;
CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
CREATE TABLE t1 (f1 DATE);
INSERT INTO t1 VALUES('2001-01-01');
UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
Warnings:
Warning 1292 Truncated incorrect datetime value: '1'
CREATE view v1 as SELECT f1() FROM t1;
UPDATE (SELECT 1 FROM t1 WHERE f1 = (select * from v1)) x, t1 SET f1 = 1;
Warnings:
Warning 1292 Truncated incorrect datetime value: '1'
DROP VIEW v1;
DROP FUNCTION f1;
DROP TABLE t1;
end of tests
......@@ -79,4 +79,6 @@ drop table bug38999_1,bug38999_2;
#
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
ERROR 21000: Operand should contain 1 column(s)
DROP TABLE t1;
......@@ -34,9 +34,7 @@ drop table bug38999_1,bug38999_2;
--echo #
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
# !!! This query returns a wrong error due to a bug in the code of mwl106
# !!! Uncomment it when the bug is fixed
# --error ER_OPERAND_COLUMNS
# UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
--error ER_OPERAND_COLUMNS
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
DROP TABLE t1;
......@@ -79,4 +79,6 @@ drop table bug38999_1,bug38999_2;
#
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
ERROR 21000: Operand should contain 1 column(s)
DROP TABLE t1;
......@@ -34,9 +34,7 @@ drop table bug38999_1,bug38999_2;
--echo #
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1);
# !!! This query returns a wrong error due to a bug in the code of mwl106
# !!! Uncomment it when the bug is fixed
# --error ER_OPERAND_COLUMNS
# UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
--error ER_OPERAND_COLUMNS
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
DROP TABLE t1;
......@@ -684,9 +684,10 @@ SET SESSION sql_safe_updates = DEFAULT;
CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
CREATE TABLE t1 (f1 DATE);
INSERT INTO t1 VALUES('2001-01-01');
# !!! This query returns a wrong error due to a bug in the code of mwl106
# !!! Uncomment it when the bug is fixed
# UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
CREATE view v1 as SELECT f1() FROM t1;
UPDATE (SELECT 1 FROM t1 WHERE f1 = (select * from v1)) x, t1 SET f1 = 1;
DROP VIEW v1;
DROP FUNCTION f1;
DROP TABLE t1;
......
......@@ -585,6 +585,8 @@ class st_select_lex_unit: public st_select_lex_node {
void set_thd(THD *thd_arg) { thd= thd_arg; }
inline bool is_union ();
void set_unique_exlude();
friend void lex_start(THD *thd);
friend int subselect_union_engine::exec();
......
......@@ -944,3 +944,27 @@ void st_select_lex::cleanup_all_joins(bool full)
for (sl= unit->first_select(); sl; sl= sl->next_select())
sl->cleanup_all_joins(full);
}
/**
Set exclude_from_table_unique_test for selects of this unit and all
underlying selects.
@note used to exclude materialized derived tables (views) from unique
table check.
*/
void st_select_lex_unit::set_unique_exlude()
{
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
sl->exclude_from_table_unique_test= TRUE;
for (SELECT_LEX_UNIT *unit= sl->first_inner_unit();
unit;
unit= unit->next_unit())
{
unit->set_unique_exlude();
}
}
}
......@@ -1040,8 +1040,8 @@ int mysql_multi_update_prepare(THD *thd)
//We need to merge for insert prior to prepare.
if (mysql_handle_list_of_derived(lex, table_list, DT_MERGE_FOR_INSERT))
DBUG_RETURN(1);
if (mysql_handle_list_of_derived(lex, table_list, DT_PREPARE))
DBUG_RETURN(1);
if (mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(TRUE);
if (setup_tables_and_check_access(thd, &lex->select_lex.context,
&lex->select_lex.top_join_list,
......
......@@ -5851,7 +5851,9 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
if (!is_view())
{
/* A subquery might be forced to be materialized due to a side-effect. */
if (!is_materialized_derived() && first_select->is_mergeable())
if (!is_materialized_derived() && first_select->is_mergeable() &&
!(thd->lex->sql_command == SQLCOM_UPDATE_MULTI ||
thd->lex->sql_command == SQLCOM_UPDATE))
set_merged_derived();
else
set_materialized_derived();
......@@ -5862,9 +5864,7 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
*/
if (is_materialized_derived())
{
SELECT_LEX *sl;
for (sl= first_select ;sl ; sl= sl->next_select())
sl->exclude_from_table_unique_test= TRUE;
unit->master_unit()->set_unique_exlude();
}
/*
Create field translation for mergeable derived tables/views.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment