1
0
Fork 0

[3.3] Bugfix: Distinct collect block could create an empty result block (#5709)

This commit is contained in:
Tobias Gödderz 2018-06-28 13:26:59 +02:00 committed by Jan
parent cb0aaa435f
commit 18f939ebcf
2 changed files with 53 additions and 5 deletions

View File

@ -1016,8 +1016,15 @@ int DistinctCollectBlock::getOrSkipSome(size_t atLeast, size_t atMost,
}
TRI_ASSERT(cur != nullptr);
res->shrink(skipped);
}
if (skipped > 0) {
res->shrink(skipped);
}
else {
AqlItemBlock* block = res.get();
returnBlock(block);
res.release();
}
}
returnBlock(cur);
_done = true;
result = res.release();
@ -1035,8 +1042,14 @@ int DistinctCollectBlock::getOrSkipSome(size_t atLeast, size_t atMost,
}
if (!skipping) {
TRI_ASSERT(skipped > 0);
res->shrink(skipped);
if (skipped > 0) {
res->shrink(skipped);
}
else {
AqlItemBlock* block = res.get();
returnBlock(block);
res.release();
}
}
result = res.release();

View File

@ -300,7 +300,42 @@ function ahuacatlCollect () {
var query = "FOR result IN UnitTestsCollection COLLECT key=result.a.key, name = result.a.name INTO group LIMIT 2,5 RETURN [key,name]";
var result = AQL_EXECUTE(query).json;
assertEqual([[0,2],[0,3],[0,4],[0,5],[0,6]], result);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @brief distinct regression test:
/// crash when a subsequent call to DistinctCollectBlock::getSome() added no new
/// non-distinct results. The crash may occur ONLY IN MAINTAINER MODE, while
/// in non-maintainer mode problems may occur only because either an empty
/// result is returned (which would cause some parent blocks to crash), or
/// an erroneous result is returned, but I didn't find a way to produce this
/// reliably with an AQL query.
////////////////////////////////////////////////////////////////////////////////
testDistinctRegressionGetSomeWithEmptyResult : function () {
const query = 'FOR i IN 1..2 FOR k IN 1..1000 RETURN DISTINCT k';
containsDistinct(query);
const options = {optimizer: {rules: [ "-interchange-adjacent-enumerations" ]}};
// check plan
const plan = helper.getCompactPlan(AQL_EXPLAIN(query, {}, options));
assertEqual(
[
"SingletonNode",
"CalculationNode",
"CalculationNode",
"EnumerateListNode",
"EnumerateListNode",
"CollectNode",
"ReturnNode",
],
plan.map(node => node.type)
);
// execute query
const result = AQL_EXECUTE(query, {}, options).json;
assertEqual(1000, result.length);
},
};
}