3225 Jan Wedvik 2010-08-17
This commit fixes a regression that could cause core dumps when doing an
ordered scan with a lookup child where all result rows from the parent
where eliminated by the inner join (i.e. no results from the child).
The code did in some places assum that an empty batch would also have to
be the final batch. But the batch can also be empty due to inner join
row elimination.
The commit also adds a regression test for this fix.
modified:
mysql-test/suite/ndb/r/ndb_join_pushdown.result
mysql-test/suite/ndb/t/ndb_join_pushdown.test
storage/ndb/src/ndbapi/NdbQueryOperation.cpp
3224 Jan Wedvik 2010-08-17
This is a refactoring of commit http://lists.mysql.com/commits/115164 .
Dbspj::LookupData has been simplified such that is uses two rather than three
fields to keep track of the state of a lookup operation with a scan ancestor.
Also, a regression test for scan-lookup-scan has been added.
modified:
mysql-test/suite/ndb/r/ndb_join_pushdown.result
mysql-test/suite/ndb/t/ndb_join_pushdown.test
storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp
storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
=== modified file 'mysql-test/suite/ndb/r/ndb_join_pushdown.result'
--- a/mysql-test/suite/ndb/r/ndb_join_pushdown.result 2010-08-17 08:02:00 +0000
+++ b/mysql-test/suite/ndb/r/ndb_join_pushdown.result 2010-08-17 12:04:13 +0000
@@ -3323,4 +3323,30 @@ pk u a b pk u a b pk u a b
0 1 10 20 1 2 20 30 0 1 10 20
1 2 20 30 2 3 30 40 1 2 20 30
drop table t1;
+create table t1 (pk int primary key, u int not null) engine=ndb;
+insert into t1 values (0,-1), (1,-1), (2,-1), (3,-1), (4,-1), (5,-1), (6,-1),
+(7,-1), (8,-1), (9,-1), (10,-1), (11,-1), (12,-1), (13,-1), (14,-1), (15,-1),
+(16,-1), (17,-1), (18,-1), (19,-1), (20,-1), (21,-1), (22,-1), (23,-1),
+(24,-1), (25,-1), (26,-1), (27,-1), (28,-1), (29,-1), (30,-1), (31,-1),
+(32,-1), (33,-1), (34,-1), (35,-1), (36,-1), (37,-1), (38,-1), (39,-1),
+(40,-1), (41,-1), (42,-1), (43,-1), (44,-1), (45,-1), (46,-1), (47,-1),
+(48,-1), (49,-1), (50,-1), (51,-1), (52,-1), (53,-1), (54,-1), (55,-1),
+(56,-1), (57,-1), (58,-1), (59,-1), (60,-1), (61,-1), (62,-1), (63,-1),
+(64,-1), (65,-1), (66,-1), (67,-1), (68,-1), (69,-1), (70,-1), (71,-1),
+(72,-1), (73,-1), (74,-1), (75,-1), (76,-1), (77,-1), (78,-1), (79,-1),
+(80,-1), (81,-1), (82,-1), (83,-1), (84,-1), (85,-1), (86,-1), (87,-1),
+(88,-1), (89,-1), (90,-1), (91,-1), (92,-1), (93,-1), (94,-1), (95,-1),
+(96,-1), (97,-1), (98,-1), (99,-1), (100,-1), (101,-1), (102,-1), (103,-1),
+(104,-1), (105,-1), (106,-1), (107,-1), (108,-1), (109,-1), (110,-1),
+(111,-1), (112,-1), (113,-1), (114,-1), (115,-1), (116,-1), (117,-1),
+(118,-1), (119,-1), (120,-1), (121,-1), (122,-1), (123,-1), (124,-1),
+(125,-1), (126,-1), (127,-1), (128,-1), (129,-1), (130,-1), (131,-1),
+(132,-1), (133,-1), (134,-1), (135,-1), (136,-1), (137,-1), (138,-1), (139,-1);
+explain select * from t1 as x join t1 as y on x.u=y.pk order by(x.pk);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE x index NULL PRIMARY 4 NULL 140 Parent of 2 pushed join@1
+1 SIMPLE y eq_ref PRIMARY PRIMARY 4 test.x.u 1 Child of pushed join@1
+select * from t1 as x join t1 as y on x.u=y.pk order by(x.pk);
+pk u pk u
+drop table t1;
set ndb_join_pushdown = @save_ndb_join_pushdown;
=== modified file 'mysql-test/suite/ndb/t/ndb_join_pushdown.test'
--- a/mysql-test/suite/ndb/t/ndb_join_pushdown.test 2010-08-17 08:02:00 +0000
+++ b/mysql-test/suite/ndb/t/ndb_join_pushdown.test 2010-08-17 12:04:13 +0000
@@ -2352,6 +2352,32 @@ select * from t1 as x join t1 as y join
drop table t1;
+# Test sorted scan where inner join eliminates all rows (known regression).
+create table t1 (pk int primary key, u int not null) engine=ndb;
+
+insert into t1 values (0,-1), (1,-1), (2,-1), (3,-1), (4,-1), (5,-1), (6,-1),
+(7,-1), (8,-1), (9,-1), (10,-1), (11,-1), (12,-1), (13,-1), (14,-1), (15,-1),
+(16,-1), (17,-1), (18,-1), (19,-1), (20,-1), (21,-1), (22,-1), (23,-1),
+(24,-1), (25,-1), (26,-1), (27,-1), (28,-1), (29,-1), (30,-1), (31,-1),
+(32,-1), (33,-1), (34,-1), (35,-1), (36,-1), (37,-1), (38,-1), (39,-1),
+(40,-1), (41,-1), (42,-1), (43,-1), (44,-1), (45,-1), (46,-1), (47,-1),
+(48,-1), (49,-1), (50,-1), (51,-1), (52,-1), (53,-1), (54,-1), (55,-1),
+(56,-1), (57,-1), (58,-1), (59,-1), (60,-1), (61,-1), (62,-1), (63,-1),
+(64,-1), (65,-1), (66,-1), (67,-1), (68,-1), (69,-1), (70,-1), (71,-1),
+(72,-1), (73,-1), (74,-1), (75,-1), (76,-1), (77,-1), (78,-1), (79,-1),
+(80,-1), (81,-1), (82,-1), (83,-1), (84,-1), (85,-1), (86,-1), (87,-1),
+(88,-1), (89,-1), (90,-1), (91,-1), (92,-1), (93,-1), (94,-1), (95,-1),
+(96,-1), (97,-1), (98,-1), (99,-1), (100,-1), (101,-1), (102,-1), (103,-1),
+(104,-1), (105,-1), (106,-1), (107,-1), (108,-1), (109,-1), (110,-1),
+(111,-1), (112,-1), (113,-1), (114,-1), (115,-1), (116,-1), (117,-1),
+(118,-1), (119,-1), (120,-1), (121,-1), (122,-1), (123,-1), (124,-1),
+(125,-1), (126,-1), (127,-1), (128,-1), (129,-1), (130,-1), (131,-1),
+(132,-1), (133,-1), (134,-1), (135,-1), (136,-1), (137,-1), (138,-1), (139,-1);
+
+explain select * from t1 as x join t1 as y on x.u=y.pk order by(x.pk);
+select * from t1 as x join t1 as y on x.u=y.pk order by(x.pk);
+
+drop table t1;
set ndb_join_pushdown = @save_ndb_join_pushdown;
=== modified file 'storage/ndb/src/ndbapi/NdbQueryOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2010-08-17 07:32:36 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryOperation.cpp 2010-08-17 12:04:13 +0000
@@ -2904,9 +2904,14 @@ NdbQueryImpl::OrderedFragSet::add(NdbRoo
{
if(m_size+m_completedFrags < m_capacity)
{
- if(!frag.isEmpty())
+ // We have not yet received the first batch for each fragment.
+ if(frag.isEmpty() && frag.finalBatchReceived())
+ {
+ // This is the first and final batch for this fragment, and it is empty.
+ m_completedFrags++;
+ }
+ else
{
- // Frag is non-empty.
int current = 0;
// Insert the new frag such that the array remains sorted.
while(current<m_size && compare(frag, *m_array[current])==1)
@@ -2921,12 +2926,6 @@ NdbQueryImpl::OrderedFragSet::add(NdbRoo
assert(m_size <= m_capacity);
assert(verifySortOrder());
}
- else
- {
- // First batch is empty, therefore it should also be the final batch.
- assert(frag.finalBatchReceived());
- m_completedFrags++;
- }
}
else
{
@@ -2948,9 +2947,6 @@ NdbQueryImpl::OrderedFragSet::getEmpty()
{
// This method is not applicable to unordered scans.
assert(m_ordering!=NdbQueryOptions::ScanOrdering_unordered);
- // The first frag should be empty when calling this method.
- assert(m_size==0 || m_array[0]->isEmpty());
- assert(verifySortOrder());
if(m_completedFrags==m_capacity)
{
assert(m_size==0);
Attachment: [text/bzr-bundle] bzr/jan.wedvik@sun.com-20100817120413-6zv4h97o4rmjcr3z.bundle
| Thread |
|---|
| • bzr push into mysql-5.1-telco-7.0-spj-scan-vs-scan branch (jan.wedvik:3224to 3225) | Jan Wedvik | 17 Aug |