maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #02604
Rev 2774: BUG#43768: Prepared query with nested subqueries core dumps on second execution in file:///home/psergey/dev/maria-5.3-subqueries-r7-rel/
At file:///home/psergey/dev/maria-5.3-subqueries-r7-rel/
------------------------------------------------------------
revno: 2774
revision-id: psergey@xxxxxxxxxxxx-20100314175412-umtxuabkn4txl1yd
parent: psergey@xxxxxxxxxxxx-20100307154145-ksby2b1l0sqm1xne
committer: Sergey Petrunya <psergey@xxxxxxxxxxxx>
branch nick: maria-5.3-subqueries-r7-rel
timestamp: Sun 2010-03-14 20:54:12 +0300
message:
BUG#43768: Prepared query with nested subqueries core dumps on second execution
Fix two problems:
1. Let optimize_semijoin_nests() reset sj_nest->sjmat_info irrespectively
of value of optimizer_flag. We need this in case somebody has turned optimization
off between reexecutions of the same statement.
2. Do not pull out constant tables out of semi-join nests. The problem is that pullout
operation is not undoable, and if a table is constant because it is 1/0-row table it
may cease to be constant on the next execution. Note that tables that are constant
because of possible eq_ref(const) access will still be pulled out as they are
considered functionally-dependent.
=== modified file 'mysql-test/r/subselect_sj.result'
--- a/mysql-test/r/subselect_sj.result 2010-02-24 11:33:42 +0000
+++ b/mysql-test/r/subselect_sj.result 2010-03-14 17:54:12 +0000
@@ -1,4 +1,4 @@
-drop table if exists t0, t1, t2, t10, t11, t12;
+drop table if exists t0, t1, t2, t3, t4, t10, t11, t12;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1(a int, b int);
@@ -871,3 +871,54 @@
DROP TABLE t1, t2, t3;
DROP VIEW v2, v3;
# End of Bug#49198
+#
+# BUG#43768: Prepared query with nested subqueries core dumps on second execution
+#
+create table t1 (
+id int(11) unsigned not null primary key auto_increment,
+partner_id varchar(35) not null,
+t1_status_id int(10) unsigned
+);
+insert into t1 values ("1", "partner1", "10"), ("2", "partner2", "10"),
+("3", "partner3", "10"), ("4", "partner4", "10");
+create table t2 (
+id int(11) unsigned not null default '0',
+t1_line_id int(11) unsigned not null default '0',
+article_id varchar(20),
+sequence int(11) not null default '0',
+primary key (id,t1_line_id)
+);
+insert into t2 values ("1", "1", "sup", "0"), ("2", "1", "sup", "1"),
+("2", "2", "sup", "2"), ("2", "3", "sup", "3"),
+("2", "4", "imp", "4"), ("3", "1", "sup", "0"),
+("4", "1", "sup", "0");
+create table t3 (
+id int(11) not null default '0',
+preceeding_id int(11) not null default '0',
+primary key (id,preceeding_id)
+);
+create table t4 (
+user_id varchar(50) not null,
+article_id varchar(20) not null,
+primary key (user_id,article_id)
+);
+insert into t4 values("nicke", "imp");
+prepare stmt from
+'select t1.partner_id
+from t1
+where
+ t1.id in (
+ select pl_inner.id
+ from t2 as pl_inner
+ where pl_inner.article_id in (
+ select t4.article_id from t4
+ where t4.user_id = \'nicke\'
+ )
+ )';
+execute stmt;
+partner_id
+partner2
+execute stmt;
+partner_id
+partner2
+drop table t1,t2,t3,t4;
=== modified file 'mysql-test/r/subselect_sj_jcl6.result'
--- a/mysql-test/r/subselect_sj_jcl6.result 2010-03-07 15:41:45 +0000
+++ b/mysql-test/r/subselect_sj_jcl6.result 2010-03-14 17:54:12 +0000
@@ -2,7 +2,7 @@
show variables like 'join_cache_level';
Variable_name Value
join_cache_level 6
-drop table if exists t0, t1, t2, t10, t11, t12;
+drop table if exists t0, t1, t2, t3, t4, t10, t11, t12;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1(a int, b int);
@@ -876,6 +876,57 @@
DROP VIEW v2, v3;
# End of Bug#49198
#
+# BUG#43768: Prepared query with nested subqueries core dumps on second execution
+#
+create table t1 (
+id int(11) unsigned not null primary key auto_increment,
+partner_id varchar(35) not null,
+t1_status_id int(10) unsigned
+);
+insert into t1 values ("1", "partner1", "10"), ("2", "partner2", "10"),
+("3", "partner3", "10"), ("4", "partner4", "10");
+create table t2 (
+id int(11) unsigned not null default '0',
+t1_line_id int(11) unsigned not null default '0',
+article_id varchar(20),
+sequence int(11) not null default '0',
+primary key (id,t1_line_id)
+);
+insert into t2 values ("1", "1", "sup", "0"), ("2", "1", "sup", "1"),
+("2", "2", "sup", "2"), ("2", "3", "sup", "3"),
+("2", "4", "imp", "4"), ("3", "1", "sup", "0"),
+("4", "1", "sup", "0");
+create table t3 (
+id int(11) not null default '0',
+preceeding_id int(11) not null default '0',
+primary key (id,preceeding_id)
+);
+create table t4 (
+user_id varchar(50) not null,
+article_id varchar(20) not null,
+primary key (user_id,article_id)
+);
+insert into t4 values("nicke", "imp");
+prepare stmt from
+'select t1.partner_id
+from t1
+where
+ t1.id in (
+ select pl_inner.id
+ from t2 as pl_inner
+ where pl_inner.article_id in (
+ select t4.article_id from t4
+ where t4.user_id = \'nicke\'
+ )
+ )';
+execute stmt;
+partner_id
+partner2
+execute stmt;
+partner_id
+partner2
+drop table t1,t2,t3,t4;
+#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
#
CREATE TABLE t0 (a INT);
=== modified file 'mysql-test/t/subselect_sj.test'
--- a/mysql-test/t/subselect_sj.test 2010-02-24 11:33:42 +0000
+++ b/mysql-test/t/subselect_sj.test 2010-03-14 17:54:12 +0000
@@ -2,7 +2,7 @@
# Nested Loops semi-join subquery evaluation tests
#
--disable_warnings
-drop table if exists t0, t1, t2, t10, t11, t12;
+drop table if exists t0, t1, t2, t3, t4, t10, t11, t12;
--enable_warnings
#
@@ -770,3 +770,60 @@
DROP VIEW v2, v3;
--echo # End of Bug#49198
+
+--echo #
+--echo # BUG#43768: Prepared query with nested subqueries core dumps on second execution
+--echo #
+create table t1 (
+ id int(11) unsigned not null primary key auto_increment,
+ partner_id varchar(35) not null,
+ t1_status_id int(10) unsigned
+);
+
+insert into t1 values ("1", "partner1", "10"), ("2", "partner2", "10"),
+ ("3", "partner3", "10"), ("4", "partner4", "10");
+
+create table t2 (
+ id int(11) unsigned not null default '0',
+ t1_line_id int(11) unsigned not null default '0',
+ article_id varchar(20),
+ sequence int(11) not null default '0',
+ primary key (id,t1_line_id)
+);
+
+insert into t2 values ("1", "1", "sup", "0"), ("2", "1", "sup", "1"),
+ ("2", "2", "sup", "2"), ("2", "3", "sup", "3"),
+ ("2", "4", "imp", "4"), ("3", "1", "sup", "0"),
+ ("4", "1", "sup", "0");
+create table t3 (
+ id int(11) not null default '0',
+ preceeding_id int(11) not null default '0',
+ primary key (id,preceeding_id)
+);
+
+create table t4 (
+ user_id varchar(50) not null,
+ article_id varchar(20) not null,
+ primary key (user_id,article_id)
+);
+
+insert into t4 values("nicke", "imp");
+prepare stmt from
+'select t1.partner_id
+from t1
+where
+ t1.id in (
+ select pl_inner.id
+ from t2 as pl_inner
+ where pl_inner.article_id in (
+ select t4.article_id from t4
+ where t4.user_id = \'nicke\'
+ )
+ )';
+
+execute stmt;
+execute stmt;
+drop table t1,t2,t3,t4;
+
+
+
=== modified file 'sql/opt_subselect.cc'
--- a/sql/opt_subselect.cc 2010-03-07 15:41:45 +0000
+++ b/sql/opt_subselect.cc 2010-03-14 17:54:12 +0000
@@ -963,7 +963,6 @@
{
/* Action #1: Mark the constant tables to be pulled out */
table_map pulled_tables= 0;
-
List_iterator<TABLE_LIST> child_li(sj_nest->nested_join->join_list);
TABLE_LIST *tbl;
while ((tbl= child_li++))
@@ -971,12 +970,34 @@
if (tbl->table)
{
tbl->table->reginfo.join_tab->emb_sj_nest= sj_nest;
+#if 0
+ /*
+ Do not pull out tables because they are constant. This operation has
+ a problem:
+ - Some constant tables may become/cease to be constant across PS
+ re-executions
+ - Contrary to our initial assumption, it turned out that table pullout
+ operation is not easily undoable.
+
+ The solution is to leave constant tables where they are. This will
+ affect only constant tables that are 1-row or empty, tables that are
+ constant because they are accessed via eq_ref(const) access will
+ still be pulled out as functionally-dependent.
+
+ This will cause us to miss the chance to flatten some of the
+ subqueries, but since const tables do not generate many duplicates,
+ it really doesn't matter that much whether they were pulled out or
+ not.
+
+ All of this was done as fix for BUG#43768.
+ */
if (tbl->table->map & join->const_table_map)
{
pulled_tables |= tbl->table->map;
DBUG_PRINT("info", ("Table %s pulled out (reason: constant)",
tbl->table->alias));
}
+#endif
}
}
@@ -1048,6 +1069,7 @@
pointers.
*/
child_li.remove();
+ sj_nest->nested_join->used_tables &= ~tbl->table->map;
upper_join_list->push_back(tbl);
tbl->join_list= upper_join_list;
tbl->embedding= sj_nest->embedding;
@@ -1104,20 +1126,20 @@
DBUG_ENTER("optimize_semijoin_nests");
List_iterator<TABLE_LIST> sj_list_it(join->select_lex->sj_nests);
TABLE_LIST *sj_nest;
- /*
- The statement may have been executed with 'semijoin=on' earlier.
- We need to verify that 'semijoin=on' still holds.
- */
- if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_SEMIJOIN) &&
- optimizer_flag(join->thd, OPTIMIZER_SWITCH_MATERIALIZATION))
+ while ((sj_nest= sj_list_it++))
{
- while ((sj_nest= sj_list_it++))
+ /* semi-join nests with only constant tables are not valid */
+ /// DBUG_ASSERT(sj_nest->sj_inner_tables & ~join->const_table_map);
+
+ sj_nest->sj_mat_info= NULL;
+ /*
+ The statement may have been executed with 'semijoin=on' earlier.
+ We need to verify that 'semijoin=on' still holds.
+ */
+ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_SEMIJOIN) &&
+ optimizer_flag(join->thd, OPTIMIZER_SWITCH_MATERIALIZATION))
{
- /* semi-join nests with only constant tables are not valid */
- DBUG_ASSERT(sj_nest->sj_inner_tables & ~join->const_table_map);
-
- sj_nest->sj_mat_info= NULL;
- if (sj_nest->sj_inner_tables && /* not everything was pulled out */
+ if ((sj_nest->sj_inner_tables & ~join->const_table_map) && /* not everything was pulled out */
!sj_nest->sj_subq_pred->is_correlated &&
sj_nest->sj_subq_pred->types_allow_materialization)
{
@@ -1128,7 +1150,7 @@
The best plan to run the subquery is now in join->best_positions,
save it.
*/
- uint n_tables= my_count_bits(sj_nest->sj_inner_tables);
+ uint n_tables= my_count_bits(sj_nest->sj_inner_tables & ~join->const_table_map);
SJ_MATERIALIZATION_INFO* sjm;
if (!(sjm= new SJ_MATERIALIZATION_INFO) ||
!(sjm->positions= (POSITION*)join->thd->alloc(sizeof(POSITION)*
@@ -1443,7 +1465,7 @@
new_join_tab->emb_sj_nest->nested_join->sj_corr_tables |
new_join_tab->emb_sj_nest->nested_join->sj_depends_on;
const table_map sj_inner_tables=
- new_join_tab->emb_sj_nest->sj_inner_tables;
+ new_join_tab->emb_sj_nest->sj_inner_tables & ~join->const_table_map;
/*
Enter condition:
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2010-03-07 15:41:45 +0000
+++ b/sql/sql_select.cc 2010-03-14 17:54:12 +0000
@@ -5127,7 +5127,9 @@
/* number of tables that remain to be optimized */
n_tables= size_remain= my_count_bits(remaining_tables &
(join->emb_sjm_nest?
- join->emb_sjm_nest->sj_inner_tables :
+ (join->emb_sjm_nest->sj_inner_tables &
+ ~join->const_table_map)
+ :
~(table_map)0));
do {
@@ -5387,7 +5389,7 @@
table_map allowed_tables= ~(table_map)0;
if (join->emb_sjm_nest)
- allowed_tables= join->emb_sjm_nest->sj_inner_tables;
+ allowed_tables= join->emb_sjm_nest->sj_inner_tables & ~join->const_table_map;
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{