Query - LogicalOp - Filter op added

Reviewers: buda, teon.banek, mislav.bradac

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D176
This commit is contained in:
florijan 2017-03-27 13:15:26 +02:00
parent 1cf4b95c58
commit eca90c43b3
2 changed files with 81 additions and 1 deletions

View File

@ -25,11 +25,12 @@ class ScanAll;
class Expand; class Expand;
class NodeFilter; class NodeFilter;
class EdgeFilter; class EdgeFilter;
class Filter;
class Produce; class Produce;
using LogicalOperatorVisitor = using LogicalOperatorVisitor =
::utils::Visitor<CreateNode, CreateExpand, ScanAll, Expand, NodeFilter, ::utils::Visitor<CreateNode, CreateExpand, ScanAll, Expand, NodeFilter,
EdgeFilter, Produce>; EdgeFilter, Filter, Produce>;
class LogicalOperator : public ::utils::Visitable<LogicalOperatorVisitor> { class LogicalOperator : public ::utils::Visitable<LogicalOperatorVisitor> {
public: public:
@ -612,6 +613,56 @@ class EdgeFilter : public LogicalOperator {
EdgeAtom *edge_atom_; EdgeAtom *edge_atom_;
}; };
/**
* Filter whose Pull returns true only when the given expression
* evaluates into true. The given expression is assumed to
* return either NULL (treated as false) or a boolean value.
*/
class Filter : public LogicalOperator {
public:
Filter(const std::shared_ptr<LogicalOperator> &input_,
Expression *expression_)
: input_(input_), expression_(expression_) {}
void Accept(LogicalOperatorVisitor &visitor) override {
visitor.Visit(*this);
input_->Accept(visitor);
visitor.PostVisit(*this);
}
private:
class FilterCursor : public Cursor {
public:
FilterCursor(Filter &self, GraphDbAccessor &db)
: self_(self), input_cursor_(self_.input_->MakeCursor(db)) {}
bool Pull(Frame &frame, SymbolTable &symbol_table) override {
ExpressionEvaluator evaluator(frame, symbol_table);
while (input_cursor_->Pull(frame, symbol_table)) {
self_.expression_->Accept(evaluator);
TypedValue result = evaluator.PopBack();
if (result.type() == TypedValue::Type::Null || !result.Value<bool>())
continue;
return true;
}
return false;
}
private:
Filter &self_;
std::unique_ptr<Cursor> input_cursor_;
};
public:
std::unique_ptr<Cursor> MakeCursor(GraphDbAccessor &db) override {
return std::make_unique<FilterCursor>(*this, db);
}
private:
std::shared_ptr<LogicalOperator> input_;
Expression *expression_;
};
class Produce : public LogicalOperator { class Produce : public LogicalOperator {
public: public:
Produce(std::shared_ptr<LogicalOperator> input, Produce(std::shared_ptr<LogicalOperator> input,

View File

@ -903,3 +903,32 @@ TEST(ExpressionEvaluator, UnaryMinusOperator) {
op->Accept(eval.eval); op->Accept(eval.eval);
ASSERT_EQ(eval.eval.PopBack().Value<int64_t>(), -5); ASSERT_EQ(eval.eval.PopBack().Value<int64_t>(), -5);
} }
TEST(Interpreter, Filter) {
Dbms dbms;
auto dba = dbms.active();
// add a 6 nodes with property 'prop', 2 have true as value
GraphDb::Property property = dba->property("Property");
for (int i = 0; i < 6; ++i)
dba->insert_vertex().PropsSet(property, i % 3 == 0);
dba->insert_vertex(); // prop not set, gives NULL
dba->advance_command();
AstTreeStorage storage;
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
auto e =
storage.Create<PropertyLookup>(storage.Create<Identifier>("n"), property);
symbol_table[*e->expression_] = std::get<2>(n);
auto f = std::make_shared<Filter>(std::get<1>(n), e);
auto output =
storage.Create<NamedExpression>("x", storage.Create<Identifier>("n"));
symbol_table[*output->expression_] = std::get<2>(n);
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1");
auto produce = MakeProduce(f, output);
EXPECT_EQ(CollectProduce(produce, symbol_table, *dba).GetResults().size(), 2);
}