diff --git a/src/query/common.hpp b/src/query/common.hpp index eadd9b530..96b3311a7 100644 --- a/src/query/common.hpp +++ b/src/query/common.hpp @@ -21,12 +21,8 @@ std::string ParseParameter(const std::string &s); * see the OLD graph state (the latest state before the * current transaction+command), or NEW (state as * changed by the current transaction+command). - * - * Also some part of query execution could leave - * the graph state AS_IS, that is as it was left - * by some previous part of execution. */ -enum class GraphView { AS_IS, OLD, NEW }; +enum class GraphView { OLD, NEW }; /** * Helper function for recursively reconstructing all the accessors in the @@ -68,4 +64,4 @@ class TypedValueVectorCompare { // - (list, map, path, vertex, edge) can't compare to anything bool TypedValueCompare(const TypedValue &a, const TypedValue &b) const; }; -} +} // namespace query diff --git a/src/query/interpret/eval.hpp b/src/query/interpret/eval.hpp index 22904e5b3..153d47b13 100644 --- a/src/query/interpret/eval.hpp +++ b/src/query/interpret/eval.hpp @@ -22,7 +22,7 @@ class ExpressionEvaluator : public TreeVisitor { ExpressionEvaluator(Frame &frame, const Parameters ¶meters, const SymbolTable &symbol_table, database::GraphDbAccessor &db_accessor, - GraphView graph_view = GraphView::AS_IS) + GraphView graph_view) : frame_(frame), parameters_(parameters), symbol_table_(symbol_table), @@ -444,7 +444,6 @@ class ExpressionEvaluator : public TreeVisitor { // If the given TypedValue contains accessors, switch them to New or Old, // depending on use_new_ flag. void SwitchAccessors(TypedValue &value) { - if (graph_view_ == GraphView::AS_IS) return; switch (value.type()) { case TypedValue::Type::Vertex: { auto &vertex = value.Value(); diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index 165d9a8f3..a14205533 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -353,10 +353,7 @@ ScanAll::ScanAll(const std::shared_ptr &input, Symbol output_symbol, GraphView graph_view) : input_(input ? input : std::make_shared()), output_symbol_(output_symbol), - graph_view_(graph_view) { - CHECK(graph_view != GraphView::AS_IS) - << "ScanAll must have explicitly defined GraphView"; -} + graph_view_(graph_view) {} ACCEPT_WITH_INPUT(ScanAll) @@ -414,32 +411,32 @@ std::unique_ptr ScanAllByLabelPropertyRange::MakeCursor( -> std::experimental::optional { - ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, db, graph_view_); - auto convert = [&evaluator](const auto &bound) - -> std::experimental::optional> { - if (!bound) return std::experimental::nullopt; - auto value = bound->value()->Accept(evaluator); - try { - return std::experimental::make_optional( - utils::Bound(value, bound->type())); - } catch (const TypedValueException &) { - throw QueryRuntimeException( - "'{}' cannot be used as a property value.", value.type()); - } - }; - auto maybe_lower = convert(lower_bound()); - auto maybe_upper = convert(upper_bound()); - // If any bound is null, then the comparison would result in nulls. This - // is treated as not satisfying the filter, so return no vertices. - if (maybe_lower && maybe_lower->value().IsNull()) - return std::experimental::nullopt; - if (maybe_upper && maybe_upper->value().IsNull()) - return std::experimental::nullopt; + ExpressionEvaluator evaluator(frame, context.parameters_, + context.symbol_table_, db, graph_view_); + auto convert = [&evaluator](const auto &bound) + -> std::experimental::optional> { + if (!bound) return std::experimental::nullopt; + auto value = bound->value()->Accept(evaluator); + try { return std::experimental::make_optional( - db.Vertices(label_, property_, maybe_lower, maybe_upper, - graph_view_ == GraphView::NEW)); - }; + utils::Bound(value, bound->type())); + } catch (const TypedValueException &) { + throw QueryRuntimeException("'{}' cannot be used as a property value.", + value.type()); + } + }; + auto maybe_lower = convert(lower_bound()); + auto maybe_upper = convert(upper_bound()); + // If any bound is null, then the comparison would result in nulls. This + // is treated as not satisfying the filter, so return no vertices. + if (maybe_lower && maybe_lower->value().IsNull()) + return std::experimental::nullopt; + if (maybe_upper && maybe_upper->value().IsNull()) + return std::experimental::nullopt; + return std::experimental::make_optional( + db.Vertices(label_, property_, maybe_lower, maybe_upper, + graph_view_ == GraphView::NEW)); + }; return std::make_unique>( output_symbol_, input_->MakeCursor(db), std::move(vertices), db); } @@ -462,18 +459,18 @@ std::unique_ptr ScanAllByLabelPropertyValue::MakeCursor( auto vertices = [this, &db](Frame &frame, Context &context) -> std::experimental::optional { - ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, db, graph_view_); - auto value = expression_->Accept(evaluator); - if (value.IsNull()) return std::experimental::nullopt; - try { - return std::experimental::make_optional(db.Vertices( - label_, property_, value, graph_view_ == GraphView::NEW)); - } catch (const TypedValueException &) { - throw QueryRuntimeException( - "'{}' cannot be used as a property value.", value.type()); - } - }; + ExpressionEvaluator evaluator(frame, context.parameters_, + context.symbol_table_, db, graph_view_); + auto value = expression_->Accept(evaluator); + if (value.IsNull()) return std::experimental::nullopt; + try { + return std::experimental::make_optional( + db.Vertices(label_, property_, value, graph_view_ == GraphView::NEW)); + } catch (const TypedValueException &) { + throw QueryRuntimeException("'{}' cannot be used as a property value.", + value.type()); + } + }; return std::make_unique>( output_symbol_, input_->MakeCursor(db), std::move(vertices), db); } @@ -666,8 +663,6 @@ void SwitchAccessor(TAccessor &accessor, GraphView graph_view) { case GraphView::OLD: accessor.SwitchOld(); break; - case GraphView::AS_IS: - break; } } } // namespace @@ -907,7 +902,8 @@ class ExpandVariableCursor : public Cursor { // Evaluate the upper and lower bounds. ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, db_); + context.symbol_table_, db_, + self_.graph_view_); auto calc_bound = [&evaluator](auto &bound) { auto value = EvaluateInt(evaluator, bound, "Variable expansion bound"); if (value < 0) @@ -1055,7 +1051,7 @@ class ExpandBreadthFirstCursor : public query::plan::Cursor { : self_(self), db_(db), input_cursor_(self_.input_->MakeCursor(db)) {} bool Pull(Frame &frame, Context &context) override { - // evaulator for the filtering condition + // evaluator for the filtering condition ExpressionEvaluator evaluator(frame, context.parameters_, context.symbol_table_, db_, self_.graph_view_); @@ -1224,7 +1220,8 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor { // For the given (edge, vertex, weight, depth) tuple checks if they // satisfy the "where" condition. if so, places them in the priority queue. auto expand_pair = [this, &evaluator, &frame, &create_state]( - EdgeAccessor edge, VertexAccessor vertex, double weight, int depth) { + EdgeAccessor edge, VertexAccessor vertex, + double weight, int depth) { SwitchAccessor(edge, self_.graph_view_); SwitchAccessor(vertex, self_.graph_view_); @@ -2433,10 +2430,11 @@ Skip::SkipCursor::SkipCursor(const Skip &self, database::GraphDbAccessor &db) bool Skip::SkipCursor::Pull(Frame &frame, Context &context) { while (input_cursor_->Pull(frame, context)) { if (to_skip_ == -1) { - // first successful pull from the input - // evaluate the skip expression + // First successful pull from the input, evaluate the skip expression. The + // skip expression doesn't contain identifiers so graph view parameter is + // not important. ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, db_); + context.symbol_table_, db_, GraphView::OLD); TypedValue to_skip = self_.expression_->Accept(evaluator); if (to_skip.type() != TypedValue::Type::Int) throw QueryRuntimeException("Result of SKIP expression must be an int"); @@ -2484,13 +2482,15 @@ Limit::LimitCursor::LimitCursor(const Limit &self, : self_(self), db_(db), input_cursor_(self_.input_->MakeCursor(db)) {} bool Limit::LimitCursor::Pull(Frame &frame, Context &context) { - // we need to evaluate the limit expression before the first input Pull - // because it might be 0 and thereby we shouldn't Pull from input at all - // we can do this before Pulling from the input because the limit - // expression is not allowed to contain any identifiers + // We need to evaluate the limit expression before the first input Pull + // because it might be 0 and thereby we shouldn't Pull from input at all. + // We can do this before Pulling from the input because the limit expression + // is not allowed to contain any identifiers. if (limit_ == -1) { + // Limit expression doesn't contain identifiers so graph view is not + // important. ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, db_); + context.symbol_table_, db_, GraphView::OLD); TypedValue limit = self_.expression_->Accept(evaluator); if (limit.type() != TypedValue::Type::Int) throw QueryRuntimeException("Result of LIMIT expression must be an int"); @@ -2552,7 +2552,7 @@ OrderBy::OrderByCursor::OrderByCursor(const OrderBy &self, bool OrderBy::OrderByCursor::Pull(Frame &frame, Context &context) { if (!did_pull_all_) { ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, db_); + context.symbol_table_, db_, GraphView::OLD); while (input_cursor_->Pull(frame, context)) { // collect the order_by elements std::vector order_by; @@ -2782,7 +2782,7 @@ bool Unwind::UnwindCursor::Pull(Frame &frame, Context &context) { // successful pull from input, initialize value and iterator ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, db_); + context.symbol_table_, db_, GraphView::OLD); TypedValue input_value = self_.input_expression_->Accept(evaluator); if (input_value.type() != TypedValue::Type::List) throw QueryRuntimeException("UNWIND only accepts list values, got '{}'", @@ -3501,7 +3501,8 @@ class PullRemoteOrderByCursor : public Cursor { bool Pull(Frame &frame, Context &context) { if (context.db_accessor_.should_abort()) throw HintedAbortError(); ExpressionEvaluator evaluator(frame, context.parameters_, - context.symbol_table_, context.db_accessor_); + context.symbol_table_, context.db_accessor_, + GraphView::OLD); auto evaluate_result = [this, &evaluator]() { std::vector order_by; diff --git a/src/query/plan/operator.lcp b/src/query/plan/operator.lcp index 656bc15b4..b4dcb07c7 100644 --- a/src/query/plan/operator.lcp +++ b/src/query/plan/operator.lcp @@ -645,7 +645,7 @@ expansion") const std::vector &edge_types, const std::shared_ptr &input, Symbol input_symbol, bool existing_node, - GraphView graph_view = GraphView::AS_IS); + GraphView graph_view); cpp<#) (:protected #>cpp @@ -808,7 +808,7 @@ pulled.") Symbol input_symbol, bool existing_node, Lambda filter_lambda, std::experimental::optional weight_lambda, std::experimental::optional total_weight, - GraphView graph_view = GraphView::AS_IS); + GraphView graph_view); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; std::unique_ptr MakeCursor( diff --git a/tests/unit/query_cost_estimator.cpp b/tests/unit/query_cost_estimator.cpp index dd410acc3..6f2d83a56 100644 --- a/tests/unit/query_cost_estimator.cpp +++ b/tests/unit/query_cost_estimator.cpp @@ -163,7 +163,7 @@ TEST_F(QueryCostEstimator, ScanAllByLabelPropertyRangeConstExpr) { TEST_F(QueryCostEstimator, Expand) { MakeOp(NextSymbol(), NextSymbol(), EdgeAtom::Direction::IN, std::vector{}, last_op_, NextSymbol(), - false); + false, GraphView::OLD); EXPECT_COST(CardParam::kExpand * CostParam::kExpand); } @@ -173,7 +173,7 @@ TEST_F(QueryCostEstimator, ExpandVariable) { EdgeAtom::Direction::IN, std::vector{}, false, nullptr, nullptr, last_op_, NextSymbol(), false, ExpandVariable::Lambda{NextSymbol(), NextSymbol(), nullptr}, - std::experimental::nullopt, std::experimental::nullopt); + std::experimental::nullopt, std::experimental::nullopt, GraphView::OLD); EXPECT_COST(CardParam::kExpandVariable * CostParam::kExpandVariable); } @@ -199,11 +199,12 @@ TEST_F(QueryCostEstimator, ExpandUniquenessFilter) { } TEST_F(QueryCostEstimator, UnwindLiteral) { - TEST_OP(MakeOp( - last_op_, storage_.Create( - std::vector(7, nullptr)), - NextSymbol()), - CostParam::kUnwind, 7); + TEST_OP( + MakeOp( + last_op_, + storage_.Create(std::vector(7, nullptr)), + NextSymbol()), + CostParam::kUnwind, 7); } TEST_F(QueryCostEstimator, UnwindNoLiteral) { diff --git a/tests/unit/query_expression_evaluator.cpp b/tests/unit/query_expression_evaluator.cpp index f1f6f0bdd..b8c862d46 100644 --- a/tests/unit/query_expression_evaluator.cpp +++ b/tests/unit/query_expression_evaluator.cpp @@ -33,7 +33,8 @@ struct NoContextExpressionEvaluator { database::SingleNode db; database::GraphDbAccessor dba{db}; Parameters parameters; - ExpressionEvaluator eval{frame, parameters, symbol_table, dba}; + ExpressionEvaluator eval{frame, parameters, symbol_table, dba, + GraphView::OLD}; }; TypedValue EvaluateFunction(const std::string &function_name, @@ -44,7 +45,8 @@ TypedValue EvaluateFunction(const std::string &function_name, database::GraphDbAccessor dba(db); Frame frame{128}; Parameters parameters; - ExpressionEvaluator eval{frame, parameters, symbol_table, dba}; + ExpressionEvaluator eval{frame, parameters, symbol_table, dba, + GraphView::OLD}; std::vector expressions; for (const auto &arg : args) { @@ -719,7 +721,8 @@ TEST(ExpressionEvaluator, Aggregation) { database::SingleNode db; database::GraphDbAccessor dba(db); Parameters parameters; - ExpressionEvaluator eval{frame, parameters, symbol_table, dba}; + ExpressionEvaluator eval{frame, parameters, symbol_table, dba, + GraphView::OLD}; auto value = aggr->Accept(eval); EXPECT_EQ(value.Value(), 1); } diff --git a/tests/unit/query_plan_accumulate_aggregate.cpp b/tests/unit/query_plan_accumulate_aggregate.cpp index 48cec6390..6fb162a46 100644 --- a/tests/unit/query_plan_accumulate_aggregate.cpp +++ b/tests/unit/query_plan_accumulate_aggregate.cpp @@ -42,8 +42,9 @@ TEST(QueryPlan, Accumulate) { SymbolTable symbol_table; auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::BOTH, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD); auto one = LITERAL(1); auto n_p = PROPERTY_LOOKUP("n", prop); diff --git a/tests/unit/query_plan_common.hpp b/tests/unit/query_plan_common.hpp index 7a52145ed..9bfc53798 100644 --- a/tests/unit/query_plan_common.hpp +++ b/tests/unit/query_plan_common.hpp @@ -176,7 +176,7 @@ ExpandTuple MakeExpand(AstTreeStorage &storage, SymbolTable &symbol_table, EdgeAtom::Direction direction, const std::vector &edge_types, const std::string &node_identifier, bool existing_node, - GraphView graph_view = GraphView::AS_IS) { + GraphView graph_view) { auto edge = EDGE(edge_identifier, direction); auto edge_sym = symbol_table.CreateSymbol(edge_identifier, true); symbol_table[*edge->identifier_] = edge_sym; diff --git a/tests/unit/query_plan_create_set_remove_delete.cpp b/tests/unit/query_plan_create_set_remove_delete.cpp index a4d2ca4d3..63e7014b7 100644 --- a/tests/unit/query_plan_create_set_remove_delete.cpp +++ b/tests/unit/query_plan_create_set_remove_delete.cpp @@ -295,8 +295,9 @@ TEST(QueryPlan, Delete) { // delete all remaining edges { auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::OUT, {}, "m", false, GraphView::NEW); auto r_get = storage.Create("r"); symbol_table[*r_get] = r_m.edge_sym_; auto delete_op = std::make_shared( @@ -348,8 +349,9 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) { SymbolTable symbol_table; auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::BOTH, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD); // getter expressions for deletion auto n_get = storage.Create("n"); @@ -471,8 +473,9 @@ TEST(QueryPlan, SetProperty) { // scan (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD); // set prop1 to 42 on n and r auto prop1 = dba.Property("prop1"); @@ -522,8 +525,9 @@ TEST(QueryPlan, SetProperties) { // scan (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD); auto op = update ? plan::SetProperties::Op::UPDATE : plan::SetProperties::Op::REPLACE; @@ -625,8 +629,9 @@ TEST(QueryPlan, RemoveProperty) { // scan (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD); auto n_p = PROPERTY_LOOKUP("n", prop1); symbol_table[*n_p->expression_] = n.sym_; @@ -702,8 +707,9 @@ TEST(QueryPlan, NodeFilterSet) { // MATCH (n {prop: 42}) -[r]- (m) auto scan_all = MakeScanAll(storage, symbol_table, "n"); scan_all.node_->properties_[prop] = LITERAL(42); - auto expand = MakeExpand(storage, symbol_table, scan_all.op_, scan_all.sym_, - "r", EdgeAtom::Direction::BOTH, {}, "m", false); + auto expand = + MakeExpand(storage, symbol_table, scan_all.op_, scan_all.sym_, "r", + EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD); auto *filter_expr = EQ(storage.Create(scan_all.node_->identifier_, prop), LITERAL(42)); @@ -741,8 +747,9 @@ TEST(QueryPlan, FilterRemove) { // MATCH (n) -[r]- (m) WHERE n.prop < 43 auto scan_all = MakeScanAll(storage, symbol_table, "n"); scan_all.node_->properties_[prop] = LITERAL(42); - auto expand = MakeExpand(storage, symbol_table, scan_all.op_, scan_all.sym_, - "r", EdgeAtom::Direction::BOTH, {}, "m", false); + auto expand = + MakeExpand(storage, symbol_table, scan_all.op_, scan_all.sym_, "r", + EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD); auto filter_prop = PROPERTY_LOOKUP("n", prop); symbol_table[*filter_prop->expression_] = scan_all.sym_; auto filter = @@ -803,8 +810,9 @@ TEST(QueryPlan, Merge) { auto n = MakeScanAll(storage, symbol_table, "n"); // merge_match branch - auto r_m = MakeExpand(storage, symbol_table, std::make_shared(), n.sym_, - "r", EdgeAtom::Direction::BOTH, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, std::make_shared(), n.sym_, "r", + EdgeAtom::Direction::BOTH, {}, "m", false, GraphView::OLD); auto m_p = PROPERTY_LOOKUP("m", prop); symbol_table[*m_p->expression_] = r_m.node_sym_; auto m_set = std::make_shared(r_m.op_, m_p, LITERAL(1)); diff --git a/tests/unit/query_plan_match_filter_return.cpp b/tests/unit/query_plan_match_filter_return.cpp index 1d00e6517..5a91994e2 100644 --- a/tests/unit/query_plan_match_filter_return.cpp +++ b/tests/unit/query_plan_match_filter_return.cpp @@ -418,10 +418,10 @@ TEST_F(ExpandFixture, Expand) { return PullAll(produce, dba_, symbol_table); }; - EXPECT_EQ(2, test_expand(EdgeAtom::Direction::OUT, GraphView::AS_IS)); - EXPECT_EQ(2, test_expand(EdgeAtom::Direction::IN, GraphView::AS_IS)); - EXPECT_EQ(4, test_expand(EdgeAtom::Direction::BOTH, GraphView::AS_IS)); - // + EXPECT_EQ(2, test_expand(EdgeAtom::Direction::OUT, GraphView::OLD)); + EXPECT_EQ(2, test_expand(EdgeAtom::Direction::IN, GraphView::OLD)); + EXPECT_EQ(4, test_expand(EdgeAtom::Direction::BOTH, GraphView::OLD)); + // test that expand works well for both old and new graph state v1.Reconstruct(); v2.Reconstruct(); @@ -442,8 +442,9 @@ TEST_F(ExpandFixture, Expand) { TEST_F(ExpandFixture, ExpandPath) { auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD); Symbol path_sym = symbol_table.CreateSymbol("path", true); auto path = std::make_shared( r_m.op_, path_sym, @@ -540,7 +541,7 @@ class QueryPlanExpandVariable : public testing::Test { const std::vector &edge_types, std::experimental::optional lower, std::experimental::optional upper, Symbol edge_sym, - const std::string &node_to, GraphView graph_view = GraphView::AS_IS, + const std::string &node_to, GraphView graph_view, bool is_reverse = false) { auto n_from = MakeScanAll(storage, symbol_table, node_from, input_op); auto filter_op = std::make_shared( @@ -628,7 +629,7 @@ TEST_F(QueryPlanExpandVariable, OneVariableExpansion) { auto e = Edge("r", direction); return GetEdgeListSizes( AddMatch(nullptr, "n", layer, direction, {}, lower, - upper, e, "m", GraphView::AS_IS, reverse), + upper, e, "m", GraphView::OLD, reverse), e); }; @@ -691,18 +692,19 @@ TEST_F(QueryPlanExpandVariable, EdgeUniquenessSingleAndVariableExpansion) { if (single_expansion_before) { symbols.push_back(Edge("r0", direction)); last_op = AddMatch(last_op, "n0", layer, direction, {}, lower, - upper, symbols.back(), "m0"); + upper, symbols.back(), "m0", GraphView::OLD); } auto var_length_sym = Edge("r1", direction); symbols.push_back(var_length_sym); - last_op = AddMatch(last_op, "n1", layer, direction, {}, - lower, upper, var_length_sym, "m1"); + last_op = + AddMatch(last_op, "n1", layer, direction, {}, lower, + upper, var_length_sym, "m1", GraphView::OLD); if (!single_expansion_before) { symbols.push_back(Edge("r2", direction)); last_op = AddMatch(last_op, "n2", layer, direction, {}, lower, - upper, symbols.back(), "m2"); + upper, symbols.back(), "m2", GraphView::OLD); } if (add_uniqueness_check) { @@ -731,11 +733,13 @@ TEST_F(QueryPlanExpandVariable, EdgeUniquenessTwoVariableExpansions) { std::experimental::optional upper, bool add_uniqueness_check) { auto e1 = Edge("r1", direction); - auto first = AddMatch(nullptr, "n1", layer, direction, {}, - lower, upper, e1, "m1"); + auto first = + AddMatch(nullptr, "n1", layer, direction, {}, lower, + upper, e1, "m1", GraphView::OLD); auto e2 = Edge("r2", direction); - auto last_op = AddMatch(first, "n2", layer, direction, {}, - lower, upper, e2, "m2"); + auto last_op = + AddMatch(first, "n2", layer, direction, {}, lower, + upper, e2, "m2", GraphView::OLD); if (add_uniqueness_check) { last_op = std::make_shared>( last_op, e2, std::vector{e1}); @@ -785,8 +789,9 @@ TEST_F(QueryPlanExpandVariable, GraphState) { TEST_F(QueryPlanExpandVariable, NamedPath) { auto e = Edge("r", EdgeAtom::Direction::OUT); - auto expand = AddMatch( - nullptr, "n", 0, EdgeAtom::Direction::OUT, {}, 2, 2, e, "m"); + auto expand = + AddMatch(nullptr, "n", 0, EdgeAtom::Direction::OUT, {}, 2, + 2, e, "m", GraphView::OLD); auto find_symbol = [this](const std::string &name) { for (const auto &pos_sym : symbol_table.table()) if (pos_sym.second.name() == name) return pos_sym.second; @@ -876,7 +881,7 @@ class QueryPlanExpandBreadthFirst : public testing::Test { // defines and performs a breadth-first expansion with the given params // returns a vector of pairs. each pair is (vector-of-edges, vertex) auto ExpandBF(EdgeAtom::Direction direction, int max_depth, Expression *where, - GraphView graph_view = GraphView::AS_IS, + GraphView graph_view, std::experimental::optional node_id = 0, ScanAllTuple *existing_node_input = nullptr) { // scan the nodes optionally filtering on property value @@ -934,7 +939,8 @@ class QueryPlanExpandBreadthFirst : public testing::Test { #define EXPECT_EITHER(value, a, b) EXPECT_TRUE(value == a || value == b) TEST_F(QueryPlanExpandBreadthFirst, Basic) { - auto results = ExpandBF(EdgeAtom::Direction::BOTH, 1000, LITERAL(true)); + auto results = + ExpandBF(EdgeAtom::Direction::BOTH, 1000, LITERAL(true), GraphView::OLD); ASSERT_EQ(results.size(), 3); @@ -955,7 +961,8 @@ TEST_F(QueryPlanExpandBreadthFirst, Basic) { TEST_F(QueryPlanExpandBreadthFirst, EdgeDirection) { { - auto results = ExpandBF(EdgeAtom::Direction::IN, 1000, LITERAL(true)); + auto results = + ExpandBF(EdgeAtom::Direction::IN, 1000, LITERAL(true), GraphView::OLD); ASSERT_EQ(results.size(), 3); EXPECT_EQ(GetProp(results[0].second), 2); EXPECT_EQ(GetProp(results[1].second), 3); @@ -964,7 +971,8 @@ TEST_F(QueryPlanExpandBreadthFirst, EdgeDirection) { // assume edges are OK because vertices are (tested before) } { - auto results = ExpandBF(EdgeAtom::Direction::OUT, 1000, LITERAL(true)); + auto results = + ExpandBF(EdgeAtom::Direction::OUT, 1000, LITERAL(true), GraphView::OLD); ASSERT_EQ(results.size(), 3); EXPECT_EQ(GetProp(results[0].second), 1); EXPECT_EQ(GetProp(results[1].second), 3); @@ -976,15 +984,15 @@ TEST_F(QueryPlanExpandBreadthFirst, EdgeDirection) { TEST_F(QueryPlanExpandBreadthFirst, Where) { { - auto results = - ExpandBF(EdgeAtom::Direction::BOTH, 1000, PropNe(inner_node, 2)); + auto results = ExpandBF(EdgeAtom::Direction::BOTH, 1000, + PropNe(inner_node, 2), GraphView::OLD); ASSERT_EQ(results.size(), 2); EXPECT_EQ(GetProp(results[0].second), 1); EXPECT_EQ(GetProp(results[1].second), 3); } { - auto results = - ExpandBF(EdgeAtom::Direction::BOTH, 1000, PropNe(inner_edge, 20)); + auto results = ExpandBF(EdgeAtom::Direction::BOTH, 1000, + PropNe(inner_edge, 20), GraphView::OLD); ASSERT_EQ(results.size(), 3); EXPECT_EQ(GetProp(results[0].second), 1); EXPECT_EITHER(GetProp(results[1].second), 3, 2); @@ -1014,7 +1022,7 @@ TEST_F(QueryPlanExpandBreadthFirst, GraphState) { TEST_F(QueryPlanExpandBreadthFirst, MultipleInputs) { auto results = ExpandBF(EdgeAtom::Direction::OUT, 1000, LITERAL(true), - GraphView::AS_IS, std::experimental::nullopt); + GraphView::OLD, std::experimental::nullopt); // expect that each vertex has been returned 3 times EXPECT_EQ(results.size(), 12); std::vector found(4, 0); @@ -1037,7 +1045,7 @@ TEST_F(QueryPlanExpandBreadthFirst, ExistingNode) { } return ExpandBF(EdgeAtom::Direction::OUT, 1000, LITERAL(true), - GraphView::AS_IS, std::experimental::nullopt, &n0); + GraphView::OLD, std::experimental::nullopt, &n0); }; EXPECT_EQ(ExpandPreceeding(std::experimental::nullopt).size(), 12); @@ -1112,8 +1120,7 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test { // returns a vector of pairs. each pair is (vector-of-edges, vertex) auto ExpandWShortest(EdgeAtom::Direction direction, std::experimental::optional max_depth, - Expression *where, - GraphView graph_view = GraphView::AS_IS, + Expression *where, GraphView graph_view, std::experimental::optional node_id = 0, ScanAllTuple *existing_node_input = nullptr) { // scan the nodes optionally filtering on property value @@ -1191,8 +1198,8 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test { // 3 3 3 TEST_F(QueryPlanExpandWeightedShortestPath, Basic) { - auto results = - ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, LITERAL(true)); + auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, LITERAL(true), + GraphView::OLD); ASSERT_EQ(results.size(), 4); @@ -1225,8 +1232,8 @@ TEST_F(QueryPlanExpandWeightedShortestPath, Basic) { TEST_F(QueryPlanExpandWeightedShortestPath, EdgeDirection) { { - auto results = - ExpandWShortest(EdgeAtom::Direction::OUT, 1000, LITERAL(true)); + auto results = ExpandWShortest(EdgeAtom::Direction::OUT, 1000, + LITERAL(true), GraphView::OLD); ASSERT_EQ(results.size(), 4); EXPECT_EQ(GetProp(results[0].vertex), 2); EXPECT_EQ(results[0].total_weight, 3); @@ -1238,8 +1245,8 @@ TEST_F(QueryPlanExpandWeightedShortestPath, EdgeDirection) { EXPECT_EQ(results[3].total_weight, 9); } { - auto results = - ExpandWShortest(EdgeAtom::Direction::IN, 1000, LITERAL(true)); + auto results = ExpandWShortest(EdgeAtom::Direction::IN, 1000, LITERAL(true), + GraphView::OLD); ASSERT_EQ(results.size(), 4); EXPECT_EQ(GetProp(results[0].vertex), 4); EXPECT_EQ(results[0].total_weight, 12); @@ -1255,7 +1262,7 @@ TEST_F(QueryPlanExpandWeightedShortestPath, EdgeDirection) { TEST_F(QueryPlanExpandWeightedShortestPath, Where) { { auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, - PropNe(filter_node, 2)); + PropNe(filter_node, 2), GraphView::OLD); ASSERT_EQ(results.size(), 3); EXPECT_EQ(GetProp(results[0].vertex), 1); EXPECT_EQ(results[0].total_weight, 5); @@ -1266,7 +1273,7 @@ TEST_F(QueryPlanExpandWeightedShortestPath, Where) { } { auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, - PropNe(filter_node, 1)); + PropNe(filter_node, 1), GraphView::OLD); ASSERT_EQ(results.size(), 3); EXPECT_EQ(GetProp(results[0].vertex), 2); EXPECT_EQ(results[0].total_weight, 3); @@ -1299,23 +1306,23 @@ TEST_F(QueryPlanExpandWeightedShortestPath, GraphState) { } TEST_F(QueryPlanExpandWeightedShortestPath, ExistingNode) { - auto ExpandPreceeding = [this]( - std::experimental::optional preceeding_node_id) { - // scan the nodes optionally filtering on property value - auto n0 = MakeScanAll(storage, symbol_table, "n0"); - if (preceeding_node_id) { - auto filter = std::make_shared( - n0.op_, EQ(PROPERTY_LOOKUP(n0.node_->identifier_, prop), - LITERAL(*preceeding_node_id))); - // inject the filter op into the ScanAllTuple. that way the filter op - // can be passed into the ExpandWShortest function without too much - // refactor - n0.op_ = filter; - } + auto ExpandPreceeding = + [this](std::experimental::optional preceeding_node_id) { + // scan the nodes optionally filtering on property value + auto n0 = MakeScanAll(storage, symbol_table, "n0"); + if (preceeding_node_id) { + auto filter = std::make_shared( + n0.op_, EQ(PROPERTY_LOOKUP(n0.node_->identifier_, prop), + LITERAL(*preceeding_node_id))); + // inject the filter op into the ScanAllTuple. that way the filter op + // can be passed into the ExpandWShortest function without too much + // refactor + n0.op_ = filter; + } - return ExpandWShortest(EdgeAtom::Direction::OUT, 1000, LITERAL(true), - GraphView::AS_IS, std::experimental::nullopt, &n0); - }; + return ExpandWShortest(EdgeAtom::Direction::OUT, 1000, LITERAL(true), + GraphView::OLD, std::experimental::nullopt, &n0); + }; EXPECT_EQ(ExpandPreceeding(std::experimental::nullopt).size(), 20); { @@ -1327,8 +1334,9 @@ TEST_F(QueryPlanExpandWeightedShortestPath, ExistingNode) { TEST_F(QueryPlanExpandWeightedShortestPath, UpperBound) { { - auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, - std::experimental::nullopt, LITERAL(true)); + auto results = + ExpandWShortest(EdgeAtom::Direction::BOTH, std::experimental::nullopt, + LITERAL(true), GraphView::OLD); ASSERT_EQ(results.size(), 4); EXPECT_EQ(GetProp(results[0].vertex), 2); EXPECT_EQ(results[0].total_weight, 3); @@ -1361,7 +1369,8 @@ TEST_F(QueryPlanExpandWeightedShortestPath, UpperBound) { EXPECT_EQ(results[4].total_weight, 12); } { - auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 2, LITERAL(true)); + auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 2, LITERAL(true), + GraphView::OLD); ASSERT_EQ(results.size(), 4); EXPECT_EQ(GetProp(results[0].vertex), 2); EXPECT_EQ(results[0].total_weight, 3); @@ -1373,7 +1382,8 @@ TEST_F(QueryPlanExpandWeightedShortestPath, UpperBound) { EXPECT_EQ(results[3].total_weight, 10); } { - auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 1, LITERAL(true)); + auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 1, LITERAL(true), + GraphView::OLD); ASSERT_EQ(results.size(), 3); EXPECT_EQ(GetProp(results[0].vertex), 2); EXPECT_EQ(results[0].total_weight, 3); @@ -1433,8 +1443,9 @@ TEST(QueryPlan, ExpandOptional) { // MATCH (n) OPTIONAL MATCH (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = MakeExpand(storage, symbol_table, nullptr, n.sym_, "r", - EdgeAtom::Direction::OUT, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, nullptr, n.sym_, "r", + EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD); auto optional = std::make_shared( n.op_, r_m.op_, std::vector{r_m.edge_sym_, r_m.node_sym_}); @@ -1508,8 +1519,9 @@ TEST(QueryPlan, OptionalMatchEmptyDBExpandFromNode) { symbol_table[*n_ne] = with_n_sym; auto with = MakeProduce(optional, n_ne); // MATCH (n) -[r]-> (m) - auto r_m = MakeExpand(storage, symbol_table, with, with_n_sym, "r", - EdgeAtom::Direction::OUT, {}, "m", false); + auto r_m = + MakeExpand(storage, symbol_table, with, with_n_sym, "r", + EdgeAtom::Direction::OUT, {}, "m", false, GraphView::OLD); // RETURN m auto m_ne = NEXPR("m", IDENT("m")); symbol_table[*m_ne->expression_] = r_m.node_sym_; @@ -1558,7 +1570,7 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingNode) { symbol_table[*node->identifier_] = with_n_sym; auto expand = std::make_shared( with_n_sym, edge_sym, edge_direction, std::vector{}, - m.op_, m.sym_, true); + m.op_, m.sym_, true, GraphView::OLD); // RETURN m auto m_ne = NEXPR("m", IDENT("m")); symbol_table[*m_ne->expression_] = m.sym_; @@ -1587,11 +1599,13 @@ TEST(QueryPlan, ExpandExistingNode) { auto test_existing = [&](bool with_existing, int expected_result_count) { auto n = MakeScanAll(storage, symbol_table, "n"); auto r_n = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {}, "n", with_existing); + EdgeAtom::Direction::OUT, {}, "n", with_existing, + GraphView::OLD); if (with_existing) - r_n.op_ = std::make_shared( - n.sym_, r_n.edge_sym_, r_n.edge_->direction_, - std::vector{}, n.op_, n.sym_, with_existing); + r_n.op_ = + std::make_shared(n.sym_, r_n.edge_sym_, r_n.edge_->direction_, + std::vector{}, n.op_, + n.sym_, with_existing, GraphView::OLD); // make a named expression and a produce auto output = NEXPR("n", IDENT("n")); @@ -1622,8 +1636,9 @@ TEST(QueryPlan, ExpandBothCycleEdgeCase) { SymbolTable symbol_table; auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_ = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::BOTH, {}, "_", false); + auto r_ = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::BOTH, {}, "_", false, GraphView::OLD); EXPECT_EQ(1, PullAll(r_.op_, dba, symbol_table)); } @@ -1670,7 +1685,8 @@ TEST(QueryPlan, EdgeFilter) { auto n = MakeScanAll(storage, symbol_table, "n"); const auto &edge_type = edge_types[0]; auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {edge_type}, "m", false); + EdgeAtom::Direction::OUT, {edge_type}, "m", false, + GraphView::OLD); r_m.edge_->edge_types_.push_back(edge_type); r_m.edge_->properties_[prop] = LITERAL(42); auto *filter_expr = @@ -1715,7 +1731,8 @@ TEST(QueryPlan, EdgeFilterMultipleTypes) { // make a scan all auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, {type_1, type_2}, "m", false); + EdgeAtom::Direction::OUT, {type_1, type_2}, "m", false, + GraphView::OLD); // make a named expression and a produce auto output = NEXPR("m", IDENT("m")); @@ -1776,14 +1793,16 @@ TEST(QueryPlan, ExpandUniquenessFilter) { SymbolTable symbol_table; auto n1 = MakeScanAll(storage, symbol_table, "n1"); - auto r1_n2 = MakeExpand(storage, symbol_table, n1.op_, n1.sym_, "r1", - EdgeAtom::Direction::OUT, {}, "n2", false); + auto r1_n2 = + MakeExpand(storage, symbol_table, n1.op_, n1.sym_, "r1", + EdgeAtom::Direction::OUT, {}, "n2", false, GraphView::OLD); std::shared_ptr last_op = r1_n2.op_; if (vertex_uniqueness) last_op = std::make_shared>( last_op, r1_n2.node_sym_, std::vector{n1.sym_}); - auto r2_n3 = MakeExpand(storage, symbol_table, last_op, r1_n2.node_sym_, - "r2", EdgeAtom::Direction::OUT, {}, "n3", false); + auto r2_n3 = + MakeExpand(storage, symbol_table, last_op, r1_n2.node_sym_, "r2", + EdgeAtom::Direction::OUT, {}, "n3", false, GraphView::OLD); last_op = r2_n3.op_; if (edge_uniqueness) last_op = std::make_shared>(