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); ...@@ -654,6 +654,9 @@ INSERT INTO t3 VALUES (1), (2);
UPDATE IGNORE UPDATE IGNORE
( SELECT ( SELECT COUNT(*) FROM t1 GROUP BY a, @v ) a FROM t2 ) x, t3 ( SELECT ( SELECT COUNT(*) FROM t1 GROUP BY a, @v ) a FROM t2 ) x, t3
SET t3.a = 0; 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; DROP TABLE t1, t2, t3;
SET SESSION sql_safe_updates = DEFAULT; SET SESSION sql_safe_updates = DEFAULT;
# #
...@@ -662,6 +665,14 @@ SET SESSION sql_safe_updates = DEFAULT; ...@@ -662,6 +665,14 @@ SET SESSION sql_safe_updates = DEFAULT;
CREATE FUNCTION f1 () RETURNS BLOB RETURN 1; CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
CREATE TABLE t1 (f1 DATE); CREATE TABLE t1 (f1 DATE);
INSERT INTO t1 VALUES('2001-01-01'); 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 FUNCTION f1;
DROP TABLE t1; DROP TABLE t1;
end of tests end of tests
...@@ -79,4 +79,6 @@ drop table bug38999_1,bug38999_2; ...@@ -79,4 +79,6 @@ drop table bug38999_1,bug38999_2;
# #
CREATE TABLE t1(f1 INT) ENGINE=INNODB; CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1); 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; DROP TABLE t1;
...@@ -34,9 +34,7 @@ drop table bug38999_1,bug38999_2; ...@@ -34,9 +34,7 @@ drop table bug38999_1,bug38999_2;
--echo # --echo #
CREATE TABLE t1(f1 INT) ENGINE=INNODB; CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
# !!! This query returns a wrong error due to a bug in the code of mwl106 --error ER_OPERAND_COLUMNS
# !!! Uncomment it when the bug is fixed 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; DROP TABLE t1;
...@@ -79,4 +79,6 @@ drop table bug38999_1,bug38999_2; ...@@ -79,4 +79,6 @@ drop table bug38999_1,bug38999_2;
# #
CREATE TABLE t1(f1 INT) ENGINE=INNODB; CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1); 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; DROP TABLE t1;
...@@ -34,9 +34,7 @@ drop table bug38999_1,bug38999_2; ...@@ -34,9 +34,7 @@ drop table bug38999_1,bug38999_2;
--echo # --echo #
CREATE TABLE t1(f1 INT) ENGINE=INNODB; CREATE TABLE t1(f1 INT) ENGINE=INNODB;
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
# !!! This query returns a wrong error due to a bug in the code of mwl106 --error ER_OPERAND_COLUMNS
# !!! Uncomment it when the bug is fixed 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; DROP TABLE t1;
...@@ -684,9 +684,10 @@ SET SESSION sql_safe_updates = DEFAULT; ...@@ -684,9 +684,10 @@ SET SESSION sql_safe_updates = DEFAULT;
CREATE FUNCTION f1 () RETURNS BLOB RETURN 1; CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
CREATE TABLE t1 (f1 DATE); CREATE TABLE t1 (f1 DATE);
INSERT INTO t1 VALUES('2001-01-01'); INSERT INTO t1 VALUES('2001-01-01');
# !!! This query returns a wrong error due to a bug in the code of mwl106 UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
# !!! Uncomment it when the bug is fixed CREATE view v1 as SELECT f1() FROM t1;
# UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1; UPDATE (SELECT 1 FROM t1 WHERE f1 = (select * from v1)) x, t1 SET f1 = 1;
DROP VIEW v1;
DROP FUNCTION f1; DROP FUNCTION f1;
DROP TABLE t1; DROP TABLE t1;
......
...@@ -585,6 +585,8 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -585,6 +585,8 @@ class st_select_lex_unit: public st_select_lex_node {
void set_thd(THD *thd_arg) { thd= thd_arg; } void set_thd(THD *thd_arg) { thd= thd_arg; }
inline bool is_union (); inline bool is_union ();
void set_unique_exlude();
friend void lex_start(THD *thd); friend void lex_start(THD *thd);
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
......
...@@ -944,3 +944,27 @@ void st_select_lex::cleanup_all_joins(bool full) ...@@ -944,3 +944,27 @@ void st_select_lex::cleanup_all_joins(bool full)
for (sl= unit->first_select(); sl; sl= sl->next_select()) for (sl= unit->first_select(); sl; sl= sl->next_select())
sl->cleanup_all_joins(full); 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) ...@@ -1040,8 +1040,8 @@ int mysql_multi_update_prepare(THD *thd)
//We need to merge for insert prior to prepare. //We need to merge for insert prior to prepare.
if (mysql_handle_list_of_derived(lex, table_list, DT_MERGE_FOR_INSERT)) if (mysql_handle_list_of_derived(lex, table_list, DT_MERGE_FOR_INSERT))
DBUG_RETURN(1); DBUG_RETURN(1);
if (mysql_handle_list_of_derived(lex, table_list, DT_PREPARE)) if (mysql_handle_derived(lex, DT_PREPARE))
DBUG_RETURN(1); DBUG_RETURN(TRUE);
if (setup_tables_and_check_access(thd, &lex->select_lex.context, if (setup_tables_and_check_access(thd, &lex->select_lex.context,
&lex->select_lex.top_join_list, &lex->select_lex.top_join_list,
......
...@@ -5851,7 +5851,9 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) ...@@ -5851,7 +5851,9 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
if (!is_view()) if (!is_view())
{ {
/* A subquery might be forced to be materialized due to a side-effect. */ /* 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(); set_merged_derived();
else else
set_materialized_derived(); set_materialized_derived();
...@@ -5862,9 +5864,7 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) ...@@ -5862,9 +5864,7 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
*/ */
if (is_materialized_derived()) if (is_materialized_derived())
{ {
SELECT_LEX *sl; unit->master_unit()->set_unique_exlude();
for (sl= first_select ;sl ; sl= sl->next_select())
sl->exclude_from_table_unique_test= TRUE;
} }
/* /*
Create field translation for mergeable derived tables/views. 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