Property lookup caching (#1168)
This commit is contained in:
167
tests/gql_behave/tests/memgraph_V1/features/map.feature
Normal file
167
tests/gql_behave/tests/memgraph_V1/features/map.feature
Normal file
@@ -0,0 +1,167 @@
|
||||
Feature: Creating map values
|
||||
|
||||
Scenario: Creating a map with multiple properties from a vertex
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (:Employee {name: "Andy", surname: "Walker", age: 24, id: 1234});
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (e:Employee) RETURN {name: e.name, surname: e.surname, age: e.age} AS public_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| public_data |
|
||||
| {age: 24, name: 'Andy', surname: 'Walker'} |
|
||||
|
||||
Scenario: Creating instances of a map with multiple properties from a vertex
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (:Employee {name: "Andy", surname: "Walker", age: 24, id: 1234}), (:Person), (:Person);
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (e:Employee), (n:Person) RETURN {name: e.name, surname: e.surname, age: e.age} AS public_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| public_data |
|
||||
| {age: 24, name: 'Andy', surname: 'Walker'} |
|
||||
| {age: 24, name: 'Andy', surname: 'Walker'} |
|
||||
|
||||
Scenario: Creating a map with multiple properties from each vertex
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (:Cat {name: "Luigi", age: 11}), (:Dog {name: "Don", age: 10}), (:Owner {name: "Ivan"});
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (m:Cat), (n:Dog), (o:Owner) SET o += {catName: m.name, catAge: m.age, dogName: n.name, dogAge: n.age} RETURN o;
|
||||
"""
|
||||
Then the result should be:
|
||||
| o |
|
||||
| (:Owner {catAge: 11, catName: 'Luigi', dogAge: 10, dogName: 'Don', name: 'Ivan'}) |
|
||||
|
||||
Scenario: Creating distinct maps with multiple properties, each from one vertex
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
FOREACH (i in range(1, 5) | CREATE (:Node {prop1: i, prop2: 2 * i}));
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (n) RETURN {prop1: n.prop1, prop2: n.prop2} AS prop_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| prop_data |
|
||||
| {prop1: 1, prop2: 2} |
|
||||
| {prop1: 2, prop2: 4} |
|
||||
| {prop1: 3, prop2: 6} |
|
||||
| {prop1: 4, prop2: 8} |
|
||||
| {prop1: 5, prop2: 10} |
|
||||
|
||||
Scenario: Creating a map with multiple properties from a vertex; one property is null
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (:Employee {name: "Andy", surname: "Walker", age: 24, id: 1234});
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (e:Employee) RETURN {name: e.name, surname: e.surname, age: e.age, null_prop: e.nonexistent} AS public_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| public_data |
|
||||
| {age: 24, name: 'Andy', null_prop: null, surname: 'Walker'} |
|
||||
|
||||
Scenario: Creating a map with multiple properties from an edge
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (m)-[:ROUTE {km: 466, cross_border: true}]->(n);
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH ()-[r:ROUTE]->() RETURN {km: r.km, cross_border: r.cross_border} AS route_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| route_data |
|
||||
| {cross_border: true, km: 466} |
|
||||
|
||||
Scenario: Creating instances of a map with multiple properties from an edge
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (m)-[:ROUTE {km: 466, cross_border: true}]->(n), (:City), (:City);
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (:City), ()-[r:ROUTE]->() RETURN {km: r.km, cross_border: r.cross_border} AS route_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| route_data |
|
||||
| {cross_border: true, km: 466} |
|
||||
| {cross_border: true, km: 466} |
|
||||
|
||||
Scenario: Creating a map with multiple properties from each edge
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (m)-[:HIGHWAY {km: 466, cross_border: true}]->(n), (m)-[:FLIGHT {km: 350, daily: true}]->(n);
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH ()-[h:HIGHWAY]->(), ()-[f:FLIGHT]->()
|
||||
RETURN {km_hwy: h.km, cross_border: h.cross_border, km_air: f.km, daily_flight: f.daily} AS routes_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| routes_data |
|
||||
| {cross_border: true, daily_flight: true, km_air: 350, km_hwy: 466} |
|
||||
|
||||
Scenario: Creating distinct maps with multiple properties, each from one edge
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
MERGE (m:City) MERGE (n:Country) FOREACH (i in range(1, 5) | CREATE (m)-[:IN {prop1: i, prop2: 2 * i}]->(n));
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (m)-[r]->(n) RETURN {prop1: r.prop1, prop2: r.prop2} AS prop_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| prop_data |
|
||||
| {prop1: 1, prop2: 2} |
|
||||
| {prop1: 2, prop2: 4} |
|
||||
| {prop1: 3, prop2: 6} |
|
||||
| {prop1: 4, prop2: 8} |
|
||||
| {prop1: 5, prop2: 10} |
|
||||
|
||||
Scenario: Creating a map with multiple properties from an edge; one property is null
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (m)-[:ROUTE {km: 466, cross_border: true}]->(n);
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH ()-[r:ROUTE]->() RETURN {km: r.km, cross_border: r.cross_border, null_prop: r.nonexistent} AS route_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| route_data |
|
||||
| {cross_border: true, km: 466, null_prop: null} |
|
||||
|
||||
Scenario: Creating a map with multiple properties from both a vertex and an edge
|
||||
Given an empty graph
|
||||
And having executed
|
||||
"""
|
||||
CREATE (m:City {name: "Split", highway_connected: true})-[:ROUTE {km: 466, cross_border: true}]->(n:City {name: "Ljubljana"});
|
||||
"""
|
||||
When executing query:
|
||||
"""
|
||||
MATCH (m:City {name: "Split"})-[r:ROUTE]->()
|
||||
RETURN {km: r.km, cross_border: r.cross_border, start_city: m.name, highway_connected: m.highway_connected} AS route_data;
|
||||
"""
|
||||
Then the result should be:
|
||||
| route_data |
|
||||
| {cross_border: true, highway_connected: true, km: 466, start_city: 'Split'} |
|
||||
@@ -1653,6 +1653,21 @@ TYPED_TEST(QueryPlanTest, MergeNoInput) {
|
||||
EXPECT_EQ(1, CountIterable(dba.Vertices(memgraph::storage::View::OLD)));
|
||||
}
|
||||
|
||||
TYPED_TEST(QueryPlanTest, SetPropertyWithCaching) {
|
||||
// SET (Null).prop = 42
|
||||
auto storage_dba = this->db->Access();
|
||||
memgraph::query::DbAccessor dba(storage_dba.get());
|
||||
SymbolTable symbol_table;
|
||||
auto prop = PROPERTY_PAIR(dba, "property");
|
||||
auto null = LITERAL(TypedValue());
|
||||
auto literal = LITERAL(42);
|
||||
auto n_prop = PROPERTY_LOOKUP(dba, null, prop);
|
||||
auto once = std::make_shared<Once>();
|
||||
auto set_op = std::make_shared<plan::SetProperty>(once, prop.second, n_prop, literal);
|
||||
auto context = MakeContext(this->storage, symbol_table, &dba);
|
||||
EXPECT_EQ(1, PullAll(*set_op, &context));
|
||||
}
|
||||
|
||||
TYPED_TEST(QueryPlanTest, SetPropertyOnNull) {
|
||||
// SET (Null).prop = 42
|
||||
auto storage_dba = this->db->Access();
|
||||
@@ -1717,6 +1732,46 @@ TYPED_TEST(QueryPlanTest, UpdateSetPropertiesFromMap) {
|
||||
EXPECT_EQ(*new_properties, expected_properties);
|
||||
}
|
||||
|
||||
TYPED_TEST(QueryPlanTest, SetPropertiesFromMapWithCaching) {
|
||||
auto storage_dba = this->db->Access();
|
||||
memgraph::query::DbAccessor dba(storage_dba.get());
|
||||
|
||||
// Add a single vertex. ({prop1: 43, prop2: 44})
|
||||
auto vertex_accessor = dba.InsertVertex();
|
||||
auto old_value = vertex_accessor.SetProperty(dba.NameToProperty("prop1"), memgraph::storage::PropertyValue{43});
|
||||
old_value = vertex_accessor.SetProperty(dba.NameToProperty("prop2"), memgraph::storage::PropertyValue{44});
|
||||
EXPECT_EQ(old_value.HasError(), false);
|
||||
EXPECT_EQ(*old_value, memgraph::storage::PropertyValue());
|
||||
dba.AdvanceCommand();
|
||||
EXPECT_EQ(1, CountIterable(dba.Vertices(memgraph::storage::View::OLD)));
|
||||
|
||||
SymbolTable symbol_table;
|
||||
// MATCH (n) SET n += {new_prop1: n.prop1, new_prop2: n.prop2};
|
||||
auto n = MakeScanAll(this->storage, symbol_table, "n");
|
||||
auto prop_new_prop1 = PROPERTY_PAIR(dba, "new_prop1");
|
||||
auto prop_new_prop2 = PROPERTY_PAIR(dba, "new_prop2");
|
||||
std::unordered_map<PropertyIx, Expression *> prop_map;
|
||||
prop_map.emplace(this->storage.GetPropertyIx(prop_new_prop1.first), LITERAL(43));
|
||||
prop_map.emplace(this->storage.GetPropertyIx(prop_new_prop2.first), LITERAL(44));
|
||||
auto *rhs = this->storage.template Create<MapLiteral>(prop_map);
|
||||
|
||||
auto op_type{plan::SetProperties::Op::UPDATE};
|
||||
auto set_op = std::make_shared<plan::SetProperties>(n.op_, n.sym_, rhs, op_type);
|
||||
auto context = MakeContext(this->storage, symbol_table, &dba);
|
||||
PullAll(*set_op, &context);
|
||||
dba.AdvanceCommand();
|
||||
|
||||
auto new_properties = vertex_accessor.Properties(memgraph::storage::View::OLD);
|
||||
std::map<memgraph::storage::PropertyId, memgraph::storage::PropertyValue> expected_properties;
|
||||
expected_properties.emplace(dba.NameToProperty("prop1"), memgraph::storage::PropertyValue(43));
|
||||
expected_properties.emplace(dba.NameToProperty("prop2"), memgraph::storage::PropertyValue(44));
|
||||
expected_properties.emplace(dba.NameToProperty("new_prop1"), memgraph::storage::PropertyValue(43));
|
||||
expected_properties.emplace(dba.NameToProperty("new_prop2"), memgraph::storage::PropertyValue(44));
|
||||
EXPECT_EQ(context.evaluation_context.property_lookups_cache.size(), 0);
|
||||
EXPECT_EQ(new_properties.HasError(), false);
|
||||
EXPECT_EQ(*new_properties, expected_properties);
|
||||
}
|
||||
|
||||
TYPED_TEST(QueryPlanTest, SetLabelsOnNull) {
|
||||
// OPTIONAL MATCH (n) SET n :label
|
||||
auto storage_dba = this->db->Access();
|
||||
|
||||
@@ -1020,7 +1020,7 @@ TYPED_TEST(TestSymbolGenerator, MatchUnionReturnSymbols) {
|
||||
EXPECT_EQ(symbol_table.max_position(), 8);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, MatchUnionParameterNameThrowSemanticExpcetion) {
|
||||
TYPED_TEST(TestSymbolGenerator, MatchUnionParameterNameThrowSemanticException) {
|
||||
// WITH 1 as X, 2 AS Y RETURN * UNION RETURN 3 AS Z, 4 AS Y
|
||||
auto ret = this->storage.template Create<Return>();
|
||||
ret->body_.all_identifiers = true;
|
||||
@@ -1029,7 +1029,7 @@ TYPED_TEST(TestSymbolGenerator, MatchUnionParameterNameThrowSemanticExpcetion) {
|
||||
EXPECT_THROW(memgraph::query::MakeSymbolTable(query), SemanticException);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, MatchUnionParameterNumberThrowSemanticExpcetion) {
|
||||
TYPED_TEST(TestSymbolGenerator, MatchUnionParameterNumberThrowSemanticException) {
|
||||
// WITH 1 as X, 2 AS Y RETURN * UNION RETURN 4 AS Y
|
||||
auto ret = this->storage.template Create<Return>();
|
||||
ret->body_.all_identifiers = true;
|
||||
@@ -1278,3 +1278,166 @@ TYPED_TEST(TestSymbolGenerator, Subqueries) {
|
||||
symbol_table = MakeSymbolTable(query);
|
||||
ASSERT_EQ(symbol_table.max_position(), 13);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, PropertyCachingSingleLookup) {
|
||||
// WITH {icode: 0000} AS item
|
||||
// RETURN {icode: item.icode} AS new_map;
|
||||
|
||||
auto prop1_key = this->storage.GetPropertyIx("icode");
|
||||
auto prop1_val = PROPERTY_LOOKUP(this->dba, "item", this->dba.NameToProperty("icode"));
|
||||
|
||||
auto has_properties = MAP({prop1_key, LITERAL(0000)});
|
||||
auto new_map = MAP({prop1_key, prop1_val});
|
||||
auto query = QUERY(SINGLE_QUERY(WITH(has_properties, AS("item")), RETURN(new_map, AS("new_map"))));
|
||||
|
||||
memgraph::query::MakeSymbolTable(query);
|
||||
|
||||
auto prop1_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[prop1_key])->evaluation_mode_;
|
||||
|
||||
ASSERT_TRUE(prop1_eval_mode == PropertyLookup::EvaluationMode::GET_OWN_PROPERTY);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, PropertyCachingTwoSingleLookups) {
|
||||
// WITH {icode: 0000} AS item1, {icode: 1111} AS item2
|
||||
// RETURN {icode1: item1.icode, icode2: item2.icode} AS new_map;
|
||||
|
||||
auto in_prop1_key = this->storage.GetPropertyIx("icode");
|
||||
auto out_prop1_key = this->storage.GetPropertyIx("icode1");
|
||||
auto out_prop1_val = PROPERTY_LOOKUP(this->dba, "item1", this->dba.NameToProperty("icode"));
|
||||
auto out_prop2_key = this->storage.GetPropertyIx("icode2");
|
||||
auto out_prop2_val = PROPERTY_LOOKUP(this->dba, "item2", this->dba.NameToProperty("icode"));
|
||||
|
||||
auto has_properties1 = MAP({in_prop1_key, LITERAL(0000)});
|
||||
auto has_properties2 = MAP({in_prop1_key, LITERAL(1111)});
|
||||
auto new_map = MAP({out_prop1_key, out_prop1_val}, {out_prop2_key, out_prop2_val});
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(has_properties1, AS("item1"), has_properties2, AS("item2")), RETURN(new_map, AS("new_map"))));
|
||||
|
||||
memgraph::query::MakeSymbolTable(query);
|
||||
|
||||
auto prop1_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop1_key])->evaluation_mode_;
|
||||
auto prop2_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop2_key])->evaluation_mode_;
|
||||
|
||||
ASSERT_TRUE(prop1_eval_mode == PropertyLookup::EvaluationMode::GET_OWN_PROPERTY);
|
||||
ASSERT_TRUE(prop2_eval_mode == PropertyLookup::EvaluationMode::GET_OWN_PROPERTY);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, PropertyCachingMultipleLookup) {
|
||||
// WITH {icode: 0000, price: 10} AS item
|
||||
// RETURN {icode: item.icode, price: item.price} AS new_map;
|
||||
|
||||
auto prop1_key = this->storage.GetPropertyIx("icode");
|
||||
auto prop1_val = PROPERTY_LOOKUP(this->dba, "item", this->dba.NameToProperty("icode"));
|
||||
auto prop2_key = this->storage.GetPropertyIx("price");
|
||||
auto prop2_val = PROPERTY_LOOKUP(this->dba, "item", this->dba.NameToProperty("price"));
|
||||
|
||||
auto has_properties = MAP({prop1_key, LITERAL(0000)}, {prop2_key, LITERAL(10)});
|
||||
auto new_map = MAP({prop1_key, prop1_val}, {prop2_key, prop2_val});
|
||||
auto query = QUERY(SINGLE_QUERY(WITH(has_properties, AS("item")), RETURN(new_map, AS("new_map"))));
|
||||
|
||||
memgraph::query::MakeSymbolTable(query);
|
||||
|
||||
auto prop1_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[prop1_key])->evaluation_mode_;
|
||||
auto prop2_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[prop2_key])->evaluation_mode_;
|
||||
|
||||
ASSERT_TRUE(prop1_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
ASSERT_TRUE(prop2_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, PropertyCachingTwoMultipleLookups) {
|
||||
// WITH {icode: 0000, price: 10} AS item1, {icode: 1111, price: 16} AS item2
|
||||
// RETURN {icode1: item1.icode, price1: item1.price, icode2: item2.icode, price2: item2.price} AS new_map;
|
||||
|
||||
auto in_prop1_key = this->storage.GetPropertyIx("icode");
|
||||
auto in_prop2_key = this->storage.GetPropertyIx("price");
|
||||
|
||||
auto out_prop1_key = this->storage.GetPropertyIx("icode1");
|
||||
auto out_prop1_val = PROPERTY_LOOKUP(this->dba, "item1", this->dba.NameToProperty("icode"));
|
||||
auto out_prop2_key = this->storage.GetPropertyIx("price1");
|
||||
auto out_prop2_val = PROPERTY_LOOKUP(this->dba, "item1", this->dba.NameToProperty("price"));
|
||||
auto out_prop3_key = this->storage.GetPropertyIx("icode2");
|
||||
auto out_prop3_val = PROPERTY_LOOKUP(this->dba, "item2", this->dba.NameToProperty("icode"));
|
||||
auto out_prop4_key = this->storage.GetPropertyIx("price2");
|
||||
auto out_prop4_val = PROPERTY_LOOKUP(this->dba, "item2", this->dba.NameToProperty("price"));
|
||||
|
||||
auto has_properties1 = MAP({in_prop1_key, LITERAL(0000)}, {in_prop2_key, LITERAL(10)});
|
||||
auto has_properties2 = MAP({in_prop1_key, LITERAL(1111)}, {in_prop2_key, LITERAL(16)});
|
||||
auto new_map = MAP({out_prop1_key, out_prop1_val}, {out_prop2_key, out_prop2_val}, {out_prop3_key, out_prop3_val},
|
||||
{out_prop4_key, out_prop4_val});
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(has_properties1, AS("item1"), has_properties2, AS("item2")), RETURN(new_map, AS("new_map"))));
|
||||
|
||||
memgraph::query::MakeSymbolTable(query);
|
||||
|
||||
auto prop1_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop1_key])->evaluation_mode_;
|
||||
auto prop2_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop2_key])->evaluation_mode_;
|
||||
auto prop3_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop3_key])->evaluation_mode_;
|
||||
auto prop4_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop4_key])->evaluation_mode_;
|
||||
|
||||
ASSERT_TRUE(prop1_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
ASSERT_TRUE(prop2_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
ASSERT_TRUE(prop3_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
ASSERT_TRUE(prop4_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, PropertyCachingMixedLookups1) {
|
||||
// WITH {icode: 0000, price: 10} AS item1, {icode: 1111, price: 16} AS item2
|
||||
// RETURN {icode1: item1.icode, price1: item1.price, icode2: item2.icode} AS new_map;
|
||||
|
||||
auto in_prop1_key = this->storage.GetPropertyIx("icode");
|
||||
auto in_prop2_key = this->storage.GetPropertyIx("price");
|
||||
|
||||
auto out_prop1_key = this->storage.GetPropertyIx("icode1");
|
||||
auto out_prop1_val = PROPERTY_LOOKUP(this->dba, "item1", this->dba.NameToProperty("icode"));
|
||||
auto out_prop2_key = this->storage.GetPropertyIx("price1");
|
||||
auto out_prop2_val = PROPERTY_LOOKUP(this->dba, "item1", this->dba.NameToProperty("price"));
|
||||
auto out_prop3_key = this->storage.GetPropertyIx("icode2");
|
||||
auto out_prop3_val = PROPERTY_LOOKUP(this->dba, "item2", this->dba.NameToProperty("icode"));
|
||||
|
||||
auto has_properties1 = MAP({in_prop1_key, LITERAL(0000)}, {in_prop2_key, LITERAL(10)});
|
||||
auto has_properties2 = MAP({in_prop1_key, LITERAL(1111)}, {in_prop2_key, LITERAL(16)});
|
||||
auto new_map = MAP({out_prop1_key, out_prop1_val}, {out_prop2_key, out_prop2_val}, {out_prop3_key, out_prop3_val});
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(has_properties1, AS("item1"), has_properties2, AS("item2")), RETURN(new_map, AS("new_map"))));
|
||||
|
||||
memgraph::query::MakeSymbolTable(query);
|
||||
|
||||
auto prop1_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop1_key])->evaluation_mode_;
|
||||
auto prop2_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop2_key])->evaluation_mode_;
|
||||
auto prop3_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop3_key])->evaluation_mode_;
|
||||
|
||||
ASSERT_TRUE(prop1_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
ASSERT_TRUE(prop2_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
ASSERT_TRUE(prop3_eval_mode == PropertyLookup::EvaluationMode::GET_OWN_PROPERTY);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestSymbolGenerator, PropertyCachingMixedLookups2) {
|
||||
// WITH {icode: 0000, price: 10} AS item1, {icode: 1111, price: 16} AS item2
|
||||
// RETURN {icode1: item1.icode, icode2: item2.icode, price2: item2.price} AS new_map;
|
||||
|
||||
auto in_prop1_key = this->storage.GetPropertyIx("icode");
|
||||
auto in_prop2_key = this->storage.GetPropertyIx("price");
|
||||
|
||||
auto out_prop1_key = this->storage.GetPropertyIx("icode1");
|
||||
auto out_prop1_val = PROPERTY_LOOKUP(this->dba, "item1", this->dba.NameToProperty("icode"));
|
||||
auto out_prop3_key = this->storage.GetPropertyIx("icode2");
|
||||
auto out_prop3_val = PROPERTY_LOOKUP(this->dba, "item2", this->dba.NameToProperty("icode"));
|
||||
auto out_prop4_key = this->storage.GetPropertyIx("price2");
|
||||
auto out_prop4_val = PROPERTY_LOOKUP(this->dba, "item2", this->dba.NameToProperty("price"));
|
||||
|
||||
auto has_properties1 = MAP({in_prop1_key, LITERAL(0000)}, {in_prop2_key, LITERAL(10)});
|
||||
auto has_properties2 = MAP({in_prop1_key, LITERAL(1111)}, {in_prop2_key, LITERAL(16)});
|
||||
auto new_map = MAP({out_prop1_key, out_prop1_val}, {out_prop3_key, out_prop3_val}, {out_prop4_key, out_prop4_val});
|
||||
auto query = QUERY(
|
||||
SINGLE_QUERY(WITH(has_properties1, AS("item1"), has_properties2, AS("item2")), RETURN(new_map, AS("new_map"))));
|
||||
|
||||
memgraph::query::MakeSymbolTable(query);
|
||||
|
||||
auto prop1_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop1_key])->evaluation_mode_;
|
||||
auto prop3_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop3_key])->evaluation_mode_;
|
||||
auto prop4_eval_mode = dynamic_cast<PropertyLookup *>(new_map->elements_[out_prop4_key])->evaluation_mode_;
|
||||
|
||||
ASSERT_TRUE(prop1_eval_mode == PropertyLookup::EvaluationMode::GET_OWN_PROPERTY);
|
||||
ASSERT_TRUE(prop3_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
ASSERT_TRUE(prop4_eval_mode == PropertyLookup::EvaluationMode::GET_ALL_PROPERTIES);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user