Fix ScanAll cursor family w.r.t. empty collections

Reviewers: teon.banek, dgleich, msantl

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1291
This commit is contained in:
florijan 2018-03-09 14:52:09 +01:00
parent a97de56d31
commit 67092ae4d7
2 changed files with 39 additions and 12 deletions

View File

@ -312,7 +312,8 @@ class ScanAllCursor : public Cursor {
bool Pull(Frame &frame, Context &context) override {
if (db_.should_abort()) throw HintedAbortError();
if (!vertices_ || vertices_it_.value() == vertices_.value().end()) {
while (!vertices_ || vertices_it_.value() == vertices_.value().end()) {
if (!input_cursor_->Pull(frame, context)) return false;
// We need a getter function, because in case of exhausting a lazy
// iterable, we cannot simply reset it by calling begin().
@ -320,10 +321,6 @@ class ScanAllCursor : public Cursor {
vertices_it_.emplace(vertices_.value().begin());
}
// if vertices_ is empty then we are done even though we have just
// reinitialized vertices_it_
if (vertices_it_.value() == vertices_.value().end()) return false;
frame[output_symbol_] = *vertices_it_.value()++;
return true;
}
@ -441,13 +438,15 @@ class ScanAllByLabelPropertyValueCursor : public Cursor {
bool Pull(Frame &frame, Context &context) override {
if (db_.should_abort()) throw HintedAbortError();
if (!vertices_ || vertices_it_.value() == vertices_.value().end()) {
if (!input_cursor_->Pull(frame, context)) return false;
while (!vertices_ || vertices_it_.value() == vertices_.value().end()) {
if (!input_cursor_->Pull(frame, context)) {
return false;
}
ExpressionEvaluator evaluator(frame, context.parameters_,
context.symbol_table_, db_,
self_.graph_view());
TypedValue value = self_.expression()->Accept(evaluator);
if (value.IsNull()) return Pull(frame, context);
if (value.IsNull()) continue;
try {
vertices_.emplace(db_.Vertices(self_.label(), self_.property(), value,
self_.graph_view() == GraphView::NEW));
@ -458,10 +457,6 @@ class ScanAllByLabelPropertyValueCursor : public Cursor {
vertices_it_.emplace(vertices_.value().begin());
}
// if vertices_ is empty then we are done even though we have just
// reinitialized vertices_it_
if (vertices_it_.value() == vertices_.value().end()) return false;
frame[self_.output_symbol()] = *vertices_it_.value()++;
return true;
}

View File

@ -1981,6 +1981,38 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualNull) {
EXPECT_EQ(results.size(), 0);
}
TEST(QueryPlan, ScanAllByLabelPropertyNoValueInIndexContinuation) {
database::SingleNode db;
auto label = database::GraphDbAccessor(db).Label("label");
auto prop = database::GraphDbAccessor(db).Property("prop");
{
database::GraphDbAccessor dba(db);
auto v = dba.InsertVertex();
v.add_label(label);
v.PropsSet(prop, 2);
dba.Commit();
database::GraphDbAccessor(db).BuildIndex(label, prop);
}
database::GraphDbAccessor dba(db);
EXPECT_EQ(1, CountIterable(dba.Vertices(false)));
AstTreeStorage storage;
SymbolTable symbol_table;
// UNWIND [1, 2, 3] as x
auto input_expr = LIST(LITERAL(1), LITERAL(2), LITERAL(3));
auto x = symbol_table.CreateSymbol("x", true);
auto unwind = std::make_shared<plan::Unwind>(nullptr, input_expr, x);
auto x_expr = IDENT("x");
symbol_table[*x_expr] = x;
// MATCH (n :label {prop: x})
auto scan_all = MakeScanAllByLabelPropertyValue(storage, symbol_table, "n",
label, prop, x_expr, unwind);
EXPECT_EQ(PullAll(scan_all.op_, dba, symbol_table), 1);
}
int main(int argc, char **argv) {
google::InitGoogleLogging(argv[0]);
::testing::InitGoogleTest(&argc, argv);