List:Commits« Previous MessageNext Message »
From:Ole John Aske Date:November 13 2012 10:28am
Subject:bzr push into mysql-5.5-cluster-7.2 branch (ole.john.aske:4087 to 4088)
Bug#14709490
View as plain text  
 4088 Ole John Aske	2012-11-13 [merge]
      Merge 7.1 -> 7.2 (Bug#14709490)
      
      - Also added new (SPJ) testcase developed for this bug.
      - Updated some other testcase results as this fix may change 
        the EXPLAIN of some pushed queries.

    added:
      mysql-test/suite/ndb/r/ndb_bushy_joins.result
      mysql-test/suite/ndb/t/ndb_bushy_joins.cnf
      mysql-test/suite/ndb/t/ndb_bushy_joins.test
    modified:
      mysql-test/suite/ndb/r/ndb_condition_pushdown.result
      mysql-test/suite/ndb/r/ndb_join_pushdown_default.result
      mysql-test/suite/ndb/t/ndb_join_pushdown.inc
      sql/ha_ndbcluster_push.cc
      storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp
      storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
 4087 magnus.blaudd@stripped	2012-11-12 [merge]
      Merge 7.1 -> 7.2

    modified:
      storage/ndb/compile-cluster
=== added file 'mysql-test/suite/ndb/r/ndb_bushy_joins.result'

=== added file 'mysql-test/suite/ndb/r/ndb_bushy_joins.result'
--- a/mysql-test/suite/ndb/r/ndb_bushy_joins.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_bushy_joins.result	2012-11-13 10:27:06 +0000
@@ -0,0 +1,842 @@
+create table parent(a int primary key, b int, c int, d int) engine=ndb;
+create table eq_child(a int, b int, c int, d int, primary key(a,b)) engine=ndb;
+create table ref_child(a int, b int, c int, d int, primary key(a,b)) engine=ndb;
+alter table parent partition by key(a) partitions 32;
+alter table eq_child  partition by key(a) partitions 32;
+alter table ref_child  partition by key(a) partitions 32;
+insert into parent values (1,1,1,1);
+insert into parent select a+1, b+1, c+1, d+1  from parent;
+insert into parent select a+1*2, b+1*2, c+1*2, d+1*2  from parent;
+insert into parent select a+1*2*2, b+1*2*2, c+1*2*2, d+1*2*2  from parent;
+insert into parent select a+1*2*2*2, b+1*2*2*2, c+1*2*2*2, d+1*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2, b+1*2*2*2*2, c+1*2*2*2*2, d+1*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2, b+1*2*2*2*2*2, c+1*2*2*2*2*2, d+1*2*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2*2, b+1*2*2*2*2*2*2, c+1*2*2*2*2*2*2, d+1*2*2*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2*2*2, b+1*2*2*2*2*2*2*2, c+1*2*2*2*2*2*2*2, d+1*2*2*2*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2*2*2*2, b+1*2*2*2*2*2*2*2*2, c+1*2*2*2*2*2*2*2*2, d+1*2*2*2*2*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2*2*2*2*2, b+1*2*2*2*2*2*2*2*2*2, c+1*2*2*2*2*2*2*2*2*2, d+1*2*2*2*2*2*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2*2*2*2*2*2, b+1*2*2*2*2*2*2*2*2*2*2, c+1*2*2*2*2*2*2*2*2*2*2, d+1*2*2*2*2*2*2*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2*2*2*2*2*2*2, b+1*2*2*2*2*2*2*2*2*2*2*2, c+1*2*2*2*2*2*2*2*2*2*2*2, d+1*2*2*2*2*2*2*2*2*2*2*2  from parent;
+insert into parent select a+1*2*2*2*2*2*2*2*2*2*2*2*2, b+1*2*2*2*2*2*2*2*2*2*2*2*2, c+1*2*2*2*2*2*2*2*2*2*2*2*2, d+1*2*2*2*2*2*2*2*2*2*2*2*2  from parent;
+select count(*) from parent;
+count(*)
+8192
+insert into eq_child select * from parent;
+insert into ref_child select * from parent;
+update ref_child set a = a-(a%16) where a > 4000;
+analyze table parent, eq_child, ref_child;
+Table	Op	Msg_type	Msg_text
+test.parent	analyze	status	OK
+test.eq_child	analyze	status	OK
+test.ref_child	analyze	status	OK
+set ndb_join_pushdown = on;
+call mtr.add_suppression("starting connect thread");
+===============================
+Run single instance of 'query1' 
+===============================
+explain select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c5 on c5.a = parent.b and c5.b = parent.b
+join eq_child as c6 on c6.a = parent.b and c6.b = parent.b
+join eq_child as c7 on c7.a = parent.b and c7.b = parent.b
+join eq_child as c8 on c8.a = parent.b and c8.b = parent.b
+join eq_child as c9 on c9.a = parent.b and c9.b = parent.b
+join eq_child as c10 on c10.a = parent.b and c10.b = parent.b
+join eq_child as c11 on c11.a = parent.b and c11.b = parent.b
+join eq_child as c12 on c12.a = parent.b and c12.b = parent.b
+join eq_child as c13 on c13.a = parent.b and c13.b = parent.b
+join eq_child as c14 on c14.a = parent.b and c14.b = parent.b
+join eq_child as c15 on c15.a = parent.b and c15.b = parent.b
+join eq_child as c16 on c16.a = parent.b and c16.b = parent.b
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	ALL	NULL	NULL	NULL	NULL	8192	Parent of 17 pushed join@1
+1	SIMPLE	c1	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'parent' in pushed join@1
+1	SIMPLE	c2	eq_ref	PRIMARY	PRIMARY	8	test.c1.a,test.c1.b	1	Child of 'c1' in pushed join@1; Using where
+1	SIMPLE	c3	eq_ref	PRIMARY	PRIMARY	8	test.c2.a,test.c2.a	1	Child of 'c2' in pushed join@1; Using where
+1	SIMPLE	c4	eq_ref	PRIMARY	PRIMARY	8	test.c3.a,test.c1.b	1	Child of 'c3' in pushed join@1; Using where
+1	SIMPLE	c5	eq_ref	PRIMARY	PRIMARY	8	test.c4.a,test.c1.a	1	Child of 'c4' in pushed join@1; Using where
+1	SIMPLE	c6	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c5.a	1	Child of 'c5' in pushed join@1; Using where
+1	SIMPLE	c7	eq_ref	PRIMARY	PRIMARY	8	test.c4.a,test.c6.a	1	Child of 'c6' in pushed join@1; Using where
+1	SIMPLE	c8	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'c7' in pushed join@1
+1	SIMPLE	c9	eq_ref	PRIMARY	PRIMARY	8	test.c1.b,test.parent.b	1	Child of 'c8' in pushed join@1; Using where
+1	SIMPLE	c10	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c7.b	1	Child of 'c9' in pushed join@1; Using where
+1	SIMPLE	c11	eq_ref	PRIMARY	PRIMARY	8	test.c4.a,test.c7.b	1	Child of 'c10' in pushed join@1; Using where
+1	SIMPLE	c12	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c1.b	1	Child of 'c11' in pushed join@1; Using where
+1	SIMPLE	c13	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c1.b	1	Child of 'c12' in pushed join@1; Using where
+1	SIMPLE	c14	eq_ref	PRIMARY	PRIMARY	8	test.c5.a,test.c7.b	1	Child of 'c13' in pushed join@1; Using where
+1	SIMPLE	c15	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c1.b	1	Child of 'c14' in pushed join@1; Using where
+1	SIMPLE	c16	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c15.b	1	Child of 'c15' in pushed join@1; Using where
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c5 on c5.a = parent.b and c5.b = parent.b
+join eq_child as c6 on c6.a = parent.b and c6.b = parent.b
+join eq_child as c7 on c7.a = parent.b and c7.b = parent.b
+join eq_child as c8 on c8.a = parent.b and c8.b = parent.b
+join eq_child as c9 on c9.a = parent.b and c9.b = parent.b
+join eq_child as c10 on c10.a = parent.b and c10.b = parent.b
+join eq_child as c11 on c11.a = parent.b and c11.b = parent.b
+join eq_child as c12 on c12.a = parent.b and c12.b = parent.b
+join eq_child as c13 on c13.a = parent.b and c13.b = parent.b
+join eq_child as c14 on c14.a = parent.b and c14.b = parent.b
+join eq_child as c15 on c15.a = parent.b and c15.b = parent.b
+join eq_child as c16 on c16.a = parent.b and c16.b = parent.b
+;
+count(*)
+8192
+===============================
+Run single instance of 'query2' 
+===============================
+explain select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c5 on c5.a = c1.c and c5.b = c1.c
+join eq_child as c6 on c6.a = c1.c and c6.b = c1.c
+join eq_child as c7 on c7.a = c1.c and c7.b = c1.c
+join eq_child as c8 on c8.a = c1.c and c8.b = c1.c
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c9  on c9.a = c2.c  and c9.b  = c2.c
+join eq_child as c10 on c10.a = c2.c and c10.b = c2.c
+join eq_child as c11 on c11.a = c2.c and c11.b = c2.c
+join eq_child as c12 on c12.a = c2.c and c12.b = c2.c
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c13 on c13.a = c3.c and c13.b = c3.c
+join eq_child as c14 on c14.a = c3.c and c14.b = c3.c
+join eq_child as c15 on c15.a = c3.c and c15.b = c3.c
+join eq_child as c16 on c16.a = c3.c and c16.b = c3.c
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c17 on c17.a = c4.c and c17.b = c4.c
+join eq_child as c18 on c18.a = c4.c and c18.b = c4.c
+join eq_child as c19 on c19.a = c4.c and c19.b = c4.c
+join eq_child as c20 on c20.a = c4.c and c20.b = c4.c
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	ALL	NULL	NULL	NULL	NULL	8192	Parent of 21 pushed join@1
+1	SIMPLE	c1	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'parent' in pushed join@1
+1	SIMPLE	c5	eq_ref	PRIMARY	PRIMARY	8	test.c1.c,test.c1.c	1	Child of 'c1' in pushed join@1
+1	SIMPLE	c6	eq_ref	PRIMARY	PRIMARY	8	test.c1.c,test.c1.c	1	Child of 'c5' in pushed join@1
+1	SIMPLE	c7	eq_ref	PRIMARY	PRIMARY	8	test.c1.c,test.c5.b	1	Child of 'c6' in pushed join@1; Using where
+1	SIMPLE	c8	eq_ref	PRIMARY	PRIMARY	8	test.c7.b,test.c1.c	1	Child of 'c7' in pushed join@1; Using where
+1	SIMPLE	c2	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'c1' in pushed join@1
+1	SIMPLE	c9	eq_ref	PRIMARY	PRIMARY	8	test.c2.c,test.c2.c	1	Child of 'c2' in pushed join@1
+1	SIMPLE	c10	eq_ref	PRIMARY	PRIMARY	8	test.c2.c,test.c9.b	1	Child of 'c9' in pushed join@1; Using where
+1	SIMPLE	c11	eq_ref	PRIMARY	PRIMARY	8	test.c9.a,test.c9.b	1	Child of 'c10' in pushed join@1; Using where
+1	SIMPLE	c12	eq_ref	PRIMARY	PRIMARY	8	test.c10.b,test.c9.a	1	Child of 'c11' in pushed join@1; Using where
+1	SIMPLE	c3	eq_ref	PRIMARY	PRIMARY	8	test.c1.b,test.c1.b	1	Child of 'c2' in pushed join@1; Using where
+1	SIMPLE	c13	eq_ref	PRIMARY	PRIMARY	8	test.c3.c,test.c3.c	1	Child of 'c3' in pushed join@1
+1	SIMPLE	c14	eq_ref	PRIMARY	PRIMARY	8	test.c13.a,test.c13.b	1	Child of 'c13' in pushed join@1; Using where
+1	SIMPLE	c15	eq_ref	PRIMARY	PRIMARY	8	test.c13.b,test.c3.c	1	Child of 'c14' in pushed join@1; Using where
+1	SIMPLE	c16	eq_ref	PRIMARY	PRIMARY	8	test.c15.a,test.c13.a	1	Child of 'c15' in pushed join@1; Using where
+1	SIMPLE	c4	eq_ref	PRIMARY	PRIMARY	8	test.c1.a,test.parent.b	1	Child of 'c3' in pushed join@1; Using where
+1	SIMPLE	c17	eq_ref	PRIMARY	PRIMARY	8	test.c4.c,test.c4.c	1	Child of 'c4' in pushed join@1
+1	SIMPLE	c18	eq_ref	PRIMARY	PRIMARY	8	test.c4.c,test.c4.c	1	Child of 'c17' in pushed join@1
+1	SIMPLE	c19	eq_ref	PRIMARY	PRIMARY	8	test.c17.a,test.c17.b	1	Child of 'c18' in pushed join@1; Using where
+1	SIMPLE	c20	eq_ref	PRIMARY	PRIMARY	8	test.c19.b,test.c19.a	1	Child of 'c19' in pushed join@1; Using where
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c5 on c5.a = c1.c and c5.b = c1.c
+join eq_child as c6 on c6.a = c1.c and c6.b = c1.c
+join eq_child as c7 on c7.a = c1.c and c7.b = c1.c
+join eq_child as c8 on c8.a = c1.c and c8.b = c1.c
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c9  on c9.a = c2.c  and c9.b  = c2.c
+join eq_child as c10 on c10.a = c2.c and c10.b = c2.c
+join eq_child as c11 on c11.a = c2.c and c11.b = c2.c
+join eq_child as c12 on c12.a = c2.c and c12.b = c2.c
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c13 on c13.a = c3.c and c13.b = c3.c
+join eq_child as c14 on c14.a = c3.c and c14.b = c3.c
+join eq_child as c15 on c15.a = c3.c and c15.b = c3.c
+join eq_child as c16 on c16.a = c3.c and c16.b = c3.c
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c17 on c17.a = c4.c and c17.b = c4.c
+join eq_child as c18 on c18.a = c4.c and c18.b = c4.c
+join eq_child as c19 on c19.a = c4.c and c19.b = c4.c
+join eq_child as c20 on c20.a = c4.c and c20.b = c4.c
+;
+count(*)
+8192
+===============================
+Run single instance of 'query3' 
+===============================
+explain select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join ref_child as c2 on c2.a = parent.b
+join ref_child as c3 on c3.a = parent.b
+join ref_child as c4 on c4.a = parent.b
+join ref_child as c5 on c5.a = parent.b
+join ref_child as c6 on c6.a = parent.b
+join ref_child as c7 on c7.a = parent.b
+join ref_child as c8 on c8.a = parent.b
+join ref_child as c9 on c9.a = parent.b
+join ref_child as c10 on c10.a = parent.b
+join ref_child as c11 on c11.a = parent.b
+join ref_child as c12 on c12.a = parent.b
+join ref_child as c13 on c13.a = parent.b
+join ref_child as c14 on c14.a = parent.b
+join ref_child as c15 on c15.a = parent.b
+join ref_child as c16 on c16.a = parent.b
+where parent.a < 1000
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	range	PRIMARY	PRIMARY	4	NULL	1104	Parent of 17 pushed join@1; Using where with pushed condition
+1	SIMPLE	c1	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c2	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c3	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c4	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c5	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c6	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c7	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c8	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c9	ref	PRIMARY	PRIMARY	4	test.c1.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c10	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c11	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c12	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c13	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c14	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c15	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c16	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join ref_child as c2 on c2.a = parent.b
+join ref_child as c3 on c3.a = parent.b
+join ref_child as c4 on c4.a = parent.b
+join ref_child as c5 on c5.a = parent.b
+join ref_child as c6 on c6.a = parent.b
+join ref_child as c7 on c7.a = parent.b
+join ref_child as c8 on c8.a = parent.b
+join ref_child as c9 on c9.a = parent.b
+join ref_child as c10 on c10.a = parent.b
+join ref_child as c11 on c11.a = parent.b
+join ref_child as c12 on c12.a = parent.b
+join ref_child as c13 on c13.a = parent.b
+join ref_child as c14 on c14.a = parent.b
+join ref_child as c15 on c15.a = parent.b
+join ref_child as c16 on c16.a = parent.b
+where parent.a < 1000
+;
+count(*)
+999
+===============================
+Run single instance of 'query4' 
+===============================
+explain select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join eq_child as c1eq on c1eq.a = c1.a and c1eq.b = c1.b
+join ref_child as c2 on c2.a = parent.b
+join eq_child as c2eq on c2eq.a = c2.a and c2eq.b = c2.b
+join ref_child as c3 on c3.a = parent.b
+join eq_child as c3eq on c3eq.a = c3.a and c3eq.b = c3.b
+join ref_child as c4 on c4.a = parent.b
+join eq_child as c4eq on c4eq.a = c4.a and c4eq.b = c4.b
+join ref_child as c5 on c5.a = parent.b
+join eq_child as c5eq on c5eq.a = c5.a and c5eq.b = c5.b
+join ref_child as c6 on c6.a = parent.b
+join eq_child as c6eq on c6eq.a = c6.a and c6eq.b = c6.b
+join ref_child as c7 on c7.a = parent.b
+join eq_child as c7eq on c7eq.a = c7.a and c7eq.b = c7.b
+join ref_child as c8 on c8.a = parent.b
+join eq_child as c8eq on c8eq.a = c8.a and c8eq.b = c8.b
+join ref_child as c9 on c9.a = parent.b
+join eq_child as c9eq on c9eq.a = c9.a and c9eq.b = c9.b
+join ref_child as c10 on c10.a = parent.b
+join eq_child as c10eq on c10eq.a = c10.a and c10eq.b = c10.b
+join ref_child as c11 on c11.a = parent.b
+join eq_child as c11eq on c11eq.a = c11.a and c11eq.b = c11.b
+join ref_child as c12 on c12.a = parent.b
+join eq_child as c12eq on c12eq.a = c12.a and c12eq.b = c12.b
+join ref_child as c13 on c13.a = parent.b
+join eq_child as c13eq on c13eq.a = c13.a and c13eq.b = c13.b
+join ref_child as c14 on c14.a = parent.b
+join eq_child as c14eq on c14eq.a = c14.a and c14eq.b = c14.b
+join ref_child as c15 on c15.a = parent.b
+join eq_child as c15eq on c15eq.a = c15.a and c15eq.b = c15.b
+join ref_child as c16 on c16.a = parent.b
+join eq_child as c16eq on c16eq.a = c16.a and c16eq.b = c16.b
+where parent.a < 1000
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	range	PRIMARY	PRIMARY	4	NULL	1104	Parent of 32 pushed join@1; Using where with pushed condition
+1	SIMPLE	c1	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c1eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c1.b	1	Child of 'c1' in pushed join@1
+1	SIMPLE	c2	ref	PRIMARY	PRIMARY	4	test.c1.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c2eq	eq_ref	PRIMARY	PRIMARY	8	test.c2.a,test.c2.b	1	Child of 'c2' in pushed join@1; Using where
+1	SIMPLE	c3	ref	PRIMARY	PRIMARY	4	test.c2.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c3eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c3.b	1	Child of 'c3' in pushed join@1
+1	SIMPLE	c4	ref	PRIMARY	PRIMARY	4	test.c3.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c4eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c4.b	1	Child of 'c4' in pushed join@1
+1	SIMPLE	c5	ref	PRIMARY	PRIMARY	4	test.c4.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c5eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c5.b	1	Child of 'c5' in pushed join@1
+1	SIMPLE	c6	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c6eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c6.b	1	Child of 'c6' in pushed join@1
+1	SIMPLE	c7	ref	PRIMARY	PRIMARY	4	test.c5eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c7eq	eq_ref	PRIMARY	PRIMARY	8	test.c6.a,test.c7.b	1	Child of 'c7' in pushed join@1; Using where
+1	SIMPLE	c8	ref	PRIMARY	PRIMARY	4	test.c6eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c8eq	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c8.b	1	Child of 'c8' in pushed join@1; Using where
+1	SIMPLE	c9	ref	PRIMARY	PRIMARY	4	test.c6eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c9eq	eq_ref	PRIMARY	PRIMARY	8	test.c2eq.a,test.c9.b	1	Child of 'c9' in pushed join@1; Using where
+1	SIMPLE	c10	ref	PRIMARY	PRIMARY	4	test.c7.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c10eq	eq_ref	PRIMARY	PRIMARY	8	test.c7eq.a,test.c10.b	1	Child of 'c10' in pushed join@1; Using where
+1	SIMPLE	c11	ref	PRIMARY	PRIMARY	4	test.c7.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c11eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c11.b	1	Child of 'c11' in pushed join@1
+1	SIMPLE	c12	ref	PRIMARY	PRIMARY	4	test.c8eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c12eq	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c12.b	1	Child of 'c12' in pushed join@1; Using where
+1	SIMPLE	c13	ref	PRIMARY	PRIMARY	4	test.c6eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c13eq	eq_ref	PRIMARY	PRIMARY	8	test.c6.a,test.c13.b	1	Child of 'c13' in pushed join@1; Using where
+1	SIMPLE	c14	ref	PRIMARY	PRIMARY	4	test.c5.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c14eq	eq_ref	PRIMARY	PRIMARY	8	test.c5eq.a,test.c14.b	1	Child of 'c14' in pushed join@1; Using where
+1	SIMPLE	c15	ref	PRIMARY	PRIMARY	4	test.c1eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c15eq	eq_ref	PRIMARY	PRIMARY	8	test.c15.a,test.c15.b	1	Child of 'c15' in pushed join@1; Using where
+1	SIMPLE	c16	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c16eq	eq_ref	PRIMARY	PRIMARY	8	test.c5.a,test.c16.b	1	Using where
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join eq_child as c1eq on c1eq.a = c1.a and c1eq.b = c1.b
+join ref_child as c2 on c2.a = parent.b
+join eq_child as c2eq on c2eq.a = c2.a and c2eq.b = c2.b
+join ref_child as c3 on c3.a = parent.b
+join eq_child as c3eq on c3eq.a = c3.a and c3eq.b = c3.b
+join ref_child as c4 on c4.a = parent.b
+join eq_child as c4eq on c4eq.a = c4.a and c4eq.b = c4.b
+join ref_child as c5 on c5.a = parent.b
+join eq_child as c5eq on c5eq.a = c5.a and c5eq.b = c5.b
+join ref_child as c6 on c6.a = parent.b
+join eq_child as c6eq on c6eq.a = c6.a and c6eq.b = c6.b
+join ref_child as c7 on c7.a = parent.b
+join eq_child as c7eq on c7eq.a = c7.a and c7eq.b = c7.b
+join ref_child as c8 on c8.a = parent.b
+join eq_child as c8eq on c8eq.a = c8.a and c8eq.b = c8.b
+join ref_child as c9 on c9.a = parent.b
+join eq_child as c9eq on c9eq.a = c9.a and c9eq.b = c9.b
+join ref_child as c10 on c10.a = parent.b
+join eq_child as c10eq on c10eq.a = c10.a and c10eq.b = c10.b
+join ref_child as c11 on c11.a = parent.b
+join eq_child as c11eq on c11eq.a = c11.a and c11eq.b = c11.b
+join ref_child as c12 on c12.a = parent.b
+join eq_child as c12eq on c12eq.a = c12.a and c12eq.b = c12.b
+join ref_child as c13 on c13.a = parent.b
+join eq_child as c13eq on c13eq.a = c13.a and c13eq.b = c13.b
+join ref_child as c14 on c14.a = parent.b
+join eq_child as c14eq on c14eq.a = c14.a and c14eq.b = c14.b
+join ref_child as c15 on c15.a = parent.b
+join eq_child as c15eq on c15eq.a = c15.a and c15eq.b = c15.b
+join ref_child as c16 on c16.a = parent.b
+join eq_child as c16eq on c16eq.a = c16.a and c16eq.b = c16.b
+where parent.a < 1000
+;
+count(*)
+999
+=================================
+Run multiple 'query1' in parallel 
+=================================
+explain select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c5 on c5.a = parent.b and c5.b = parent.b
+join eq_child as c6 on c6.a = parent.b and c6.b = parent.b
+join eq_child as c7 on c7.a = parent.b and c7.b = parent.b
+join eq_child as c8 on c8.a = parent.b and c8.b = parent.b
+join eq_child as c9 on c9.a = parent.b and c9.b = parent.b
+join eq_child as c10 on c10.a = parent.b and c10.b = parent.b
+join eq_child as c11 on c11.a = parent.b and c11.b = parent.b
+join eq_child as c12 on c12.a = parent.b and c12.b = parent.b
+join eq_child as c13 on c13.a = parent.b and c13.b = parent.b
+join eq_child as c14 on c14.a = parent.b and c14.b = parent.b
+join eq_child as c15 on c15.a = parent.b and c15.b = parent.b
+join eq_child as c16 on c16.a = parent.b and c16.b = parent.b
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	ALL	NULL	NULL	NULL	NULL	8192	Parent of 17 pushed join@1
+1	SIMPLE	c1	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'parent' in pushed join@1
+1	SIMPLE	c2	eq_ref	PRIMARY	PRIMARY	8	test.c1.a,test.c1.b	1	Child of 'c1' in pushed join@1; Using where
+1	SIMPLE	c3	eq_ref	PRIMARY	PRIMARY	8	test.c2.a,test.c2.a	1	Child of 'c2' in pushed join@1; Using where
+1	SIMPLE	c4	eq_ref	PRIMARY	PRIMARY	8	test.c3.a,test.c1.b	1	Child of 'c3' in pushed join@1; Using where
+1	SIMPLE	c5	eq_ref	PRIMARY	PRIMARY	8	test.c4.a,test.c1.a	1	Child of 'c4' in pushed join@1; Using where
+1	SIMPLE	c6	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c5.a	1	Child of 'c5' in pushed join@1; Using where
+1	SIMPLE	c7	eq_ref	PRIMARY	PRIMARY	8	test.c4.a,test.c6.a	1	Child of 'c6' in pushed join@1; Using where
+1	SIMPLE	c8	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'c7' in pushed join@1
+1	SIMPLE	c9	eq_ref	PRIMARY	PRIMARY	8	test.c1.b,test.parent.b	1	Child of 'c8' in pushed join@1; Using where
+1	SIMPLE	c10	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c7.b	1	Child of 'c9' in pushed join@1; Using where
+1	SIMPLE	c11	eq_ref	PRIMARY	PRIMARY	8	test.c4.a,test.c7.b	1	Child of 'c10' in pushed join@1; Using where
+1	SIMPLE	c12	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c1.b	1	Child of 'c11' in pushed join@1; Using where
+1	SIMPLE	c13	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c1.b	1	Child of 'c12' in pushed join@1; Using where
+1	SIMPLE	c14	eq_ref	PRIMARY	PRIMARY	8	test.c5.a,test.c7.b	1	Child of 'c13' in pushed join@1; Using where
+1	SIMPLE	c15	eq_ref	PRIMARY	PRIMARY	8	test.c5.b,test.c1.b	1	Child of 'c14' in pushed join@1; Using where
+1	SIMPLE	c16	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c15.b	1	Child of 'c15' in pushed join@1; Using where
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c5 on c5.a = parent.b and c5.b = parent.b
+join eq_child as c6 on c6.a = parent.b and c6.b = parent.b
+join eq_child as c7 on c7.a = parent.b and c7.b = parent.b
+join eq_child as c8 on c8.a = parent.b and c8.b = parent.b
+join eq_child as c9 on c9.a = parent.b and c9.b = parent.b
+join eq_child as c10 on c10.a = parent.b and c10.b = parent.b
+join eq_child as c11 on c11.a = parent.b and c11.b = parent.b
+join eq_child as c12 on c12.a = parent.b and c12.b = parent.b
+join eq_child as c13 on c13.a = parent.b and c13.b = parent.b
+join eq_child as c14 on c14.a = parent.b and c14.b = parent.b
+join eq_child as c15 on c15.a = parent.b and c15.b = parent.b
+join eq_child as c16 on c16.a = parent.b and c16.b = parent.b
+;
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c5 on c5.a = parent.b and c5.b = parent.b
+join eq_child as c6 on c6.a = parent.b and c6.b = parent.b
+join eq_child as c7 on c7.a = parent.b and c7.b = parent.b
+join eq_child as c8 on c8.a = parent.b and c8.b = parent.b
+join eq_child as c9 on c9.a = parent.b and c9.b = parent.b
+join eq_child as c10 on c10.a = parent.b and c10.b = parent.b
+join eq_child as c11 on c11.a = parent.b and c11.b = parent.b
+join eq_child as c12 on c12.a = parent.b and c12.b = parent.b
+join eq_child as c13 on c13.a = parent.b and c13.b = parent.b
+join eq_child as c14 on c14.a = parent.b and c14.b = parent.b
+join eq_child as c15 on c15.a = parent.b and c15.b = parent.b
+join eq_child as c16 on c16.a = parent.b and c16.b = parent.b
+;
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c5 on c5.a = parent.b and c5.b = parent.b
+join eq_child as c6 on c6.a = parent.b and c6.b = parent.b
+join eq_child as c7 on c7.a = parent.b and c7.b = parent.b
+join eq_child as c8 on c8.a = parent.b and c8.b = parent.b
+join eq_child as c9 on c9.a = parent.b and c9.b = parent.b
+join eq_child as c10 on c10.a = parent.b and c10.b = parent.b
+join eq_child as c11 on c11.a = parent.b and c11.b = parent.b
+join eq_child as c12 on c12.a = parent.b and c12.b = parent.b
+join eq_child as c13 on c13.a = parent.b and c13.b = parent.b
+join eq_child as c14 on c14.a = parent.b and c14.b = parent.b
+join eq_child as c15 on c15.a = parent.b and c15.b = parent.b
+join eq_child as c16 on c16.a = parent.b and c16.b = parent.b
+;
+Await completion or failure
+count(*)
+8192
+count(*)
+8192
+count(*)
+8192
+=================================
+Run multiple 'query2' in parallel 
+=================================
+explain select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c5 on c5.a = c1.c and c5.b = c1.c
+join eq_child as c6 on c6.a = c1.c and c6.b = c1.c
+join eq_child as c7 on c7.a = c1.c and c7.b = c1.c
+join eq_child as c8 on c8.a = c1.c and c8.b = c1.c
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c9  on c9.a = c2.c  and c9.b  = c2.c
+join eq_child as c10 on c10.a = c2.c and c10.b = c2.c
+join eq_child as c11 on c11.a = c2.c and c11.b = c2.c
+join eq_child as c12 on c12.a = c2.c and c12.b = c2.c
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c13 on c13.a = c3.c and c13.b = c3.c
+join eq_child as c14 on c14.a = c3.c and c14.b = c3.c
+join eq_child as c15 on c15.a = c3.c and c15.b = c3.c
+join eq_child as c16 on c16.a = c3.c and c16.b = c3.c
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c17 on c17.a = c4.c and c17.b = c4.c
+join eq_child as c18 on c18.a = c4.c and c18.b = c4.c
+join eq_child as c19 on c19.a = c4.c and c19.b = c4.c
+join eq_child as c20 on c20.a = c4.c and c20.b = c4.c
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	ALL	NULL	NULL	NULL	NULL	8192	Parent of 21 pushed join@1
+1	SIMPLE	c1	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'parent' in pushed join@1
+1	SIMPLE	c5	eq_ref	PRIMARY	PRIMARY	8	test.c1.c,test.c1.c	1	Child of 'c1' in pushed join@1
+1	SIMPLE	c6	eq_ref	PRIMARY	PRIMARY	8	test.c1.c,test.c1.c	1	Child of 'c5' in pushed join@1
+1	SIMPLE	c7	eq_ref	PRIMARY	PRIMARY	8	test.c1.c,test.c5.b	1	Child of 'c6' in pushed join@1; Using where
+1	SIMPLE	c8	eq_ref	PRIMARY	PRIMARY	8	test.c7.b,test.c1.c	1	Child of 'c7' in pushed join@1; Using where
+1	SIMPLE	c2	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.parent.b	1	Child of 'c1' in pushed join@1
+1	SIMPLE	c9	eq_ref	PRIMARY	PRIMARY	8	test.c2.c,test.c2.c	1	Child of 'c2' in pushed join@1
+1	SIMPLE	c10	eq_ref	PRIMARY	PRIMARY	8	test.c2.c,test.c9.b	1	Child of 'c9' in pushed join@1; Using where
+1	SIMPLE	c11	eq_ref	PRIMARY	PRIMARY	8	test.c9.a,test.c9.b	1	Child of 'c10' in pushed join@1; Using where
+1	SIMPLE	c12	eq_ref	PRIMARY	PRIMARY	8	test.c10.b,test.c9.a	1	Child of 'c11' in pushed join@1; Using where
+1	SIMPLE	c3	eq_ref	PRIMARY	PRIMARY	8	test.c1.b,test.c1.b	1	Child of 'c2' in pushed join@1; Using where
+1	SIMPLE	c13	eq_ref	PRIMARY	PRIMARY	8	test.c3.c,test.c3.c	1	Child of 'c3' in pushed join@1
+1	SIMPLE	c14	eq_ref	PRIMARY	PRIMARY	8	test.c13.a,test.c13.b	1	Child of 'c13' in pushed join@1; Using where
+1	SIMPLE	c15	eq_ref	PRIMARY	PRIMARY	8	test.c13.b,test.c3.c	1	Child of 'c14' in pushed join@1; Using where
+1	SIMPLE	c16	eq_ref	PRIMARY	PRIMARY	8	test.c15.a,test.c13.a	1	Child of 'c15' in pushed join@1; Using where
+1	SIMPLE	c4	eq_ref	PRIMARY	PRIMARY	8	test.c1.a,test.parent.b	1	Child of 'c3' in pushed join@1; Using where
+1	SIMPLE	c17	eq_ref	PRIMARY	PRIMARY	8	test.c4.c,test.c4.c	1	Child of 'c4' in pushed join@1
+1	SIMPLE	c18	eq_ref	PRIMARY	PRIMARY	8	test.c4.c,test.c4.c	1	Child of 'c17' in pushed join@1
+1	SIMPLE	c19	eq_ref	PRIMARY	PRIMARY	8	test.c17.a,test.c17.b	1	Child of 'c18' in pushed join@1; Using where
+1	SIMPLE	c20	eq_ref	PRIMARY	PRIMARY	8	test.c19.b,test.c19.a	1	Child of 'c19' in pushed join@1; Using where
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c5 on c5.a = c1.c and c5.b = c1.c
+join eq_child as c6 on c6.a = c1.c and c6.b = c1.c
+join eq_child as c7 on c7.a = c1.c and c7.b = c1.c
+join eq_child as c8 on c8.a = c1.c and c8.b = c1.c
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c9  on c9.a = c2.c  and c9.b  = c2.c
+join eq_child as c10 on c10.a = c2.c and c10.b = c2.c
+join eq_child as c11 on c11.a = c2.c and c11.b = c2.c
+join eq_child as c12 on c12.a = c2.c and c12.b = c2.c
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c13 on c13.a = c3.c and c13.b = c3.c
+join eq_child as c14 on c14.a = c3.c and c14.b = c3.c
+join eq_child as c15 on c15.a = c3.c and c15.b = c3.c
+join eq_child as c16 on c16.a = c3.c and c16.b = c3.c
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c17 on c17.a = c4.c and c17.b = c4.c
+join eq_child as c18 on c18.a = c4.c and c18.b = c4.c
+join eq_child as c19 on c19.a = c4.c and c19.b = c4.c
+join eq_child as c20 on c20.a = c4.c and c20.b = c4.c
+;
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c5 on c5.a = c1.c and c5.b = c1.c
+join eq_child as c6 on c6.a = c1.c and c6.b = c1.c
+join eq_child as c7 on c7.a = c1.c and c7.b = c1.c
+join eq_child as c8 on c8.a = c1.c and c8.b = c1.c
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c9  on c9.a = c2.c  and c9.b  = c2.c
+join eq_child as c10 on c10.a = c2.c and c10.b = c2.c
+join eq_child as c11 on c11.a = c2.c and c11.b = c2.c
+join eq_child as c12 on c12.a = c2.c and c12.b = c2.c
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c13 on c13.a = c3.c and c13.b = c3.c
+join eq_child as c14 on c14.a = c3.c and c14.b = c3.c
+join eq_child as c15 on c15.a = c3.c and c15.b = c3.c
+join eq_child as c16 on c16.a = c3.c and c16.b = c3.c
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c17 on c17.a = c4.c and c17.b = c4.c
+join eq_child as c18 on c18.a = c4.c and c18.b = c4.c
+join eq_child as c19 on c19.a = c4.c and c19.b = c4.c
+join eq_child as c20 on c20.a = c4.c and c20.b = c4.c
+;
+select straight_join count(*) from parent
+join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+join eq_child as c5 on c5.a = c1.c and c5.b = c1.c
+join eq_child as c6 on c6.a = c1.c and c6.b = c1.c
+join eq_child as c7 on c7.a = c1.c and c7.b = c1.c
+join eq_child as c8 on c8.a = c1.c and c8.b = c1.c
+join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+join eq_child as c9  on c9.a = c2.c  and c9.b  = c2.c
+join eq_child as c10 on c10.a = c2.c and c10.b = c2.c
+join eq_child as c11 on c11.a = c2.c and c11.b = c2.c
+join eq_child as c12 on c12.a = c2.c and c12.b = c2.c
+join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+join eq_child as c13 on c13.a = c3.c and c13.b = c3.c
+join eq_child as c14 on c14.a = c3.c and c14.b = c3.c
+join eq_child as c15 on c15.a = c3.c and c15.b = c3.c
+join eq_child as c16 on c16.a = c3.c and c16.b = c3.c
+join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+join eq_child as c17 on c17.a = c4.c and c17.b = c4.c
+join eq_child as c18 on c18.a = c4.c and c18.b = c4.c
+join eq_child as c19 on c19.a = c4.c and c19.b = c4.c
+join eq_child as c20 on c20.a = c4.c and c20.b = c4.c
+;
+Await completion or failure
+count(*)
+8192
+count(*)
+8192
+count(*)
+8192
+=================================
+Run multiple 'query3' in parallel 
+=================================
+explain select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join ref_child as c2 on c2.a = parent.b
+join ref_child as c3 on c3.a = parent.b
+join ref_child as c4 on c4.a = parent.b
+join ref_child as c5 on c5.a = parent.b
+join ref_child as c6 on c6.a = parent.b
+join ref_child as c7 on c7.a = parent.b
+join ref_child as c8 on c8.a = parent.b
+join ref_child as c9 on c9.a = parent.b
+join ref_child as c10 on c10.a = parent.b
+join ref_child as c11 on c11.a = parent.b
+join ref_child as c12 on c12.a = parent.b
+join ref_child as c13 on c13.a = parent.b
+join ref_child as c14 on c14.a = parent.b
+join ref_child as c15 on c15.a = parent.b
+join ref_child as c16 on c16.a = parent.b
+where parent.a < 1000
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	range	PRIMARY	PRIMARY	4	NULL	1104	Parent of 17 pushed join@1; Using where with pushed condition
+1	SIMPLE	c1	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c2	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c3	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c4	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c5	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c6	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c7	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c8	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c9	ref	PRIMARY	PRIMARY	4	test.c1.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c10	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c11	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c12	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c13	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c14	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c15	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c16	ref	PRIMARY	PRIMARY	4	test.c10.a	54	Child of 'parent' in pushed join@1; Using where
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join ref_child as c2 on c2.a = parent.b
+join ref_child as c3 on c3.a = parent.b
+join ref_child as c4 on c4.a = parent.b
+join ref_child as c5 on c5.a = parent.b
+join ref_child as c6 on c6.a = parent.b
+join ref_child as c7 on c7.a = parent.b
+join ref_child as c8 on c8.a = parent.b
+join ref_child as c9 on c9.a = parent.b
+join ref_child as c10 on c10.a = parent.b
+join ref_child as c11 on c11.a = parent.b
+join ref_child as c12 on c12.a = parent.b
+join ref_child as c13 on c13.a = parent.b
+join ref_child as c14 on c14.a = parent.b
+join ref_child as c15 on c15.a = parent.b
+join ref_child as c16 on c16.a = parent.b
+where parent.a < 1000
+;
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join ref_child as c2 on c2.a = parent.b
+join ref_child as c3 on c3.a = parent.b
+join ref_child as c4 on c4.a = parent.b
+join ref_child as c5 on c5.a = parent.b
+join ref_child as c6 on c6.a = parent.b
+join ref_child as c7 on c7.a = parent.b
+join ref_child as c8 on c8.a = parent.b
+join ref_child as c9 on c9.a = parent.b
+join ref_child as c10 on c10.a = parent.b
+join ref_child as c11 on c11.a = parent.b
+join ref_child as c12 on c12.a = parent.b
+join ref_child as c13 on c13.a = parent.b
+join ref_child as c14 on c14.a = parent.b
+join ref_child as c15 on c15.a = parent.b
+join ref_child as c16 on c16.a = parent.b
+where parent.a < 1000
+;
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join ref_child as c2 on c2.a = parent.b
+join ref_child as c3 on c3.a = parent.b
+join ref_child as c4 on c4.a = parent.b
+join ref_child as c5 on c5.a = parent.b
+join ref_child as c6 on c6.a = parent.b
+join ref_child as c7 on c7.a = parent.b
+join ref_child as c8 on c8.a = parent.b
+join ref_child as c9 on c9.a = parent.b
+join ref_child as c10 on c10.a = parent.b
+join ref_child as c11 on c11.a = parent.b
+join ref_child as c12 on c12.a = parent.b
+join ref_child as c13 on c13.a = parent.b
+join ref_child as c14 on c14.a = parent.b
+join ref_child as c15 on c15.a = parent.b
+join ref_child as c16 on c16.a = parent.b
+where parent.a < 1000
+;
+Await completion or failure
+count(*)
+999
+count(*)
+999
+count(*)
+999
+=================================
+Run multiple 'query4' in parallel 
+=================================
+explain select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join eq_child as c1eq on c1eq.a = c1.a and c1eq.b = c1.b
+join ref_child as c2 on c2.a = parent.b
+join eq_child as c2eq on c2eq.a = c2.a and c2eq.b = c2.b
+join ref_child as c3 on c3.a = parent.b
+join eq_child as c3eq on c3eq.a = c3.a and c3eq.b = c3.b
+join ref_child as c4 on c4.a = parent.b
+join eq_child as c4eq on c4eq.a = c4.a and c4eq.b = c4.b
+join ref_child as c5 on c5.a = parent.b
+join eq_child as c5eq on c5eq.a = c5.a and c5eq.b = c5.b
+join ref_child as c6 on c6.a = parent.b
+join eq_child as c6eq on c6eq.a = c6.a and c6eq.b = c6.b
+join ref_child as c7 on c7.a = parent.b
+join eq_child as c7eq on c7eq.a = c7.a and c7eq.b = c7.b
+join ref_child as c8 on c8.a = parent.b
+join eq_child as c8eq on c8eq.a = c8.a and c8eq.b = c8.b
+join ref_child as c9 on c9.a = parent.b
+join eq_child as c9eq on c9eq.a = c9.a and c9eq.b = c9.b
+join ref_child as c10 on c10.a = parent.b
+join eq_child as c10eq on c10eq.a = c10.a and c10eq.b = c10.b
+join ref_child as c11 on c11.a = parent.b
+join eq_child as c11eq on c11eq.a = c11.a and c11eq.b = c11.b
+join ref_child as c12 on c12.a = parent.b
+join eq_child as c12eq on c12eq.a = c12.a and c12eq.b = c12.b
+join ref_child as c13 on c13.a = parent.b
+join eq_child as c13eq on c13eq.a = c13.a and c13eq.b = c13.b
+join ref_child as c14 on c14.a = parent.b
+join eq_child as c14eq on c14eq.a = c14.a and c14eq.b = c14.b
+join ref_child as c15 on c15.a = parent.b
+join eq_child as c15eq on c15eq.a = c15.a and c15eq.b = c15.b
+join ref_child as c16 on c16.a = parent.b
+join eq_child as c16eq on c16eq.a = c16.a and c16eq.b = c16.b
+where parent.a < 1000
+;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	parent	range	PRIMARY	PRIMARY	4	NULL	1104	Parent of 32 pushed join@1; Using where with pushed condition
+1	SIMPLE	c1	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c1eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c1.b	1	Child of 'c1' in pushed join@1
+1	SIMPLE	c2	ref	PRIMARY	PRIMARY	4	test.c1.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c2eq	eq_ref	PRIMARY	PRIMARY	8	test.c2.a,test.c2.b	1	Child of 'c2' in pushed join@1; Using where
+1	SIMPLE	c3	ref	PRIMARY	PRIMARY	4	test.c2.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c3eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c3.b	1	Child of 'c3' in pushed join@1
+1	SIMPLE	c4	ref	PRIMARY	PRIMARY	4	test.c3.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c4eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c4.b	1	Child of 'c4' in pushed join@1
+1	SIMPLE	c5	ref	PRIMARY	PRIMARY	4	test.c4.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c5eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c5.b	1	Child of 'c5' in pushed join@1
+1	SIMPLE	c6	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c6eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c6.b	1	Child of 'c6' in pushed join@1
+1	SIMPLE	c7	ref	PRIMARY	PRIMARY	4	test.c5eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c7eq	eq_ref	PRIMARY	PRIMARY	8	test.c6.a,test.c7.b	1	Child of 'c7' in pushed join@1; Using where
+1	SIMPLE	c8	ref	PRIMARY	PRIMARY	4	test.c6eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c8eq	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c8.b	1	Child of 'c8' in pushed join@1; Using where
+1	SIMPLE	c9	ref	PRIMARY	PRIMARY	4	test.c6eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c9eq	eq_ref	PRIMARY	PRIMARY	8	test.c2eq.a,test.c9.b	1	Child of 'c9' in pushed join@1; Using where
+1	SIMPLE	c10	ref	PRIMARY	PRIMARY	4	test.c7.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c10eq	eq_ref	PRIMARY	PRIMARY	8	test.c7eq.a,test.c10.b	1	Child of 'c10' in pushed join@1; Using where
+1	SIMPLE	c11	ref	PRIMARY	PRIMARY	4	test.c7.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c11eq	eq_ref	PRIMARY	PRIMARY	8	test.parent.b,test.c11.b	1	Child of 'c11' in pushed join@1
+1	SIMPLE	c12	ref	PRIMARY	PRIMARY	4	test.c8eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c12eq	eq_ref	PRIMARY	PRIMARY	8	test.c7.a,test.c12.b	1	Child of 'c12' in pushed join@1; Using where
+1	SIMPLE	c13	ref	PRIMARY	PRIMARY	4	test.c6eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c13eq	eq_ref	PRIMARY	PRIMARY	8	test.c6.a,test.c13.b	1	Child of 'c13' in pushed join@1; Using where
+1	SIMPLE	c14	ref	PRIMARY	PRIMARY	4	test.c5.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c14eq	eq_ref	PRIMARY	PRIMARY	8	test.c5eq.a,test.c14.b	1	Child of 'c14' in pushed join@1; Using where
+1	SIMPLE	c15	ref	PRIMARY	PRIMARY	4	test.c1eq.a	54	Child of 'parent' in pushed join@1; Using where
+1	SIMPLE	c15eq	eq_ref	PRIMARY	PRIMARY	8	test.c15.a,test.c15.b	1	Child of 'c15' in pushed join@1; Using where
+1	SIMPLE	c16	ref	PRIMARY	PRIMARY	4	test.parent.b	54	Child of 'parent' in pushed join@1
+1	SIMPLE	c16eq	eq_ref	PRIMARY	PRIMARY	8	test.c5.a,test.c16.b	1	Using where
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join eq_child as c1eq on c1eq.a = c1.a and c1eq.b = c1.b
+join ref_child as c2 on c2.a = parent.b
+join eq_child as c2eq on c2eq.a = c2.a and c2eq.b = c2.b
+join ref_child as c3 on c3.a = parent.b
+join eq_child as c3eq on c3eq.a = c3.a and c3eq.b = c3.b
+join ref_child as c4 on c4.a = parent.b
+join eq_child as c4eq on c4eq.a = c4.a and c4eq.b = c4.b
+join ref_child as c5 on c5.a = parent.b
+join eq_child as c5eq on c5eq.a = c5.a and c5eq.b = c5.b
+join ref_child as c6 on c6.a = parent.b
+join eq_child as c6eq on c6eq.a = c6.a and c6eq.b = c6.b
+join ref_child as c7 on c7.a = parent.b
+join eq_child as c7eq on c7eq.a = c7.a and c7eq.b = c7.b
+join ref_child as c8 on c8.a = parent.b
+join eq_child as c8eq on c8eq.a = c8.a and c8eq.b = c8.b
+join ref_child as c9 on c9.a = parent.b
+join eq_child as c9eq on c9eq.a = c9.a and c9eq.b = c9.b
+join ref_child as c10 on c10.a = parent.b
+join eq_child as c10eq on c10eq.a = c10.a and c10eq.b = c10.b
+join ref_child as c11 on c11.a = parent.b
+join eq_child as c11eq on c11eq.a = c11.a and c11eq.b = c11.b
+join ref_child as c12 on c12.a = parent.b
+join eq_child as c12eq on c12eq.a = c12.a and c12eq.b = c12.b
+join ref_child as c13 on c13.a = parent.b
+join eq_child as c13eq on c13eq.a = c13.a and c13eq.b = c13.b
+join ref_child as c14 on c14.a = parent.b
+join eq_child as c14eq on c14eq.a = c14.a and c14eq.b = c14.b
+join ref_child as c15 on c15.a = parent.b
+join eq_child as c15eq on c15eq.a = c15.a and c15eq.b = c15.b
+join ref_child as c16 on c16.a = parent.b
+join eq_child as c16eq on c16eq.a = c16.a and c16eq.b = c16.b
+where parent.a < 1000
+;
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join eq_child as c1eq on c1eq.a = c1.a and c1eq.b = c1.b
+join ref_child as c2 on c2.a = parent.b
+join eq_child as c2eq on c2eq.a = c2.a and c2eq.b = c2.b
+join ref_child as c3 on c3.a = parent.b
+join eq_child as c3eq on c3eq.a = c3.a and c3eq.b = c3.b
+join ref_child as c4 on c4.a = parent.b
+join eq_child as c4eq on c4eq.a = c4.a and c4eq.b = c4.b
+join ref_child as c5 on c5.a = parent.b
+join eq_child as c5eq on c5eq.a = c5.a and c5eq.b = c5.b
+join ref_child as c6 on c6.a = parent.b
+join eq_child as c6eq on c6eq.a = c6.a and c6eq.b = c6.b
+join ref_child as c7 on c7.a = parent.b
+join eq_child as c7eq on c7eq.a = c7.a and c7eq.b = c7.b
+join ref_child as c8 on c8.a = parent.b
+join eq_child as c8eq on c8eq.a = c8.a and c8eq.b = c8.b
+join ref_child as c9 on c9.a = parent.b
+join eq_child as c9eq on c9eq.a = c9.a and c9eq.b = c9.b
+join ref_child as c10 on c10.a = parent.b
+join eq_child as c10eq on c10eq.a = c10.a and c10eq.b = c10.b
+join ref_child as c11 on c11.a = parent.b
+join eq_child as c11eq on c11eq.a = c11.a and c11eq.b = c11.b
+join ref_child as c12 on c12.a = parent.b
+join eq_child as c12eq on c12eq.a = c12.a and c12eq.b = c12.b
+join ref_child as c13 on c13.a = parent.b
+join eq_child as c13eq on c13eq.a = c13.a and c13eq.b = c13.b
+join ref_child as c14 on c14.a = parent.b
+join eq_child as c14eq on c14eq.a = c14.a and c14eq.b = c14.b
+join ref_child as c15 on c15.a = parent.b
+join eq_child as c15eq on c15eq.a = c15.a and c15eq.b = c15.b
+join ref_child as c16 on c16.a = parent.b
+join eq_child as c16eq on c16eq.a = c16.a and c16eq.b = c16.b
+where parent.a < 1000
+;
+select straight_join count(*) from parent
+join ref_child as c1 on c1.a = parent.b
+join eq_child as c1eq on c1eq.a = c1.a and c1eq.b = c1.b
+join ref_child as c2 on c2.a = parent.b
+join eq_child as c2eq on c2eq.a = c2.a and c2eq.b = c2.b
+join ref_child as c3 on c3.a = parent.b
+join eq_child as c3eq on c3eq.a = c3.a and c3eq.b = c3.b
+join ref_child as c4 on c4.a = parent.b
+join eq_child as c4eq on c4eq.a = c4.a and c4eq.b = c4.b
+join ref_child as c5 on c5.a = parent.b
+join eq_child as c5eq on c5eq.a = c5.a and c5eq.b = c5.b
+join ref_child as c6 on c6.a = parent.b
+join eq_child as c6eq on c6eq.a = c6.a and c6eq.b = c6.b
+join ref_child as c7 on c7.a = parent.b
+join eq_child as c7eq on c7eq.a = c7.a and c7eq.b = c7.b
+join ref_child as c8 on c8.a = parent.b
+join eq_child as c8eq on c8eq.a = c8.a and c8eq.b = c8.b
+join ref_child as c9 on c9.a = parent.b
+join eq_child as c9eq on c9eq.a = c9.a and c9eq.b = c9.b
+join ref_child as c10 on c10.a = parent.b
+join eq_child as c10eq on c10eq.a = c10.a and c10eq.b = c10.b
+join ref_child as c11 on c11.a = parent.b
+join eq_child as c11eq on c11eq.a = c11.a and c11eq.b = c11.b
+join ref_child as c12 on c12.a = parent.b
+join eq_child as c12eq on c12eq.a = c12.a and c12eq.b = c12.b
+join ref_child as c13 on c13.a = parent.b
+join eq_child as c13eq on c13eq.a = c13.a and c13eq.b = c13.b
+join ref_child as c14 on c14.a = parent.b
+join eq_child as c14eq on c14eq.a = c14.a and c14eq.b = c14.b
+join ref_child as c15 on c15.a = parent.b
+join eq_child as c15eq on c15eq.a = c15.a and c15eq.b = c15.b
+join ref_child as c16 on c16.a = parent.b
+join eq_child as c16eq on c16eq.a = c16.a and c16eq.b = c16.b
+where parent.a < 1000
+;
+Await completion or failure
+count(*)
+999
+count(*)
+999
+count(*)
+999
+drop table parent, eq_child, ref_child;

=== modified file 'mysql-test/suite/ndb/r/ndb_condition_pushdown.result'
--- a/mysql-test/suite/ndb/r/ndb_condition_pushdown.result	2012-06-11 10:56:04 +0000
+++ b/mysql-test/suite/ndb/r/ndb_condition_pushdown.result	2012-11-13 10:27:06 +0000
@@ -2233,8 +2233,8 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	tx	ALL	PRIMARY	NULL	NULL	NULL	2	100.00	Parent of 4 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.tx.a,test.tx.b	1	100.00	Child of 'tx' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.tx.c,test.tx.d	1	100.00	Child of 'tx' in pushed join@1
-1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.tx.d,test.t2.c	1	100.00	Child of 't2' in pushed join@1
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.tx.c,test.tx.d	1	100.00	Child of 't2' in pushed join@1
+1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.tx.d,test.t2.c	1	100.00	Child of 't3' in pushed join@1
 Warnings:
 Note	1003	select straight_join `test`.`tx`.`a` AS `a`,`test`.`tx`.`b` AS `b`,`test`.`tx`.`c` AS `c`,`test`.`tx`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c`,`test`.`t4`.`d` AS `d` from `test`.`tx` join `test`.`tx` `t2` join `test`.`tx` `t3` join `test`.`tx` `t4` where ((`test`.`t2`.`b` = `test`.`tx`.`b`) and (`test`.`t2`.`a` = `test`.`tx`.`a`) and (`test`.`t3`.`a` = `test`.`tx`.`c`) and (`test`.`t4`.`b` = `test`.`t2`.`c`) and (`test`.`t3`.`b` = `test`.`tx`.`d`) and (`test`.`t4`.`a` = `test`.`tx`.`d`))
 explain extended

=== modified file 'mysql-test/suite/ndb/r/ndb_join_pushdown_default.result'
--- a/mysql-test/suite/ndb/r/ndb_join_pushdown_default.result	2012-09-21 07:24:28 +0000
+++ b/mysql-test/suite/ndb/r/ndb_join_pushdown_default.result	2012-11-13 10:27:06 +0000
@@ -167,11 +167,30 @@
 select *
 from t1
 join t1 as t2 on t2.a = t1.b and t2.b = t1.c
+join t1 as t3 on t3.a = t2.a and t3.b = t2.b
+where t1.a = 1 and t1.b = 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
+1	SIMPLE	t1	eq_ref	PRIMARY	PRIMARY	8	const,const	1	100.00	Parent of 3 pushed join@1
+1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	const,test.t1.c	1	100.00	Child of 't1' in pushed join@1
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	const,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
+Warnings:
+Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t1`.`b` = 1) and (`test`.`t2`.`a` = 1) and (`test`.`t3`.`a` = 1) and (`test`.`t1`.`a` = 1))
+select *
+from t1
+join t1 as t2 on t2.a = t1.b and t2.b = t1.c
+join t1 as t3 on t3.a = t2.a and t3.b = t2.b
+where t1.a = 1 and t1.b = 1;
+a	b	c	d	a	b	c	d	a	b	c	d
+1	1	1	1	1	1	1	1	1	1	1	1
+explain extended
+select *
+from t1
+join t1 as t2 on t2.a = t1.b and t2.b = t1.c
 join t1 as t3 on t3.a = t2.a and t3.b = t2.b;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`))
 select *
@@ -200,7 +219,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t2.a,test.t2.b	1	100.00	Child of 't1' in pushed join@1
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t2.a,test.t2.b	1	100.00	Child of 't2' in pushed join@1
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` left join `test`.`t1` `t3` on(((`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`a` = `test`.`t1`.`b`))) where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`))
 select *
@@ -1218,8 +1237,8 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	16	100.00	Parent of 4 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.a,test.t1.b	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t2.c	1	100.00	Child of 't2' in pushed join@1
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't2' in pushed join@1
+1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t2.c	1	100.00	Child of 't3' in pushed join@1
 Warnings:
 Note	1003	select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c`,`test`.`t4`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` join `test`.`t1` `t4` where ((`test`.`t2`.`b` = `test`.`t1`.`b`) and (`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t3`.`b` = `test`.`t1`.`d`) and (`test`.`t4`.`b` = `test`.`t2`.`c`) and (`test`.`t3`.`a` = `test`.`t1`.`c`) and (`test`.`t4`.`a` = `test`.`t1`.`c`))
 select straight_join *
@@ -1248,8 +1267,8 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	16	100.00	Parent of 4 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.a,test.t1.b	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t1.d,test.t2.c	1	100.00	Child of 't2' in pushed join@1
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't2' in pushed join@1
+1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t1.d,test.t2.c	1	100.00	Child of 't3' in pushed join@1
 Warnings:
 Note	1003	select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c`,`test`.`t4`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` join `test`.`t1` `t4` where ((`test`.`t2`.`b` = `test`.`t1`.`b`) and (`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t3`.`a` = `test`.`t1`.`c`) and (`test`.`t4`.`b` = `test`.`t2`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`d`) and (`test`.`t4`.`a` = `test`.`t1`.`d`))
 select straight_join *
@@ -1332,8 +1351,8 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	16	100.00	Parent of 4 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.a,test.t1.b	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t3.a,test.t2.c	1	100.00	Child of 't2' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't2' in pushed join@1
+1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t3.a,test.t2.c	1	100.00	Child of 't3' in pushed join@1; Using where
 Warnings:
 Note	1003	select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c`,`test`.`t4`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` join `test`.`t1` `t4` where ((`test`.`t2`.`b` = `test`.`t1`.`b`) and (`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t3`.`b` = `test`.`t1`.`d`) and (`test`.`t4`.`b` = `test`.`t2`.`c`) and (`test`.`t3`.`a` = `test`.`t1`.`c`) and (`test`.`t4`.`a` = `test`.`t1`.`c`))
 select straight_join *
@@ -1441,8 +1460,8 @@
 1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	16	100.00	Parent of 6 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.a,test.t1.b	1	100.00	Child of 't1' in pushed join@1
 1	SIMPLE	t2x	eq_ref	PRIMARY	PRIMARY	8	test.t2.c,test.t2.d	1	100.00	Child of 't2' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3x	eq_ref	PRIMARY	PRIMARY	8	test.t3.a,test.t3.b	1	100.00	Child of 't2x' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t1.d	1	100.00	Child of 't2x' in pushed join@1
+1	SIMPLE	t3x	eq_ref	PRIMARY	PRIMARY	8	test.t3.a,test.t3.b	1	100.00	Child of 't3' in pushed join@1; Using where
 1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t3x.c,test.t2x.c	1	100.00	Child of 't3x' in pushed join@1
 Warnings:
 Note	1003	select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t2x`.`a` AS `a`,`test`.`t2x`.`b` AS `b`,`test`.`t2x`.`c` AS `c`,`test`.`t2x`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d`,`test`.`t3x`.`a` AS `a`,`test`.`t3x`.`b` AS `b`,`test`.`t3x`.`c` AS `c`,`test`.`t3x`.`d` AS `d`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c`,`test`.`t4`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t2x` join `test`.`t1` `t3` join `test`.`t1` `t3x` join `test`.`t1` `t4` where ((`test`.`t2`.`b` = `test`.`t1`.`b`) and (`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t2x`.`b` = `test`.`t2`.`d`) and (`test`.`t2x`.`a` = `test`.`t2`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`d`) and (`test`.`t3x`.`b` = `test`.`t1`.`d`) and (`test`.`t3`.`a` = `test`.`t1`.`c`) and (`test`.`t3x`.`a` = `test`.`t1`.`c`) and (`test`.`t4`.`b` = `test`.`t2x`.`c`) and (`test`.`t4`.`a` = `test`.`t3x`.`c`))
@@ -1458,8 +1477,8 @@
 1	SIMPLE	t1	ALL	PRIMARY	NULL	NULL	NULL	16	100.00	Parent of 6 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.a,test.t1.b	1	100.00	Child of 't1' in pushed join@1
 1	SIMPLE	t2x	eq_ref	PRIMARY	PRIMARY	8	test.t2.c,test.t2.d	1	100.00	Child of 't2' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
-1	SIMPLE	t3x	eq_ref	PRIMARY	PRIMARY	8	test.t3.a,test.t1.d	1	100.00	Child of 't2x' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.c,test.t2.b	1	100.00	Child of 't2x' in pushed join@1; Using where
+1	SIMPLE	t3x	eq_ref	PRIMARY	PRIMARY	8	test.t3.a,test.t1.d	1	100.00	Child of 't3' in pushed join@1; Using where
 1	SIMPLE	t4	eq_ref	PRIMARY	PRIMARY	8	test.t3x.c,test.t2x.c	1	100.00	Child of 't3x' in pushed join@1
 Warnings:
 Note	1003	select straight_join `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t2x`.`a` AS `a`,`test`.`t2x`.`b` AS `b`,`test`.`t2x`.`c` AS `c`,`test`.`t2x`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d`,`test`.`t3x`.`a` AS `a`,`test`.`t3x`.`b` AS `b`,`test`.`t3x`.`c` AS `c`,`test`.`t3x`.`d` AS `d`,`test`.`t4`.`a` AS `a`,`test`.`t4`.`b` AS `b`,`test`.`t4`.`c` AS `c`,`test`.`t4`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t2x` join `test`.`t1` `t3` join `test`.`t1` `t3x` join `test`.`t1` `t4` where ((`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t2x`.`b` = `test`.`t2`.`d`) and (`test`.`t2x`.`a` = `test`.`t2`.`c`) and (`test`.`t2`.`b` = `test`.`t1`.`b`) and (`test`.`t3`.`b` = `test`.`t1`.`b`) and (`test`.`t3x`.`b` = `test`.`t1`.`d`) and (`test`.`t3`.`a` = `test`.`t1`.`c`) and (`test`.`t3x`.`a` = `test`.`t1`.`c`) and (`test`.`t4`.`b` = `test`.`t2x`.`c`) and (`test`.`t4`.`a` = `test`.`t3x`.`c`))
@@ -1730,7 +1749,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1; Using temporary; Using filesort
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`c`,`test`.`t1`.`d`,`test`.`t1`.`a`,`test`.`t1`.`b`
 select *
@@ -1763,7 +1782,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1; Using temporary; Using filesort
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`c`,`test`.`t2`.`d`,`test`.`t1`.`a`,`test`.`t1`.`b`
 select *
@@ -1795,7 +1814,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	NULL	PRIMARY	8	NULL	16	100.00	Parent of 3 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`a`,`test`.`t1`.`b`
 select *
@@ -1827,7 +1846,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1; Using temporary; Using filesort
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`a`,`test`.`t2`.`b`,`test`.`t1`.`a`,`test`.`t1`.`b`
 select *
@@ -1859,7 +1878,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	NULL	PRIMARY	8	NULL	16	100.00	Parent of 3 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`a` desc,`test`.`t1`.`b` desc
 select *
@@ -1890,7 +1909,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1; Using temporary; Using filesort
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`b`,`test`.`t1`.`a`
 select *
@@ -1921,7 +1940,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	NULL	PRIMARY	8	NULL	16	100.00	Parent of 3 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`a`
 explain extended
@@ -1933,7 +1952,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1; Using temporary; Using filesort
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,`test`.`t1`.`d` AS `d`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c`,`test`.`t2`.`d` AS `d`,`test`.`t3`.`a` AS `a`,`test`.`t3`.`b` AS `b`,`test`.`t3`.`c` AS `c`,`test`.`t3`.`d` AS `d` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) order by `test`.`t1`.`b`
 explain extended
@@ -1945,7 +1964,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	NULL	PRIMARY	8	NULL	16	100.00	Parent of 3 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) group by `test`.`t1`.`a`,`test`.`t1`.`b`
 select t1.a, t1.b, count(*)
@@ -1976,7 +1995,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	index	NULL	PRIMARY	8	NULL	16	100.00	Parent of 3 pushed join@1
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`a` AS `a`,count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) group by `test`.`t1`.`a`
 select t1.a, count(*)
@@ -1998,7 +2017,7 @@
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	16	100.00	Parent of 3 pushed join@1; Using temporary; Using filesort
 1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t1.c	1	100.00	Child of 't1' in pushed join@1
-1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't1' in pushed join@1; Using where
+1	SIMPLE	t3	eq_ref	PRIMARY	PRIMARY	8	test.t1.b,test.t2.b	1	100.00	Child of 't2' in pushed join@1; Using where
 Warnings:
 Note	1003	select `test`.`t1`.`b` AS `b`,count(0) AS `count(*)` from `test`.`t1` join `test`.`t1` `t2` join `test`.`t1` `t3` where ((`test`.`t2`.`b` = `test`.`t1`.`c`) and (`test`.`t3`.`b` = `test`.`t1`.`c`) and (`test`.`t2`.`a` = `test`.`t1`.`b`) and (`test`.`t3`.`a` = `test`.`t1`.`b`)) group by `test`.`t1`.`b`
 select t1.b, count(*)
@@ -5774,7 +5793,7 @@
 LOCAL_TABLE_SCANS_SENT	254
 PRUNED_RANGE_SCANS_RECEIVED	27
 RANGE_SCANS_RECEIVED	738
-READS_RECEIVED	48
+READS_RECEIVED	49
 TABLE_SCANS_RECEIVED	254
 drop table spj_counts_at_startup;
 drop table spj_counts_at_end;
@@ -5785,9 +5804,9 @@
 order by new.variable_name;
 variable_name	new.variable_value - old.variable_value
 NDB_PRUNED_SCAN_COUNT	8
-NDB_PUSHED_QUERIES_DEFINED	411
+NDB_PUSHED_QUERIES_DEFINED	413
 NDB_PUSHED_QUERIES_DROPPED	9
-NDB_PUSHED_QUERIES_EXECUTED	541
+NDB_PUSHED_QUERIES_EXECUTED	542
 NDB_SORTED_SCAN_COUNT	11
 drop table server_counts_at_startup;
 set ndb_join_pushdown = @save_ndb_join_pushdown;

=== added file 'mysql-test/suite/ndb/t/ndb_bushy_joins.cnf'
--- a/mysql-test/suite/ndb/t/ndb_bushy_joins.cnf	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_bushy_joins.cnf	2012-11-13 10:27:06 +0000
@@ -0,0 +1,22 @@
+!include suite/ndb/my.cnf
+
+[cluster_config]
+######
+# Increase #LDM threads such that tables
+# can be created with many partitions (> 8)
+# Max: #nodes * #LDM * NoOfFragmentLogParts / NoOfReplicas
+######
+ThreadConfig=ldm={count=4}
+
+######
+# Tune some more  configs as test load is 
+# expected to really strain the system.
+######
+MaxNoOfConcurrentOperations=250000
+LongMessageBuffer=64M
+TransactionDeadlockDetectionTimeout=30000
+
+[ENV]
+# Need to always use ndbmtd when we want lots of partitions
+# (Avoid mixed 'round robin' use of mt / non-mt) 
+MTR_NDBMTD= 1

=== added file 'mysql-test/suite/ndb/t/ndb_bushy_joins.test'
--- a/mysql-test/suite/ndb/t/ndb_bushy_joins.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_bushy_joins.test	2012-11-13 10:27:06 +0000
@@ -0,0 +1,270 @@
+########################################################
+# ndb_bushy_joins.test
+#
+# This test is intended to check system behaviour when SPJ
+# executes large bushy-joins, aka 'star-joins' -> joins with
+# multiple childs being dependent on the same parent.
+#
+# These types of joins has previously caused 
+# job buffer overflow as too many requests was
+# sent in parallel from the SPJ block.
+# (bug#14709490)
+########################################################
+
+-- source include/have_ndb.inc
+-- source include/have_multi_ndb.inc
+
+connect (ddl,localhost,root,,test);
+connect (j1,localhost,root,,test);
+connect (j2,localhost,root,,test);
+connect (j3,localhost,root,,test);
+
+connection ddl;
+
+create table parent(a int primary key, b int, c int, d int) engine=ndb;
+create table eq_child(a int, b int, c int, d int, primary key(a,b)) engine=ndb;
+create table ref_child(a int, b int, c int, d int, primary key(a,b)) engine=ndb;
+
+alter table parent partition by key(a) partitions 32;
+alter table eq_child  partition by key(a) partitions 32;
+alter table ref_child  partition by key(a) partitions 32;
+
+insert into parent values (1,1,1,1);
+
+let $factor = 1;
+let $loops = 13;
+
+# Fill tables with 2^loops rows
+while ($loops)
+{
+  eval insert into parent select a+$factor, b+$factor, c+$factor, d+$factor  from parent;
+  let $factor = $factor*2;
+  dec $loops;
+}
+select count(*) from parent;
+
+insert into eq_child select * from parent;
+insert into ref_child select * from parent;
+
+# Cheat statistics: update rows actually not refered in joins below
+# (Cheat required in order to make 'ref-joins' bushy)
+update ref_child set a = a-(a%16) where a > 4000;
+
+analyze table parent, eq_child, ref_child;
+
+let $query1 =
+ select straight_join count(*) from parent
+ join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+ join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+ join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+ join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+ join eq_child as c5 on c5.a = parent.b and c5.b = parent.b
+ join eq_child as c6 on c6.a = parent.b and c6.b = parent.b
+ join eq_child as c7 on c7.a = parent.b and c7.b = parent.b
+ join eq_child as c8 on c8.a = parent.b and c8.b = parent.b
+ join eq_child as c9 on c9.a = parent.b and c9.b = parent.b
+ join eq_child as c10 on c10.a = parent.b and c10.b = parent.b
+ join eq_child as c11 on c11.a = parent.b and c11.b = parent.b
+ join eq_child as c12 on c12.a = parent.b and c12.b = parent.b
+ join eq_child as c13 on c13.a = parent.b and c13.b = parent.b
+ join eq_child as c14 on c14.a = parent.b and c14.b = parent.b
+ join eq_child as c15 on c15.a = parent.b and c15.b = parent.b
+ join eq_child as c16 on c16.a = parent.b and c16.b = parent.b
+;
+
+let $query2 =
+ select straight_join count(*) from parent
+ join eq_child as c1 on c1.a = parent.b and c1.b = parent.b
+   join eq_child as c5 on c5.a = c1.c and c5.b = c1.c
+   join eq_child as c6 on c6.a = c1.c and c6.b = c1.c
+   join eq_child as c7 on c7.a = c1.c and c7.b = c1.c
+   join eq_child as c8 on c8.a = c1.c and c8.b = c1.c
+ join eq_child as c2 on c2.a = parent.b and c2.b = parent.b
+   join eq_child as c9  on c9.a = c2.c  and c9.b  = c2.c
+   join eq_child as c10 on c10.a = c2.c and c10.b = c2.c
+   join eq_child as c11 on c11.a = c2.c and c11.b = c2.c
+   join eq_child as c12 on c12.a = c2.c and c12.b = c2.c
+ join eq_child as c3 on c3.a = parent.b and c3.b = parent.b
+   join eq_child as c13 on c13.a = c3.c and c13.b = c3.c
+   join eq_child as c14 on c14.a = c3.c and c14.b = c3.c
+   join eq_child as c15 on c15.a = c3.c and c15.b = c3.c
+   join eq_child as c16 on c16.a = c3.c and c16.b = c3.c
+ join eq_child as c4 on c4.a = parent.b and c4.b = parent.b
+   join eq_child as c17 on c17.a = c4.c and c17.b = c4.c
+   join eq_child as c18 on c18.a = c4.c and c18.b = c4.c
+   join eq_child as c19 on c19.a = c4.c and c19.b = c4.c
+   join eq_child as c20 on c20.a = c4.c and c20.b = c4.c
+;
+
+let $query3 =
+ select straight_join count(*) from parent
+ join ref_child as c1 on c1.a = parent.b
+ join ref_child as c2 on c2.a = parent.b
+ join ref_child as c3 on c3.a = parent.b
+ join ref_child as c4 on c4.a = parent.b
+ join ref_child as c5 on c5.a = parent.b
+ join ref_child as c6 on c6.a = parent.b
+ join ref_child as c7 on c7.a = parent.b
+ join ref_child as c8 on c8.a = parent.b
+ join ref_child as c9 on c9.a = parent.b
+ join ref_child as c10 on c10.a = parent.b
+ join ref_child as c11 on c11.a = parent.b
+ join ref_child as c12 on c12.a = parent.b
+ join ref_child as c13 on c13.a = parent.b
+ join ref_child as c14 on c14.a = parent.b
+ join ref_child as c15 on c15.a = parent.b
+ join ref_child as c16 on c16.a = parent.b
+ where parent.a < 1000
+;
+
+let $query4 =
+ select straight_join count(*) from parent
+ join ref_child as c1 on c1.a = parent.b
+   join eq_child as c1eq on c1eq.a = c1.a and c1eq.b = c1.b
+ join ref_child as c2 on c2.a = parent.b
+   join eq_child as c2eq on c2eq.a = c2.a and c2eq.b = c2.b
+ join ref_child as c3 on c3.a = parent.b
+   join eq_child as c3eq on c3eq.a = c3.a and c3eq.b = c3.b
+ join ref_child as c4 on c4.a = parent.b
+   join eq_child as c4eq on c4eq.a = c4.a and c4eq.b = c4.b
+ join ref_child as c5 on c5.a = parent.b
+   join eq_child as c5eq on c5eq.a = c5.a and c5eq.b = c5.b
+ join ref_child as c6 on c6.a = parent.b
+   join eq_child as c6eq on c6eq.a = c6.a and c6eq.b = c6.b
+ join ref_child as c7 on c7.a = parent.b
+   join eq_child as c7eq on c7eq.a = c7.a and c7eq.b = c7.b
+ join ref_child as c8 on c8.a = parent.b
+   join eq_child as c8eq on c8eq.a = c8.a and c8eq.b = c8.b
+ join ref_child as c9 on c9.a = parent.b
+   join eq_child as c9eq on c9eq.a = c9.a and c9eq.b = c9.b
+ join ref_child as c10 on c10.a = parent.b
+   join eq_child as c10eq on c10eq.a = c10.a and c10eq.b = c10.b
+ join ref_child as c11 on c11.a = parent.b
+   join eq_child as c11eq on c11eq.a = c11.a and c11eq.b = c11.b
+ join ref_child as c12 on c12.a = parent.b
+   join eq_child as c12eq on c12eq.a = c12.a and c12eq.b = c12.b
+ join ref_child as c13 on c13.a = parent.b
+   join eq_child as c13eq on c13eq.a = c13.a and c13eq.b = c13.b
+ join ref_child as c14 on c14.a = parent.b
+   join eq_child as c14eq on c14eq.a = c14.a and c14eq.b = c14.b
+ join ref_child as c15 on c15.a = parent.b
+   join eq_child as c15eq on c15eq.a = c15.a and c15eq.b = c15.b
+ join ref_child as c16 on c16.a = parent.b
+   join eq_child as c16eq on c16eq.a = c16.a and c16eq.b = c16.b
+ where parent.a < 1000
+;
+
+connection j1;
+set ndb_join_pushdown = on;
+
+call mtr.add_suppression("starting connect thread");
+
+-- echo ===============================
+-- echo Run single instance of 'query1' 
+-- echo ===============================
+eval explain $query1;
+eval $query1;
+
+-- echo ===============================
+-- echo Run single instance of 'query2' 
+-- echo ===============================
+eval explain $query2;
+eval $query2;
+
+-- echo ===============================
+-- echo Run single instance of 'query3' 
+-- echo ===============================
+eval explain $query3;
+eval $query3;
+
+-- echo ===============================
+-- echo Run single instance of 'query4' 
+-- echo ===============================
+eval explain $query4;
+eval $query4;
+
+
+-- echo =================================
+-- echo Run multiple 'query1' in parallel 
+-- echo =================================
+let $query = $query1;
+eval explain $query;
+connection j1;
+send_eval $query;
+connection j2;
+send_eval $query;
+connection j3;
+send_eval $query;
+
+-- echo Await completion or failure
+connection j1;
+reap;
+connection j2;
+reap;
+connection j3;
+reap;
+
+-- echo =================================
+-- echo Run multiple 'query2' in parallel 
+-- echo =================================
+let $query = $query2;
+eval explain $query;
+connection j1;
+send_eval $query;
+connection j2;
+send_eval $query;
+connection j3;
+send_eval $query;
+
+-- echo Await completion or failure
+connection j1;
+reap;
+connection j2;
+reap;
+connection j3;
+reap;
+
+-- echo =================================
+-- echo Run multiple 'query3' in parallel 
+-- echo =================================
+let $query = $query3;
+eval explain $query;
+connection j1;
+send_eval $query;
+connection j2;
+send_eval $query;
+connection j3;
+send_eval $query;
+
+-- echo Await completion or failure
+connection j1;
+reap;
+connection j2;
+reap;
+connection j3;
+reap;
+
+-- echo =================================
+-- echo Run multiple 'query4' in parallel 
+-- echo =================================
+let $query = $query4;
+eval explain $query;
+connection j1;
+send_eval $query;
+connection j2;
+send_eval $query;
+connection j3;
+send_eval $query;
+
+-- echo Await completion or failure
+connection j1;
+reap;
+connection j2;
+reap;
+connection j3;
+reap;
+
+
+connection ddl;
+drop table parent, eq_child, ref_child;
+

=== modified file 'mysql-test/suite/ndb/t/ndb_join_pushdown.inc'
--- a/mysql-test/suite/ndb/t/ndb_join_pushdown.inc	2012-09-21 07:24:28 +0000
+++ b/mysql-test/suite/ndb/t/ndb_join_pushdown.inc	2012-11-13 10:27:06 +0000
@@ -109,6 +109,19 @@
 select *
 from t1
 join t1 as t2 on t2.a = t1.b and t2.b = t1.c
+join t1 as t3 on t3.a = t2.a and t3.b = t2.b
+where t1.a = 1 and t1.b = 1;
+--sorted_result
+select *
+from t1
+join t1 as t2 on t2.a = t1.b and t2.b = t1.c
+join t1 as t3 on t3.a = t2.a and t3.b = t2.b
+where t1.a = 1 and t1.b = 1;
+
+explain extended
+select *
+from t1
+join t1 as t2 on t2.a = t1.b and t2.b = t1.c
 join t1 as t3 on t3.a = t2.a and t3.b = t2.b;
 --sorted_result
 select *

=== modified file 'sql/ha_ndbcluster_push.cc'
--- a/sql/ha_ndbcluster_push.cc	2012-06-11 10:56:04 +0000
+++ b/sql/ha_ndbcluster_push.cc	2012-11-13 10:27:06 +0000
@@ -1097,35 +1097,31 @@
     DBUG_ASSERT(!parents.contain(tab_no)); // No circular dependency!
 
     /**
-     * In order to take advantage of the parallelism in the SPJ block; 
+-    * In order to take advantage of the parallelism in the SPJ block;
      * Initial parent candidate is the first possible among 'parents'.
      * Will result in the most 'bushy' query plan (aka: star-join)
      */
     parent_no= parents.first_table(root_no);
 
-    if (table.m_fanout*table.m_child_fanout > 1.0 ||
-        !ndbcluster_is_lookup_operation(m_plan.get_table_access(tab_no)->get_access_type()))
+    /**
+     * Push optimization for execution of child operations:
+     *
+     * To take advantage of the selectivity of parent operations we 
+     * execute any parent operations with fanout <= 1 before this
+     * child operation. By making them depending on parent 
+     * operations with high selectivity, child will be eliminated when
+     * the parent returns no matching rows.
+     *
+     * -> Execute child operation after any such parents
+     */
+    for (uint candidate= parent_no+1; candidate<parents.length(); candidate++)
     {
-      /**
-       * This is a index-scan or lookup with scan childs.
-       * Push optimization for index-scan execute:
-       *
-       * These are relative expensive operation which we try to avoid to 
-       * execute whenever possible. By making them depending on parent 
-       * operations with high selectivity, they will be eliminated when
-       * the parent returns no matching rows.
-       *
-       * -> Execute index-scan after any such parents
-       */
-      for (uint candidate= parent_no+1; candidate<parents.length(); candidate++)
+      if (parents.contain(candidate))
       {
-        if (parents.contain(candidate))
-        {
-          if (m_tables[candidate].m_fanout > 1.0)
-            break;
+        if (m_tables[candidate].m_fanout > 1.0)
+          break;
 
-          parent_no= candidate;     // Parent candidate is selective, eval after
-        }
+        parent_no= candidate;     // Parent candidate is selective, eval after
       }
     }
 

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2012-11-08 12:02:48 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2012-11-13 10:27:06 +0000
@@ -112,6 +112,8 @@
   struct Request;
   struct TreeNode;
   struct ScanFragHandle;
+  typedef DataBuffer2<14, LocalArenaPoolImpl> Correlation_list;
+  typedef LocalDataBuffer2<14, LocalArenaPoolImpl> Local_correlation_list;
   typedef DataBuffer2<14, LocalArenaPoolImpl> Dependency_map;
   typedef LocalDataBuffer2<14, LocalArenaPoolImpl> Local_dependency_map;
   typedef DataBuffer2<14, LocalArenaPoolImpl> PatternStore;
@@ -792,6 +794,28 @@
     Uint32 m_scanFragReq[ScanFragReq::SignalLength + 2];
   };
 
+  struct DeferredParentOps
+  {
+    /**
+     * m_correlations contains a list of Correlation Values (Uint32)
+     * which identifies parent rows which has been deferred. 
+     * m_pos are index into this array, identifying the next parent row
+     * for which to resume operation.
+     */
+    Correlation_list::Head m_correlations;
+    Uint16 m_pos; // Next row operation to resume 
+
+    DeferredParentOps() : m_correlations(), m_pos(0) {}
+
+    void init()  {
+      m_correlations.init();
+      m_pos = 0;
+    }
+    bool isEmpty() const {
+      return (m_pos == m_correlations.getSize());
+    }
+  };
+
   struct TreeNode_cursor_ptr
   {
     Uint32 nextList;
@@ -809,7 +833,8 @@
     TreeNode()
     : m_magic(MAGIC), m_state(TN_END),
       m_parentPtrI(RNIL), m_requestPtrI(RNIL),
-      m_ancestors()
+      m_ancestors(),
+      m_resumeEvents(0), m_resumePtrI(RNIL)
     {
     }
 
@@ -818,6 +843,7 @@
       m_info(0), m_bits(T_LEAF), m_state(TN_BUILDING),
       m_parentPtrI(RNIL), m_requestPtrI(request),
       m_ancestors(),
+      m_resumeEvents(0), m_resumePtrI(RNIL),
       nextList(RNIL), prevList(RNIL)
     {
 //    m_send.m_ref = 0;
@@ -945,10 +971,27 @@
        */
       T_SCAN_REPEATABLE = 0x4000,
 
+      /**
+       * Exec of a previous REQ must complete before we can proceed.
+       * A ResumeEvent will later resume exec. of this operation
+       */
+      T_EXEC_SEQUENTIAL = 0x8000,
+
       // End marker...
       T_END = 0
     };
 
+    /**
+     * Describe whether a LQHKEY-REF and/or CONF whould trigger a 
+     * exec resume of another TreeNode having T_EXEC_SEQUENTIAL.
+     * (Used as a bitmask)
+     */
+    enum TreeNodeResumeEvents
+    {
+      TN_RESUME_REF   = 0x01,
+      TN_RESUME_CONF  = 0x02
+    };
+
     bool isLeaf() const { return (m_bits & T_LEAF) != 0;}
 
     // table or index this TreeNode operates on, and its schemaVersion
@@ -974,6 +1017,22 @@
      */
     RowCollection m_rows;
 
+    /**
+     * T_EXEC_SEQUENTIAL cause execution of child operations to
+     * be deferred.  These operations are queued in the 'struct DeferredParentOps'
+     * Currently only Lookup operation might be deferred.
+     * Could later be extended to also cover index scans.
+     */
+    DeferredParentOps m_deferred;
+
+    /**
+     * Set of TreeNodeResumeEvents, possibly or'ed.
+     * Specify whether a REF or CONF will cause a resume
+     * of the TreeNode referred by 'm_resumePtrI'.
+     */
+    Uint32 m_resumeEvents;
+    Uint32 m_resumePtrI;
+
     union
     {
       LookupData m_lookup_data;
@@ -1251,6 +1310,7 @@
   const OpInfo* getOpInfo(Uint32 op);
   Uint32 build(Build_context&,Ptr<Request>,SectionReader&,SectionReader&);
   Uint32 initRowBuffers(Ptr<Request>);
+  void buildExecPlan(Ptr<Request>, Ptr<TreeNode> node, Ptr<TreeNode> next);
   void checkPrepareComplete(Signal*, Ptr<Request>, Uint32 cnt);
   void start(Signal*, Ptr<Request>);
   void checkBatchComplete(Signal*, Ptr<Request>, Uint32 cnt);
@@ -1259,13 +1319,14 @@
   void sendConf(Signal*, Ptr<Request>, bool is_complete);
   void complete(Signal*, Ptr<Request>);
   void cleanup(Ptr<Request>);
+  void cleanupBatch(Ptr<Request>);
   void abort(Signal*, Ptr<Request>, Uint32 errCode);
   Uint32 nodeFail(Signal*, Ptr<Request>, NdbNodeBitmask mask);
 
   Uint32 createNode(Build_context&, Ptr<Request>, Ptr<TreeNode> &);
   void reportBatchComplete(Signal*, Ptr<Request>, Ptr<TreeNode>);
   void releaseScanBuffers(Ptr<Request> requestPtr);
-  void releaseRequestBuffers(Ptr<Request> requestPtr, bool reset);
+  void releaseRequestBuffers(Ptr<Request> requestPtr);
   void releaseNodeRows(Ptr<Request> requestPtr, Ptr<TreeNode>);
   void registerActiveCursor(Ptr<Request>, Ptr<TreeNode>);
   void nodeFail_checkRequests(Signal*);
@@ -1368,6 +1429,7 @@
   Uint32 lookup_build(Build_context&,Ptr<Request>,
 		      const QueryNode*, const QueryNodeParameters*);
   void lookup_start(Signal*, Ptr<Request>, Ptr<TreeNode>);
+  void lookup_resume(Signal*, Ptr<Request>, Ptr<TreeNode>);
   void lookup_send(Signal*, Ptr<Request>, Ptr<TreeNode>);
   void lookup_execTRANSID_AI(Signal*, Ptr<Request>, Ptr<TreeNode>,
 			     const RowPtr&);
@@ -1375,6 +1437,7 @@
   void lookup_execLQHKEYCONF(Signal*, Ptr<Request>, Ptr<TreeNode>);
   void lookup_parent_row(Signal*, Ptr<Request>, Ptr<TreeNode>, const RowPtr &);
   void lookup_parent_batch_complete(Signal*, Ptr<Request>, Ptr<TreeNode>);
+  void lookup_row(Signal*, Ptr<Request>, Ptr<TreeNode>, const RowPtr &);
   void lookup_abort(Signal*, Ptr<Request>, Ptr<TreeNode>);
   Uint32 lookup_execNODE_FAILREP(Signal*signal, Ptr<Request>, Ptr<TreeNode>,
                                NdbNodeBitmask);

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2012-11-08 12:02:48 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2012-11-13 10:27:06 +0000
@@ -50,7 +50,7 @@
  * DEBUG options for different parts od SPJ block
  * Comment out those part you don't want DEBUG'ed.
  */
-#define DEBUG(x) ndbout << "DBSPJ: "<< x << endl;
+//#define DEBUG(x) ndbout << "DBSPJ: "<< x << endl;
 //#define DEBUG_DICT(x) ndbout << "DBSPJ: "<< x << endl;
 //#define DEBUG_LQHKEYREQ
 //#define DEBUG_SCAN_FRAGREQ
@@ -1314,7 +1314,35 @@
 Uint32
 Dbspj::initRowBuffers(Ptr<Request> requestPtr)
 {
-  Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
+  jam();
+  /**
+   * Execution of scan request requires restrictions
+   * of how lookup-children issues their LQHKEYREQs:
+   * A large scan result with many parallel lookup
+   * siblings can easily flood the job buffers with too many
+   * REQs. So we set up an 'execution plan' for how a
+   * scan request should be executed:
+   *
+   * NOTE: It could make sense to do the same for a lookup Req.
+   * However, CONF/REF for these leafs operations are not 
+   * returned to SPJ. Thus, there are no way to know when
+   * the operation has completed, and other operation could
+   * be resumed.
+   *
+   * As a lookup request does not have the same potential for
+   * producing lots of LQHKEYREQs, we believe/hope the risk
+   * of flooding job buffers for a lookup request can be ignored.
+   */
+  if (requestPtr.p->isScan())
+  {
+    jam();
+    Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
+    Ptr<TreeNode> treeRootPtr;
+
+    list.first(treeRootPtr);   // treeRootPtr is a scan
+    ndbrequire(!treeRootPtr.isNull());
+    buildExecPlan(requestPtr, treeRootPtr, NullTreeNodePtr);
+  }
 
   /**
    * Init ROW_BUFFERS iff Request has to buffer any rows.
@@ -1345,6 +1373,7 @@
       requestPtr.p->m_rowBuffer.init(BUFFER_STACK);
     }
 
+    Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
     Ptr<TreeNode> treeNodePtr;
     for (list.first(treeNodePtr); !treeNodePtr.isNull(); list.next(treeNodePtr))
     {
@@ -1372,7 +1401,150 @@
   }
 
   return 0;
-}
+} // Dbspj::initRowBuffers
+
+/**
+ * buildExecPlan():
+ *   Decides the order/pace in which the different
+ *   TreeNodes should be executed.
+ *   Currently it is only used to insert sequentialization point in
+ *   the execution of bushy lookup-child nodes. (aka star-join).
+ *   This is done in order to avoid too many LQHKEYREQ-signals to
+ *   be sent which could overflow the job buffers.
+ *
+ *   For each branch of TreeNodes starting with a scan, we identify
+ *   any 'bushines' among its lookup children. We set up a left -> right
+ *   execution order among these such that:
+ *    - A child lookup operation can not be REQuested before we
+ *      either has executed a TRANSID_AI from the scan parent,
+ *      or executed a CONF / REF from another lookup child.
+ *    - When a lookup CONF or REF is executed, its TreeNode is 
+ *      annotated with 'resume' info which decides if/which TreeNode
+ *      we should execute next.
+ *
+ *   This will maintain a strict 1:1 fanout between incomming rows
+ *   being processed, and new row REQuest being produced.
+ *   Thus avoiding that large scan result will flood the jobb buffers 
+ *   with too many lookup requests.
+ *
+ * FUTURE:
+ *   For join children where child execution now is T_EXEC_SEQUENTIAL,
+ *   it should be relatively simple to extend SPJ to do 'inner join'.
+ *   As we at these sequential point knows wheteher the previous
+ *   joined children didn't found any matches, we can skip REQuesting
+ *   rows from other children having the same parent row.
+ */
+void
+Dbspj::buildExecPlan(Ptr<Request>  requestPtr,
+                     Ptr<TreeNode> treeNodePtr,
+                     Ptr<TreeNode> nextLookup)
+{
+  Uint32 lookupChildren[NDB_SPJ_MAX_TREE_NODES];
+  Uint32 lookupChildCnt = 0;
+
+  /**
+   * Need to iterate lookup childs in reverse order to set up 'next'
+   * operations. As this is not possible throught ConstDataBufferIterator,
+   * store any lookup childs into temp array childPtrI[].
+   * Scan childs are parents of new 'scan -> lookup' branches.
+   */
+  {
+    LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+    Local_dependency_map childList(pool, treeNodePtr.p->m_dependent_nodes);
+    Dependency_map::ConstDataBufferIterator it;
+    for (childList.first(it); !it.isNull(); childList.next(it))
+    {
+      jam();
+      Ptr<TreeNode> childPtr;
+      m_treenode_pool.getPtr(childPtr, *it.data);
+
+      if (childPtr.p->m_info == &g_LookupOpInfo)
+      {
+        jam();
+        lookupChildren[lookupChildCnt++] = *it.data;
+      }
+      else
+      {
+        // Build a new plan starting from this scan operation
+        jam();
+        buildExecPlan(requestPtr, childPtr, NullTreeNodePtr);
+      }
+    }
+  }
+
+  /**
+   * Lookup children might have to wait for previous LQHKEYREQs to
+   * complete before they are allowed to send their own requests.
+   * (In order to not overfill jobb buffers)
+   */
+  if (treeNodePtr.p->m_info == &g_LookupOpInfo &&
+      !nextLookup.isNull())
+  {
+    jam();
+    /**
+     * Annotate that:
+     *  - 'nextLookup' is not allowed to start immediately.
+     *  - 'treeNode' restart 'nextLookup' when it completes 
+     */
+    nextLookup.p->m_bits |= TreeNode::T_EXEC_SEQUENTIAL;
+
+    if (lookupChildCnt==0)  //'isLeaf() or only scan children
+    {
+      jam();
+      treeNodePtr.p->m_resumeEvents = TreeNode::TN_RESUME_CONF |
+                                      TreeNode::TN_RESUME_REF;
+      DEBUG("ExecPlan: 'REF/CONF' from node " << treeNodePtr.p->m_node_no
+         << " resumes node " << nextLookup.p->m_node_no);
+    }
+    else
+    {
+      /**
+       * Will REQuest from one of its child lookups if CONF,
+       * so we don't resume another TreeNode in addition.
+       */
+      jam();
+      treeNodePtr.p->m_resumeEvents = TreeNode::TN_RESUME_REF;
+      DEBUG("ExecPlan: 'REF' from node " << treeNodePtr.p->m_node_no
+         << " resumes node " << nextLookup.p->m_node_no);
+    }
+    treeNodePtr.p->m_resumePtrI = nextLookup.i;
+
+    /**
+     * When we T_EXEC_SEQUENTIAL, TreeNode will iterate its
+     * parent rows in order to create new REQ's as previous
+     * are completed (CONF or REF).
+     *  - Prepare RowIterator for parent rows
+     *  - Buffer rows to be iterated in the parent node 
+     */
+    {
+      jam();
+
+      ndbassert(nextLookup.p->m_parentPtrI != RNIL);
+      Ptr<TreeNode> parentPtr;
+      m_treenode_pool.getPtr(parentPtr, nextLookup.p->m_parentPtrI);
+      parentPtr.p->m_bits |= TreeNode::T_ROW_BUFFER
+                           | TreeNode::T_ROW_BUFFER_MAP;
+      requestPtr.p->m_bits |= Request::RT_ROW_BUFFERS;
+
+      DEBUG("ExecPlan: rows from node " << parentPtr.p->m_node_no
+         << " are buffered");
+    }
+  }
+
+  /**
+   * Recursively build exec. plan for any lookup child.
+   */
+  for (int i = lookupChildCnt-1; i >= 0; i--)
+  {
+    jam();
+    Ptr<TreeNode> childPtr;
+    m_treenode_pool.getPtr(childPtr, lookupChildren[i]);
+    ndbassert(childPtr.p->m_info == &g_LookupOpInfo);
+
+    buildExecPlan(requestPtr, childPtr, nextLookup);
+    nextLookup = childPtr;
+  }
+} // Dbspj::buildExecPlan
 
 Uint32
 Dbspj::createNode(Build_context& ctx, Ptr<Request> requestPtr,
@@ -1547,26 +1719,18 @@
   {
     jam();
     /**
-     * request completed
+     * Entire Request completed
      */
     cleanup(requestPtr);
   }
-  else if ((requestPtr.p->m_bits & Request::RT_MULTI_SCAN) != 0)
-  {
-    jam();
-    /**
-     * release unneeded buffers as preparation for later SCAN_NEXTREQ
-     */
-    releaseScanBuffers(requestPtr);
-  }
-  else if ((requestPtr.p->m_bits & Request::RT_ROW_BUFFERS) != 0)
-  {
-    jam();
-    /**
-     * if not multiple scans in request, simply release all pages allocated
-     * for row buffers (all rows will be released anyway)
-     */
-    releaseRequestBuffers(requestPtr, true);
+  else
+  {
+    jam();
+    /**
+     * Cleanup the TreeNode branches getting another
+     * batch of result rows.
+     */
+    cleanupBatch(requestPtr);
   }
 }
 
@@ -1699,6 +1863,26 @@
 }
 
 void
+Dbspj::registerActiveCursor(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr)
+{
+  Uint32 bit = treeNodePtr.p->m_node_no;
+  ndbrequire(!requestPtr.p->m_active_nodes.get(bit));
+  requestPtr.p->m_active_nodes.set(bit);
+
+  Local_TreeNodeCursor_list list(m_treenode_pool, requestPtr.p->m_cursor_nodes);
+#ifdef VM_TRACE
+  {
+    Ptr<TreeNode> nodePtr;
+    for (list.first(nodePtr); !nodePtr.isNull(); list.next(nodePtr))
+    {
+      ndbrequire(nodePtr.i != treeNodePtr.i);
+    }
+  }
+#endif
+  list.add(treeNodePtr);
+}
+
+void
 Dbspj::sendConf(Signal* signal, Ptr<Request> requestPtr, bool is_complete)
 {
   if (requestPtr.p->isScan())
@@ -1819,26 +2003,64 @@
   return 0;
 }
 
+/**
+ * Cleanup resources in preparation for a SCAN_NEXTREQ
+ * requesting a new batch of rows.
+ */
 void
-Dbspj::releaseScanBuffers(Ptr<Request> requestPtr)
+Dbspj::cleanupBatch(Ptr<Request> requestPtr)
 {
+  /**
+   * Needs to be atleast 1 active otherwise we should have
+   *   taken the Request cleanup "path" in batchComplete
+   */
+  ndbassert(requestPtr.p->m_cnt_active >= 1);
+
+  /**
+   * Release any buffered rows for the TreeNode branches
+   * getting new rows.
+   */
+  if ((requestPtr.p->m_bits & Request::RT_ROW_BUFFERS) != 0)
+  {
+    if ((requestPtr.p->m_bits & Request::RT_MULTI_SCAN) != 0)
+    {
+      jam();
+      /**
+       * A MULTI_SCAN may selectively retrieve rows from only
+       * some of the (scan-) branches in the Request.
+       * Selectively release from only these brances.
+       */
+      releaseScanBuffers(requestPtr);
+    }
+    else
+    {
+      jam();
+      /**
+       * if not multiple scans in request, simply release all pages allocated
+       * for row buffers (all rows will be released anyway)
+       */
+      // Root node should be the one and only being active
+      ndbassert(requestPtr.p->m_cnt_active == 1);
+      ndbassert(requestPtr.p->m_active_nodes.get(0));
+      releaseRequestBuffers(requestPtr);
+    }
+  } //RT_ROW_BUFFERS
+
+
   Ptr<TreeNode> treeNodePtr;
   Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
 
   for (list.first(treeNodePtr); !treeNodePtr.isNull(); list.next(treeNodePtr))
   {
     /**
-     * Release buffered rows for all treeNodes getting more rows
+     * Re-init row buffer structures for those treeNodes getting more rows
      * in the following NEXTREQ, including all its childs.
      */
     if (requestPtr.p->m_active_nodes.get(treeNodePtr.p->m_node_no) ||
         requestPtr.p->m_active_nodes.overlaps(treeNodePtr.p->m_ancestors))
     {
-      if (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER)
-      {
-        jam();
-        releaseNodeRows(requestPtr, treeNodePtr);
-      }
+      jam();
+      treeNodePtr.p->m_rows.init();
     }
 
     /**
@@ -1848,6 +2070,21 @@
     if (requestPtr.p->m_active_nodes.overlaps(treeNodePtr.p->m_ancestors))
     {
       jam();
+      /**
+       * Common TreeNode cleanup:
+       * Release list of deferred operations which may refer 
+       * buffered rows released above.
+       */
+      LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+      {
+        Local_correlation_list correlations(pool, treeNodePtr.p->m_deferred.m_correlations);
+        correlations.release();
+      }
+      treeNodePtr.p->m_deferred.init();
+
+      /**
+       * TreeNode-type specific cleanup.
+       */
       if (treeNodePtr.p->m_info->m_parent_batch_cleanup != 0)
       {
         jam();
@@ -1856,31 +2093,30 @@
       }
     }
   }
-  /**
-   * Needs to be atleast 1 active otherwise we should have
-   *   taken the cleanup "path" in batchComplete
-   */
-  ndbrequire(requestPtr.p->m_cnt_active >= 1);
 }
 
 void
-Dbspj::registerActiveCursor(Ptr<Request> requestPtr, Ptr<TreeNode> treeNodePtr)
+Dbspj::releaseScanBuffers(Ptr<Request> requestPtr)
 {
-  Uint32 bit = treeNodePtr.p->m_node_no;
-  ndbrequire(!requestPtr.p->m_active_nodes.get(bit));
-  requestPtr.p->m_active_nodes.set(bit);
+  Ptr<TreeNode> treeNodePtr;
+  Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
 
-  Local_TreeNodeCursor_list list(m_treenode_pool, requestPtr.p->m_cursor_nodes);
-#ifdef VM_TRACE
+  for (list.first(treeNodePtr); !treeNodePtr.isNull(); list.next(treeNodePtr))
   {
-    Ptr<TreeNode> nodePtr;
-    for (list.first(nodePtr); !nodePtr.isNull(); list.next(nodePtr))
+    /**
+     * Release buffered rows for all treeNodes getting more rows
+     * in the following NEXTREQ, including all its childs.
+     */
+    if (requestPtr.p->m_active_nodes.get(treeNodePtr.p->m_node_no) ||
+        requestPtr.p->m_active_nodes.overlaps(treeNodePtr.p->m_ancestors))
     {
-      ndbrequire(nodePtr.i != treeNodePtr.i);
+      if (treeNodePtr.p->m_bits & TreeNode::T_ROW_BUFFER)
+      {
+        jam();
+        releaseNodeRows(requestPtr, treeNodePtr);
+      }
     }
   }
-#endif
-  list.add(treeNodePtr);
 }
 
 void
@@ -1906,7 +2142,6 @@
     releaseRow(treeNodePtr.p->m_rows, pos);
     cnt ++;
   }
-  treeNodePtr.p->m_rows.init();
   DEBUG("RowIterator: released " << cnt << " rows!");
 
   if (treeNodePtr.p->m_rows.m_type == RowCollection::COLLECTION_MAP)
@@ -1982,7 +2217,7 @@
 }
 
 void
-Dbspj::releaseRequestBuffers(Ptr<Request> requestPtr, bool reset)
+Dbspj::releaseRequestBuffers(Ptr<Request> requestPtr)
 {
   DEBUG("releaseRequestBuffers"
      << ", request: " << requestPtr.i
@@ -2006,17 +2241,6 @@
     }
     requestPtr.p->m_rowBuffer.reset();
   }
-
-  if (reset)
-  {
-    Ptr<TreeNode> nodePtr;
-    Local_TreeNode_list list(m_treenode_pool, requestPtr.p->m_nodes);
-    for (list.first(nodePtr); !nodePtr.isNull(); list.next(nodePtr))
-    {
-      jam();
-      nodePtr.p->m_rows.init();
-    }
-  }
 }
 
 void
@@ -2226,7 +2450,7 @@
     jam();
     m_lookup_request_hash.remove(requestPtr, *requestPtr.p);
   }
-  releaseRequestBuffers(requestPtr, false);
+  releaseRequestBuffers(requestPtr);
   ArenaHead ah = requestPtr.p->m_arena;
   m_request_pool.release(requestPtr);
   m_arenaAllocator.release(ah);
@@ -2253,6 +2477,11 @@
     pattern.release();
   }
 
+  {
+    Local_correlation_list correlations(pool, treeNodePtr.p->m_deferred.m_correlations);
+    correlations.release();
+  }
+
   if (treeNodePtr.p->m_send.m_keyInfoPtrI != RNIL)
   {
     jam();
@@ -3612,6 +3841,7 @@
   treeNodePtr.p->m_lookup_data.m_outstanding--;
 
   if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE
+      && treeNodePtr.p->m_deferred.isEmpty()
       && treeNodePtr.p->m_lookup_data.m_parent_batch_complete
       && treeNodePtr.p->m_lookup_data.m_outstanding == 0)
   {
@@ -3726,7 +3956,21 @@
 
   treeNodePtr.p->m_lookup_data.m_outstanding -= cnt;
 
+  /**
+   * Another TreeNode awaited for completion of this request
+   * before it could resume its operation.
+   */
+  if (treeNodePtr.p->m_resumeEvents & TreeNode::TN_RESUME_REF)
+  {
+    jam();
+    ndbassert(treeNodePtr.p->m_resumePtrI != RNIL);
+    Ptr<TreeNode> resumeTreeNodePtr;
+    m_treenode_pool.getPtr(resumeTreeNodePtr, treeNodePtr.p->m_resumePtrI);
+    lookup_resume(signal, requestPtr, resumeTreeNodePtr);
+  }
+
   if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE
+      && treeNodePtr.p->m_deferred.isEmpty()
       && treeNodePtr.p->m_lookup_data.m_parent_batch_complete
       && treeNodePtr.p->m_lookup_data.m_outstanding == 0)
   {
@@ -3762,7 +4006,21 @@
 
   treeNodePtr.p->m_lookup_data.m_outstanding--;
 
+  /**
+   * Another TreeNode awaited for completion of this request
+   * before it could resume its operation.
+   */
+  if (treeNodePtr.p->m_resumeEvents & TreeNode::TN_RESUME_CONF)
+  {
+    jam();
+    ndbassert(treeNodePtr.p->m_resumePtrI != RNIL);
+    Ptr<TreeNode> resumeTreeNodePtr;
+    m_treenode_pool.getPtr(resumeTreeNodePtr, treeNodePtr.p->m_resumePtrI);
+    lookup_resume(signal, requestPtr, resumeTreeNodePtr);
+  }
+
   if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE
+      && treeNodePtr.p->m_deferred.isEmpty()
       && treeNodePtr.p->m_lookup_data.m_parent_batch_complete
       && treeNodePtr.p->m_lookup_data.m_outstanding == 0)
   {
@@ -3786,6 +4044,99 @@
 {
   jam();
 
+  DEBUG("::lookup_parent_row"
+     << ", node: " << treeNodePtr.p->m_node_no);
+
+  if (treeNodePtr.p->m_bits & TreeNode::T_EXEC_SEQUENTIAL)
+  {
+    jam();
+    DEBUG("T_EXEC_SEQUENTIAL --> exec deferred");
+
+    /**
+     * Append correlation values of deferred parent row operations
+     * to a list / fifo. Upon resume, we will then be able to 
+     * relocate all parent rows for which to resume operations.
+     */
+    LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+    Local_pattern_store correlations(pool, treeNodePtr.p->m_deferred.m_correlations);
+    if (!correlations.append(&rowRef.m_src_correlation, 1))
+    {
+      jam();
+      abort(signal, requestPtr, DbspjErr::OutOfQueryMemory);
+      return;
+    }
+    return;
+  }
+
+  lookup_row(signal, requestPtr, treeNodePtr, rowRef);
+} // Dbspj::lookup_parent_row()
+
+/**
+ * lookup_resume() is a delayed lookup_parent_row.
+ * It will locate the next parent row now allowed to execute,
+ * and create a child lookup request for that row.
+ */
+void
+Dbspj::lookup_resume(Signal* signal,
+                     Ptr<Request> requestPtr,
+                     Ptr<TreeNode> treeNodePtr)
+{
+  DEBUG("::lookup_resume"
+     << ", node: " << treeNodePtr.p->m_node_no
+  );
+
+  ndbassert(treeNodePtr.p->m_bits & TreeNode::T_EXEC_SEQUENTIAL);
+  ndbassert(treeNodePtr.p->m_parentPtrI != RNIL);
+  ndbassert(!treeNodePtr.p->m_deferred.isEmpty());
+
+  if (unlikely(requestPtr.p->m_state & Request::RS_ABORTING))
+  {
+    jam();
+    return;
+  }
+
+  Uint32 corrVal;
+  {
+    LocalArenaPoolImpl pool(requestPtr.p->m_arena, m_dependency_map_pool);
+    Local_pattern_store correlations(pool, treeNodePtr.p->m_deferred.m_correlations);
+
+    Local_pattern_store::DataBufferIterator it;
+    const bool valid = correlations.position(it, (Uint32)(treeNodePtr.p->m_deferred.m_pos++));
+    (void)valid; ndbassert(valid);
+    corrVal = *it.data;
+  }
+
+  Ptr<TreeNode> parentPtr;
+  m_treenode_pool.getPtr(parentPtr, treeNodePtr.p->m_parentPtrI);
+
+  // Set up RowPtr & RowRef for this parent row
+  RowPtr row;
+  row.m_src_node_ptrI = parentPtr.i;
+  row.m_src_correlation = corrVal;
+
+  ndbassert(parentPtr.p->m_rows.m_type == RowCollection::COLLECTION_MAP);
+  RowRef ref;
+  parentPtr.p->m_rows.m_map.copyto(ref);
+  const Uint32* const mapptr = get_row_ptr(ref);
+
+  // Relocate parent row from correlation value.
+  const Uint32 rowId = (corrVal & 0xFFFF);
+  parentPtr.p->m_rows.m_map.load(mapptr, rowId, ref);
+
+  const Uint32* const rowptr = get_row_ptr(ref);
+  setupRowPtr(parentPtr.p->m_rows, row, ref, rowptr);
+
+  lookup_row(signal, requestPtr, treeNodePtr, row);
+} // Dbspj::lookup_resume()
+
+void
+Dbspj::lookup_row(Signal* signal,
+                         Ptr<Request> requestPtr,
+                         Ptr<TreeNode> treeNodePtr,
+                         const RowPtr & rowRef)
+{
+  jam();
+
   /**
    * Here we need to...
    *   1) construct a key
@@ -3796,7 +4147,7 @@
   const Uint32 tableId = treeNodePtr.p->m_tableOrIndexId;
   const Uint32 corrVal = rowRef.m_src_correlation;
 
-  DEBUG("::lookup_parent_row"
+  DEBUG("::lookup_row"
      << ", node: " << treeNodePtr.p->m_node_no);
 
   do
@@ -3853,10 +4204,11 @@
          * When the key contains NULL values, an EQ-match is impossible!
          * Entire lookup request can therefore be eliminate as it is known
          * to be REFused with errorCode = 626 (Row not found).
-         * Different handling is required depening of request being a
-         * scan or lookup:
+         * Scan request can elliminate these child LQHKEYREQs if REFs 
+         * are not needed in order to handle TN_RESUME_REF.
          */
-        if (requestPtr.p->isScan())
+        if (requestPtr.p->isScan() &&
+            (treeNodePtr.p->m_resumeEvents & TreeNode::TN_RESUME_REF) == 0)
         {
           /**
            * Scan request: We can simply ignore lookup operation:
@@ -3868,7 +4220,7 @@
           releaseSection(ptrI);
           return;  // Bailout, KEYREQ would have returned KEYREF(626) anyway
         }
-        else  // isLookup()
+        else  // isLookup() or 'need TN_RESUME_REF'
         {
           /**
            * Ignored lookup request need a faked KEYREF for the lookup operation.
@@ -4053,7 +4405,9 @@
 
   ndbassert(!treeNodePtr.p->m_lookup_data.m_parent_batch_complete);
   treeNodePtr.p->m_lookup_data.m_parent_batch_complete = true;
+
   if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE
+      && treeNodePtr.p->m_deferred.isEmpty()
       && treeNodePtr.p->m_lookup_data.m_outstanding == 0)
   {
     jam();
@@ -4679,6 +5033,7 @@
       }
     }
   }
+  ndbassert(treeNodePtr.p->m_resumePtrI == RNIL);
 
   if (treeNodePtr.p->m_scanfrag_data.m_rows_received ==
       treeNodePtr.p->m_scanfrag_data.m_rows_expecting)
@@ -6312,6 +6667,7 @@
 
   ScanIndexData& data = treeNodePtr.p->m_scanindex_data;
   data.m_rows_received++;
+  ndbassert(treeNodePtr.p->m_resumePtrI == RNIL);
 
   if (data.m_frags_outstanding == 0 &&
       data.m_rows_received == data.m_rows_expecting)

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5-cluster-7.2 branch (ole.john.aske:4087 to 4088)Bug#14709490Ole John Aske14 Nov