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:
parent
1cf4b95c58
commit
eca90c43b3
@ -25,11 +25,12 @@ class ScanAll;
|
||||
class Expand;
|
||||
class NodeFilter;
|
||||
class EdgeFilter;
|
||||
class Filter;
|
||||
class Produce;
|
||||
|
||||
using LogicalOperatorVisitor =
|
||||
::utils::Visitor<CreateNode, CreateExpand, ScanAll, Expand, NodeFilter,
|
||||
EdgeFilter, Produce>;
|
||||
EdgeFilter, Filter, Produce>;
|
||||
|
||||
class LogicalOperator : public ::utils::Visitable<LogicalOperatorVisitor> {
|
||||
public:
|
||||
@ -612,6 +613,56 @@ class EdgeFilter : public LogicalOperator {
|
||||
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 {
|
||||
public:
|
||||
Produce(std::shared_ptr<LogicalOperator> input,
|
||||
|
@ -903,3 +903,32 @@ TEST(ExpressionEvaluator, UnaryMinusOperator) {
|
||||
op->Accept(eval.eval);
|
||||
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user