Evaluate epressions EdgeTypeTest and LabelsTest
Reviewers: florijan, teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D345
This commit is contained in:
parent
72d4a67c4a
commit
cfb987a90c
@ -526,7 +526,10 @@ class EdgeTypeTest : public Expression {
|
|||||||
protected:
|
protected:
|
||||||
EdgeTypeTest(int uid, Expression *expression,
|
EdgeTypeTest(int uid, Expression *expression,
|
||||||
std::vector<GraphDbTypes::EdgeType> edge_types)
|
std::vector<GraphDbTypes::EdgeType> edge_types)
|
||||||
: Expression(uid), expression_(expression), edge_types_(edge_types) {}
|
: Expression(uid), expression_(expression), edge_types_(edge_types) {
|
||||||
|
debug_assert(edge_types.size(),
|
||||||
|
"EdgeTypeTest must have at least one edge_type");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Function : public Expression {
|
class Function : public Expression {
|
||||||
|
@ -200,6 +200,51 @@ class ExpressionEvaluator : public TreeVisitorBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PostVisit(LabelsTest &labels_test) override {
|
||||||
|
auto expression_result = PopBack();
|
||||||
|
switch (expression_result.type()) {
|
||||||
|
case TypedValue::Type::Null:
|
||||||
|
result_stack_.emplace_back(TypedValue::Null);
|
||||||
|
break;
|
||||||
|
case TypedValue::Type::Vertex: {
|
||||||
|
auto vertex = expression_result.Value<VertexAccessor>();
|
||||||
|
for (const auto label : labels_test.labels_) {
|
||||||
|
if (!vertex.has_label(label)) {
|
||||||
|
result_stack_.emplace_back(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result_stack_.emplace_back(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw TypedValueException("Expected Node in labels test");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PostVisit(EdgeTypeTest &edge_type_test) override {
|
||||||
|
auto expression_result = PopBack();
|
||||||
|
switch (expression_result.type()) {
|
||||||
|
case TypedValue::Type::Null:
|
||||||
|
result_stack_.emplace_back(TypedValue::Null);
|
||||||
|
break;
|
||||||
|
case TypedValue::Type::Edge: {
|
||||||
|
auto real_edge_type =
|
||||||
|
expression_result.Value<EdgeAccessor>().edge_type();
|
||||||
|
for (const auto edge_type : edge_type_test.edge_types_) {
|
||||||
|
if (edge_type == real_edge_type) {
|
||||||
|
result_stack_.emplace_back(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result_stack_.emplace_back(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw TypedValueException("Expected Edge in edge type test");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Visit(PrimitiveLiteral &literal) override {
|
void Visit(PrimitiveLiteral &literal) override {
|
||||||
// TODO: no need to evaluate constants, we can write it to frame in one
|
// TODO: no need to evaluate constants, we can write it to frame in one
|
||||||
// of the previous phases.
|
// of the previous phases.
|
||||||
|
@ -7,11 +7,13 @@
|
|||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#include "database/graph_db_accessor.hpp"
|
#include "database/graph_db_accessor.hpp"
|
||||||
|
#include "database/graph_db_datatypes.hpp"
|
||||||
#include "dbms/dbms.hpp"
|
#include "dbms/dbms.hpp"
|
||||||
#include "query/frontend/ast/ast.hpp"
|
#include "query/frontend/ast/ast.hpp"
|
||||||
#include "query/frontend/opencypher/parser.hpp"
|
#include "query/frontend/opencypher/parser.hpp"
|
||||||
#include "query/interpret/awesome_memgraph_functions.hpp"
|
#include "query/interpret/awesome_memgraph_functions.hpp"
|
||||||
#include "query/interpret/eval.hpp"
|
#include "query/interpret/eval.hpp"
|
||||||
|
#include "query/interpret/frame.hpp"
|
||||||
|
|
||||||
using namespace query;
|
using namespace query;
|
||||||
using testing::Pair;
|
using testing::Pair;
|
||||||
@ -22,7 +24,7 @@ namespace {
|
|||||||
|
|
||||||
struct NoContextExpressionEvaluator {
|
struct NoContextExpressionEvaluator {
|
||||||
NoContextExpressionEvaluator() {}
|
NoContextExpressionEvaluator() {}
|
||||||
Frame frame{0};
|
Frame frame{128};
|
||||||
SymbolTable symbol_table;
|
SymbolTable symbol_table;
|
||||||
Dbms dbms;
|
Dbms dbms;
|
||||||
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
|
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
|
||||||
@ -428,6 +430,112 @@ TEST(ExpressionEvaluator, IsNullOperator) {
|
|||||||
ASSERT_EQ(eval.eval.PopBack().Value<bool>(), true);
|
ASSERT_EQ(eval.eval.PopBack().Value<bool>(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ExpressionEvaluator, PropertyLookup) {
|
||||||
|
AstTreeStorage storage;
|
||||||
|
NoContextExpressionEvaluator eval;
|
||||||
|
Dbms dbms;
|
||||||
|
auto dba = dbms.active();
|
||||||
|
auto v1 = dba->insert_vertex();
|
||||||
|
v1.PropsSet(dba->property("age"), 10);
|
||||||
|
auto *identifier = storage.Create<Identifier>("n");
|
||||||
|
auto node_symbol = eval.symbol_table.CreateSymbol("n");
|
||||||
|
eval.symbol_table[*identifier] = node_symbol;
|
||||||
|
eval.frame[node_symbol] = v1;
|
||||||
|
{
|
||||||
|
auto *op = storage.Create<PropertyLookup>(identifier, dba->property("age"));
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_EQ(eval.eval.PopBack().Value<int64_t>(), 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto *op =
|
||||||
|
storage.Create<PropertyLookup>(identifier, dba->property("height"));
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_TRUE(eval.eval.PopBack().IsNull());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
eval.frame[node_symbol] = TypedValue::Null;
|
||||||
|
auto *op = storage.Create<PropertyLookup>(identifier, dba->property("age"));
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_TRUE(eval.eval.PopBack().IsNull());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpressionEvaluator, LabelsTest) {
|
||||||
|
AstTreeStorage storage;
|
||||||
|
NoContextExpressionEvaluator eval;
|
||||||
|
Dbms dbms;
|
||||||
|
auto dba = dbms.active();
|
||||||
|
auto v1 = dba->insert_vertex();
|
||||||
|
v1.add_label(dba->label("ANIMAL"));
|
||||||
|
v1.add_label(dba->label("DOG"));
|
||||||
|
v1.add_label(dba->label("NICE_DOG"));
|
||||||
|
auto *identifier = storage.Create<Identifier>("n");
|
||||||
|
auto node_symbol = eval.symbol_table.CreateSymbol("n");
|
||||||
|
eval.symbol_table[*identifier] = node_symbol;
|
||||||
|
eval.frame[node_symbol] = v1;
|
||||||
|
{
|
||||||
|
auto *op = storage.Create<LabelsTest>(
|
||||||
|
identifier, std::vector<GraphDbTypes::Label>{dba->label("DOG"),
|
||||||
|
dba->label("ANIMAL")});
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_EQ(eval.eval.PopBack().Value<bool>(), true);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto *op = storage.Create<LabelsTest>(
|
||||||
|
identifier,
|
||||||
|
std::vector<GraphDbTypes::Label>{
|
||||||
|
dba->label("DOG"), dba->label("BAD_DOG"), dba->label("ANIMAL")});
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_EQ(eval.eval.PopBack().Value<bool>(), false);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
eval.frame[node_symbol] = TypedValue::Null;
|
||||||
|
auto *op = storage.Create<LabelsTest>(
|
||||||
|
identifier,
|
||||||
|
std::vector<GraphDbTypes::Label>{
|
||||||
|
dba->label("DOG"), dba->label("BAD_DOG"), dba->label("ANIMAL")});
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_TRUE(eval.eval.PopBack().IsNull());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ExpressionEvaluator, EdgeTypeTest) {
|
||||||
|
AstTreeStorage storage;
|
||||||
|
NoContextExpressionEvaluator eval;
|
||||||
|
Dbms dbms;
|
||||||
|
auto dba = dbms.active();
|
||||||
|
auto v1 = dba->insert_vertex();
|
||||||
|
auto v2 = dba->insert_vertex();
|
||||||
|
auto e = dba->insert_edge(v1, v2, dba->edge_type("TYPE1"));
|
||||||
|
auto *identifier = storage.Create<Identifier>("e");
|
||||||
|
auto edge_symbol = eval.symbol_table.CreateSymbol("e");
|
||||||
|
eval.symbol_table[*identifier] = edge_symbol;
|
||||||
|
eval.frame[edge_symbol] = e;
|
||||||
|
{
|
||||||
|
auto *op = storage.Create<EdgeTypeTest>(
|
||||||
|
identifier, std::vector<GraphDbTypes::EdgeType>{
|
||||||
|
dba->edge_type("TYPE0"), dba->edge_type("TYPE1"),
|
||||||
|
dba->edge_type("TYPE2")});
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_EQ(eval.eval.PopBack().Value<bool>(), true);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto *op = storage.Create<EdgeTypeTest>(
|
||||||
|
identifier, std::vector<GraphDbTypes::EdgeType>{
|
||||||
|
dba->edge_type("TYPE0"), dba->edge_type("TYPE2")});
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_EQ(eval.eval.PopBack().Value<bool>(), false);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
eval.frame[edge_symbol] = TypedValue::Null;
|
||||||
|
auto *op = storage.Create<EdgeTypeTest>(
|
||||||
|
identifier, std::vector<GraphDbTypes::EdgeType>{
|
||||||
|
dba->edge_type("TYPE0"), dba->edge_type("TYPE2")});
|
||||||
|
op->Accept(eval.eval);
|
||||||
|
EXPECT_TRUE(eval.eval.PopBack().IsNull());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ExpressionEvaluator, Aggregation) {
|
TEST(ExpressionEvaluator, Aggregation) {
|
||||||
AstTreeStorage storage;
|
AstTreeStorage storage;
|
||||||
auto aggr = storage.Create<Aggregation>(storage.Create<PrimitiveLiteral>(42),
|
auto aggr = storage.Create<Aggregation>(storage.Create<PrimitiveLiteral>(42),
|
||||||
|
Loading…
Reference in New Issue
Block a user