Remove GraphView from variable expansion operators
Summary: Variable expansions cannot appear in merge patterns or after updates, so they can only be planned with GraphState::OLD. Because of that, it makes sense to remove GraphView parameter from them to reduce confusion. Reviewers: teon.banek, llugovic Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1825
This commit is contained in:
parent
914f40411a
commit
9d36f775f2
@ -115,8 +115,8 @@ DistributedExpand::DistributedExpand(
|
||||
GraphView graph_view)
|
||||
: input_(input ? input : std::make_shared<Once>()),
|
||||
input_symbol_(input_symbol),
|
||||
common_{node_symbol, edge_symbol, direction,
|
||||
edge_types, existing_node, graph_view} {}
|
||||
common_{node_symbol, edge_symbol, direction, edge_types, existing_node},
|
||||
graph_view_(graph_view) {}
|
||||
|
||||
DistributedExpand::DistributedExpand(
|
||||
const std::shared_ptr<LogicalOperator> &input, Symbol input_symbol,
|
||||
@ -139,12 +139,11 @@ DistributedExpandBfs::DistributedExpandBfs(
|
||||
const std::shared_ptr<LogicalOperator> &input, Symbol input_symbol,
|
||||
Symbol node_symbol, Symbol edge_symbol, EdgeAtom::Direction direction,
|
||||
const std::vector<storage::EdgeType> &edge_types, bool existing_node,
|
||||
GraphView graph_view, Expression *lower_bound, Expression *upper_bound,
|
||||
Expression *lower_bound, Expression *upper_bound,
|
||||
const ExpansionLambda &filter_lambda)
|
||||
: input_(input ? input : std::make_shared<Once>()),
|
||||
input_symbol_(input_symbol),
|
||||
common_{node_symbol, edge_symbol, direction,
|
||||
edge_types, existing_node, graph_view},
|
||||
common_{node_symbol, edge_symbol, direction, edge_types, existing_node},
|
||||
lower_bound_(lower_bound),
|
||||
upper_bound_(upper_bound),
|
||||
filter_lambda_(filter_lambda) {}
|
||||
@ -979,7 +978,7 @@ class DistributedExpandCursor : public query::plan::Cursor {
|
||||
|
||||
ExpectType(self_->input_symbol_, vertex_value, TypedValue::Type::Vertex);
|
||||
auto &vertex = vertex_value.Value<VertexAccessor>();
|
||||
SwitchAccessor(vertex, self_->common_.graph_view);
|
||||
SwitchAccessor(vertex, self_->graph_view_);
|
||||
|
||||
auto direction = self_->common_.direction;
|
||||
if (direction == EdgeAtom::Direction::IN ||
|
||||
@ -1058,10 +1057,7 @@ class DistributedExpandBfsCursor : public query::plan::Cursor {
|
||||
public:
|
||||
DistributedExpandBfsCursor(const DistributedExpandBfs &self,
|
||||
database::GraphDbAccessor &db)
|
||||
: self_(self), db_(db), input_cursor_(self_.input()->MakeCursor(db)) {
|
||||
CHECK(self_.common_.graph_view == GraphView::OLD)
|
||||
<< "ExpandVariable should only be planned with GraphView::OLD";
|
||||
}
|
||||
: self_(self), db_(db), input_cursor_(self_.input()->MakeCursor(db)) {}
|
||||
|
||||
void InitSubcursors(database::GraphDbAccessor *dba,
|
||||
const query::SymbolTable &symbol_table,
|
||||
@ -1090,7 +1086,7 @@ class DistributedExpandBfsCursor : public query::plan::Cursor {
|
||||
// Evaluator for the filtering condition and expansion depth.
|
||||
ExpressionEvaluator evaluator(
|
||||
&frame, context.symbol_table, context.evaluation_context,
|
||||
context.db_accessor, self_.common_.graph_view);
|
||||
context.db_accessor, GraphView::OLD);
|
||||
|
||||
while (true) {
|
||||
if (context.db_accessor->should_abort()) throw HintedAbortError();
|
||||
|
@ -230,7 +230,17 @@ by having only one result from each worker.")
|
||||
:capnp-save #'save-operator-pointer
|
||||
:capnp-load #'load-operator-pointer)
|
||||
(input-symbol "Symbol" :scope :public)
|
||||
(common "ExpandCommon" :scope :public))
|
||||
(common "ExpandCommon" :scope :public)
|
||||
(graph-view "GraphView" :scope :public
|
||||
:capnp-init nil
|
||||
:capnp-save (lcp:capnp-save-enum "::query::capnp::GraphView"
|
||||
"GraphView"
|
||||
'(old new))
|
||||
:capnp-load (lcp:capnp-load-enum "::query::capnp::GraphView"
|
||||
"GraphView"
|
||||
'(old new))
|
||||
:documentation
|
||||
"State from which the input node should get expanded."))
|
||||
(:documentation "Distributed version of Expand operator")
|
||||
(:public
|
||||
#>cpp
|
||||
@ -306,8 +316,8 @@ by having only one result from each worker.")
|
||||
Symbol input_symbol, Symbol node_symbol,
|
||||
Symbol edge_symbol, EdgeAtom::Direction direction,
|
||||
const std::vector<storage::EdgeType> &edge_types,
|
||||
bool existing_node, GraphView graph_view,
|
||||
Expression *lower_bound, Expression *upper_bound,
|
||||
bool existing_node, Expression *lower_bound,
|
||||
Expression *upper_bound,
|
||||
const ExpansionLambda &filter_lambda);
|
||||
DistributedExpandBfs(const std::shared_ptr<LogicalOperator> &input,
|
||||
Symbol input_symbol, const ExpandCommon &common,
|
||||
|
@ -454,8 +454,8 @@ Expand::Expand(const std::shared_ptr<LogicalOperator> &input,
|
||||
bool existing_node, GraphView graph_view)
|
||||
: input_(input ? input : std::make_shared<Once>()),
|
||||
input_symbol_(input_symbol),
|
||||
common_{node_symbol, edge_symbol, direction,
|
||||
edge_types, existing_node, graph_view} {}
|
||||
common_{node_symbol, edge_symbol, direction, edge_types, existing_node},
|
||||
graph_view_(graph_view) {}
|
||||
|
||||
ACCEPT_WITH_INPUT(Expand)
|
||||
|
||||
@ -548,7 +548,7 @@ bool Expand::ExpandCursor::InitEdges(Frame &frame, ExecutionContext &context) {
|
||||
|
||||
ExpectType(self_.input_symbol_, vertex_value, TypedValue::Type::Vertex);
|
||||
auto &vertex = vertex_value.Value<VertexAccessor>();
|
||||
SwitchAccessor(vertex, self_.common_.graph_view);
|
||||
SwitchAccessor(vertex, self_.graph_view_);
|
||||
|
||||
auto direction = self_.common_.direction;
|
||||
if (direction == EdgeAtom::Direction::IN ||
|
||||
@ -601,11 +601,10 @@ ExpandVariable::ExpandVariable(
|
||||
Expression *lower_bound, Expression *upper_bound, bool existing_node,
|
||||
ExpansionLambda filter_lambda,
|
||||
std::experimental::optional<ExpansionLambda> weight_lambda,
|
||||
std::experimental::optional<Symbol> total_weight, GraphView graph_view)
|
||||
std::experimental::optional<Symbol> total_weight)
|
||||
: input_(input ? input : std::make_shared<Once>()),
|
||||
input_symbol_(input_symbol),
|
||||
common_{node_symbol, edge_symbol, direction,
|
||||
edge_types, existing_node, graph_view},
|
||||
common_{node_symbol, edge_symbol, direction, edge_types, existing_node},
|
||||
type_(type),
|
||||
is_reverse_(is_reverse),
|
||||
lower_bound_(lower_bound),
|
||||
@ -687,9 +686,9 @@ class ExpandVariableCursor : public Cursor {
|
||||
bool Pull(Frame &frame, ExecutionContext &context) override {
|
||||
SCOPED_PROFILE_OP("ExpandVariable");
|
||||
|
||||
ExpressionEvaluator evaluator(
|
||||
&frame, context.symbol_table, context.evaluation_context,
|
||||
context.db_accessor, self_.common_.graph_view);
|
||||
ExpressionEvaluator evaluator(&frame, context.symbol_table,
|
||||
context.evaluation_context,
|
||||
context.db_accessor, GraphView::OLD);
|
||||
while (true) {
|
||||
if (Expand(frame, context)) return true;
|
||||
|
||||
@ -764,14 +763,12 @@ class ExpandVariableCursor : public Cursor {
|
||||
|
||||
ExpectType(self_.input_symbol_, vertex_value, TypedValue::Type::Vertex);
|
||||
auto &vertex = vertex_value.Value<VertexAccessor>();
|
||||
SwitchAccessor(vertex, self_.common_.graph_view);
|
||||
SwitchAccessor(vertex, GraphView::OLD);
|
||||
|
||||
// Evaluate the upper and lower bounds.
|
||||
ExpressionEvaluator evaluator(&frame, context.symbol_table,
|
||||
|
||||
context.evaluation_context,
|
||||
context.db_accessor,
|
||||
self_.common_.graph_view);
|
||||
context.db_accessor, GraphView::OLD);
|
||||
auto calc_bound = [&evaluator](auto &bound) {
|
||||
auto value = EvaluateInt(&evaluator, bound, "Variable expansion bound");
|
||||
if (value < 0)
|
||||
@ -785,7 +782,7 @@ class ExpandVariableCursor : public Cursor {
|
||||
: std::numeric_limits<int64_t>::max();
|
||||
|
||||
if (upper_bound_ > 0) {
|
||||
SwitchAccessor(vertex, self_.common_.graph_view);
|
||||
SwitchAccessor(vertex, GraphView::OLD);
|
||||
edges_.emplace_back(ExpandFromVertex(vertex, self_.common_.direction,
|
||||
self_.common_.edge_types));
|
||||
edges_it_.emplace_back(edges_.back().begin());
|
||||
@ -830,9 +827,9 @@ class ExpandVariableCursor : public Cursor {
|
||||
* vertex and another Pull from the input cursor should be performed.
|
||||
*/
|
||||
bool Expand(Frame &frame, ExecutionContext &context) {
|
||||
ExpressionEvaluator evaluator(
|
||||
&frame, context.symbol_table, context.evaluation_context,
|
||||
context.db_accessor, self_.common_.graph_view);
|
||||
ExpressionEvaluator evaluator(&frame, context.symbol_table,
|
||||
context.evaluation_context,
|
||||
context.db_accessor, GraphView::OLD);
|
||||
// Some expansions might not be valid due to edge uniqueness and
|
||||
// existing_node criterions, so expand in a loop until either the input
|
||||
// vertex is exhausted or a valid variable-length expansion is available.
|
||||
@ -902,7 +899,7 @@ class ExpandVariableCursor : public Cursor {
|
||||
// we are doing depth-first search, so place the current
|
||||
// edge's expansions onto the stack, if we should continue to expand
|
||||
if (upper_bound_ > static_cast<int64_t>(edges_.size())) {
|
||||
SwitchAccessor(current_vertex, self_.common_.graph_view);
|
||||
SwitchAccessor(current_vertex, GraphView::OLD);
|
||||
edges_.emplace_back(ExpandFromVertex(
|
||||
current_vertex, self_.common_.direction, self_.common_.edge_types));
|
||||
edges_it_.emplace_back(edges_.back().begin());
|
||||
@ -922,8 +919,6 @@ class STShortestPathCursor : public query::plan::Cursor {
|
||||
STShortestPathCursor(const ExpandVariable &self,
|
||||
database::GraphDbAccessor &dba)
|
||||
: self_(self), input_cursor_(self_.input()->MakeCursor(dba)) {
|
||||
CHECK(self_.common_.graph_view == GraphView::OLD)
|
||||
<< "ExpandVariable should only be planned with GraphView::OLD";
|
||||
CHECK(self_.common_.existing_node)
|
||||
<< "s-t shortest path algorithm should only "
|
||||
"be used when `existing_node` flag is "
|
||||
@ -1157,8 +1152,6 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
SingleSourceShortestPathCursor(const ExpandVariable &self,
|
||||
database::GraphDbAccessor &db)
|
||||
: self_(self), input_cursor_(self_.input()->MakeCursor(db)) {
|
||||
CHECK(self_.common_.graph_view == GraphView::OLD)
|
||||
<< "ExpandVariable should only be planned with GraphView::OLD";
|
||||
CHECK(!self_.common_.existing_node)
|
||||
<< "Single source shortest path algorithm "
|
||||
"should not be used when `existing_node` "
|
||||
@ -1325,7 +1318,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
|
||||
ExpressionEvaluator evaluator(
|
||||
&frame, context.symbol_table, context.evaluation_context,
|
||||
context.db_accessor, self_.common_.graph_view);
|
||||
context.db_accessor, GraphView::OLD);
|
||||
auto create_state = [this](VertexAccessor vertex, int depth) {
|
||||
return std::make_pair(vertex, upper_bound_set_ ? depth : 0);
|
||||
};
|
||||
@ -1336,8 +1329,8 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
auto expand_pair = [this, &evaluator, &frame, &create_state](
|
||||
EdgeAccessor edge, VertexAccessor vertex,
|
||||
double weight, int depth) {
|
||||
SwitchAccessor(edge, self_.common_.graph_view);
|
||||
SwitchAccessor(vertex, self_.common_.graph_view);
|
||||
SwitchAccessor(edge, GraphView::OLD);
|
||||
SwitchAccessor(vertex, GraphView::OLD);
|
||||
|
||||
if (self_.filter_lambda_.expression) {
|
||||
frame[self_.filter_lambda_.inner_edge_symbol] = edge;
|
||||
@ -1400,7 +1393,7 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
// Skip expansion for such nodes.
|
||||
if (node.IsNull()) continue;
|
||||
}
|
||||
SwitchAccessor(vertex, self_.common_.graph_view);
|
||||
SwitchAccessor(vertex, GraphView::OLD);
|
||||
if (self_.upper_bound_) {
|
||||
upper_bound_ =
|
||||
EvaluateInt(&evaluator, self_.upper_bound_,
|
||||
@ -2179,9 +2172,8 @@ std::vector<Symbol> EdgeUniquenessFilter::ModifiedSymbols(
|
||||
return input_->ModifiedSymbols(table);
|
||||
}
|
||||
|
||||
EdgeUniquenessFilter::EdgeUniquenessFilterCursor::
|
||||
EdgeUniquenessFilterCursor(const EdgeUniquenessFilter &self,
|
||||
database::GraphDbAccessor &db)
|
||||
EdgeUniquenessFilter::EdgeUniquenessFilterCursor::EdgeUniquenessFilterCursor(
|
||||
const EdgeUniquenessFilter &self, database::GraphDbAccessor &db)
|
||||
: self_(self), input_cursor_(self.input_->MakeCursor(db)) {}
|
||||
|
||||
namespace {
|
||||
|
@ -924,7 +924,17 @@ the given types are valid."
|
||||
:capnp-load (lcp:capnp-load-vector "::storage::capnp::EdgeType"
|
||||
"storage::EdgeType"))
|
||||
(existing-node :bool :documentation "If the given node atom refer to a symbol
|
||||
that has already been expanded and should be just validated in the frame.")
|
||||
that has already been expanded and should be just validated in the frame."))
|
||||
(:serialize (:slk) (:capnp)))
|
||||
|
||||
(lcp:define-class expand (logical-operator)
|
||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||
:slk-save #'slk-save-operator-pointer
|
||||
:slk-load #'slk-load-operator-pointer
|
||||
:capnp-save #'save-operator-pointer
|
||||
:capnp-load #'load-operator-pointer)
|
||||
(input-symbol "Symbol" :scope :public)
|
||||
(common "ExpandCommon" :scope :public)
|
||||
(graph-view "GraphView" :scope :public
|
||||
:capnp-init nil
|
||||
:capnp-save (lcp:capnp-save-enum "::query::capnp::GraphView"
|
||||
@ -935,16 +945,6 @@ that has already been expanded and should be just validated in the frame.")
|
||||
'(old new))
|
||||
:documentation
|
||||
"State from which the input node should get expanded."))
|
||||
(:serialize (:slk) (:capnp)))
|
||||
|
||||
(lcp:define-class expand (logical-operator)
|
||||
((input "std::shared_ptr<LogicalOperator>" :scope :public
|
||||
:slk-save #'slk-save-operator-pointer
|
||||
:slk-load #'slk-load-operator-pointer
|
||||
:capnp-save #'save-operator-pointer
|
||||
:capnp-load #'load-operator-pointer)
|
||||
(input-symbol "Symbol" :scope :public)
|
||||
(common "ExpandCommon" :scope :public))
|
||||
(:documentation
|
||||
"Expansion operator. For a node existing in the frame it
|
||||
expands one edge and one node and places them on the frame.
|
||||
@ -1195,8 +1195,7 @@ pulled.")
|
||||
Expression *upper_bound, bool existing_node,
|
||||
ExpansionLambda filter_lambda,
|
||||
std::experimental::optional<ExpansionLambda> weight_lambda,
|
||||
std::experimental::optional<Symbol> total_weight,
|
||||
GraphView graph_view);
|
||||
std::experimental::optional<Symbol> total_weight);
|
||||
|
||||
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
|
||||
std::unique_ptr<Cursor> MakeCursor(
|
||||
|
@ -594,12 +594,13 @@ class RuleBasedPlanner {
|
||||
}
|
||||
|
||||
// TODO: Pass weight lambda.
|
||||
CHECK(match_context.graph_view == GraphView::OLD)
|
||||
<< "ExpandVariable should only be planned with GraphView::OLD";
|
||||
last_op = std::make_unique<ExpandVariable>(
|
||||
std::move(last_op), node1_symbol, node_symbol, edge_symbol,
|
||||
edge->type_, expansion.direction, edge_types,
|
||||
expansion.is_flipped, edge->lower_bound_, edge->upper_bound_,
|
||||
existing_node, filter_lambda, weight_lambda, total_weight,
|
||||
match_context.graph_view);
|
||||
existing_node, filter_lambda, weight_lambda, total_weight);
|
||||
} else {
|
||||
if (!existing_node) {
|
||||
// Try to get better behaviour by creating an indexed scan and then
|
||||
|
@ -30,7 +30,7 @@ class DistributedDb : public Database {
|
||||
const ExpansionLambda &filter_lambda) override {
|
||||
return std::make_unique<DistributedExpandBfs>(
|
||||
input, source_sym, sink_sym, edge_sym, direction, edge_types,
|
||||
existing_node, GraphView::OLD, lower_bound, upper_bound, filter_lambda);
|
||||
existing_node, lower_bound, upper_bound, filter_lambda);
|
||||
}
|
||||
|
||||
std::pair<std::vector<storage::VertexAddress>,
|
||||
|
@ -26,8 +26,7 @@ class SingleNodeDb : public Database {
|
||||
return std::make_unique<ExpandVariable>(
|
||||
input, source_sym, sink_sym, edge_sym, EdgeAtom::Type::BREADTH_FIRST,
|
||||
direction, edge_types, false, lower_bound, upper_bound, existing_node,
|
||||
filter_lambda, std::experimental::nullopt, std::experimental::nullopt,
|
||||
GraphView::OLD);
|
||||
filter_lambda, std::experimental::nullopt, std::experimental::nullopt);
|
||||
}
|
||||
|
||||
std::pair<std::vector<VertexAddress>, std::vector<EdgeAddress>> BuildGraph(
|
||||
|
@ -178,7 +178,7 @@ TEST_F(QueryCostEstimator, ExpandVariable) {
|
||||
EdgeAtom::Type::DEPTH_FIRST, EdgeAtom::Direction::IN,
|
||||
std::vector<storage::EdgeType>{}, false, nullptr, nullptr, false,
|
||||
ExpansionLambda{NextSymbol(), NextSymbol(), nullptr},
|
||||
std::experimental::nullopt, std::experimental::nullopt, GraphView::OLD);
|
||||
std::experimental::nullopt, std::experimental::nullopt);
|
||||
EXPECT_COST(CardParam::kExpandVariable * CostParam::kExpandVariable);
|
||||
}
|
||||
|
||||
|
@ -567,6 +567,8 @@ class QueryPlanExpandVariable : public testing::Test {
|
||||
auto convert = [this](std::experimental::optional<size_t> bound) {
|
||||
return bound ? LITERAL(static_cast<int64_t>(bound.value())) : nullptr;
|
||||
};
|
||||
CHECK(graph_view == GraphView::OLD)
|
||||
<< "ExpandVariable should only be planned with GraphView::OLD";
|
||||
|
||||
return std::make_shared<ExpandVariable>(
|
||||
filter_op, n_from.sym_, n_to_sym, edge_sym,
|
||||
@ -575,7 +577,7 @@ class QueryPlanExpandVariable : public testing::Test {
|
||||
ExpansionLambda{symbol_table.CreateSymbol("inner_edge", false),
|
||||
symbol_table.CreateSymbol("inner_node", false),
|
||||
nullptr},
|
||||
std::experimental::nullopt, std::experimental::nullopt, graph_view);
|
||||
std::experimental::nullopt, std::experimental::nullopt);
|
||||
} else
|
||||
return std::make_shared<Expand>(filter_op, n_from.sym_, n_to_sym,
|
||||
edge_sym, direction, edge_types, false,
|
||||
@ -761,39 +763,6 @@ TEST_F(QueryPlanExpandVariable, EdgeUniquenessTwoVariableExpansions) {
|
||||
(map_int{{2, 5 * 8}}));
|
||||
}
|
||||
|
||||
TEST_F(QueryPlanExpandVariable, GraphState) {
|
||||
auto test_expand = [&](GraphView graph_view,
|
||||
const std::vector<storage::EdgeType> &edge_types) {
|
||||
auto e = Edge("r", EdgeAtom::Direction::OUT);
|
||||
return GetEdgeListSizes(
|
||||
AddMatch<ExpandVariable>(nullptr, "n", 0, EdgeAtom::Direction::OUT,
|
||||
edge_types, 2, 2, e, "m", graph_view),
|
||||
e);
|
||||
};
|
||||
|
||||
auto new_edge_type = dba_->EdgeType("some_type");
|
||||
// add two vertices branching out from the second layer
|
||||
for (VertexAccessor &vertex : dba_->Vertices(true))
|
||||
if (vertex.has_label(labels[1])) {
|
||||
auto new_vertex = dba_->InsertVertex();
|
||||
dba_->InsertEdge(vertex, new_vertex, new_edge_type);
|
||||
}
|
||||
ASSERT_EQ(CountIterable(dba_->Vertices(false)), 6);
|
||||
ASSERT_EQ(CountIterable(dba_->Vertices(true)), 8);
|
||||
|
||||
EXPECT_EQ(test_expand(GraphView::OLD, {}), (map_int{{2, 8}}));
|
||||
EXPECT_EQ(test_expand(GraphView::OLD, {new_edge_type}), (map_int{}));
|
||||
EXPECT_EQ(test_expand(GraphView::NEW, {}), (map_int{{2, 12}}));
|
||||
EXPECT_EQ(test_expand(GraphView::NEW, {edge_type}), (map_int{{2, 8}}));
|
||||
EXPECT_EQ(test_expand(GraphView::NEW, {new_edge_type}), (map_int{}));
|
||||
dba_->AdvanceCommand();
|
||||
for (const auto graph_view : {GraphView::OLD, GraphView::NEW}) {
|
||||
EXPECT_EQ(test_expand(graph_view, {}), (map_int{{2, 12}}));
|
||||
EXPECT_EQ(test_expand(graph_view, {edge_type}), (map_int{{2, 8}}));
|
||||
EXPECT_EQ(test_expand(graph_view, {new_edge_type}), (map_int{}));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(QueryPlanExpandVariable, NamedPath) {
|
||||
auto e = Edge("r", EdgeAtom::Direction::OUT);
|
||||
auto expand =
|
||||
@ -900,7 +869,7 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test {
|
||||
// vertex)
|
||||
auto ExpandWShortest(EdgeAtom::Direction direction,
|
||||
std::experimental::optional<int> max_depth,
|
||||
Expression *where, GraphView graph_view = GraphView::OLD,
|
||||
Expression *where,
|
||||
std::experimental::optional<int> node_id = 0,
|
||||
ScanAllTuple *existing_node_input = nullptr) {
|
||||
// scan the nodes optionally filtering on property value
|
||||
@ -931,7 +900,7 @@ class QueryPlanExpandWeightedShortestPath : public testing::Test {
|
||||
ExpansionLambda{filter_edge, filter_node, where},
|
||||
ExpansionLambda{weight_edge, weight_node,
|
||||
PROPERTY_LOOKUP(ident_e, prop)},
|
||||
total_weight, graph_view);
|
||||
total_weight);
|
||||
|
||||
Frame frame(symbol_table.max_position());
|
||||
auto cursor = last_op->MakeCursor(dba);
|
||||
@ -1064,27 +1033,6 @@ TEST_F(QueryPlanExpandWeightedShortestPath, Where) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(QueryPlanExpandWeightedShortestPath, GraphState) {
|
||||
auto ExpandSize = [this](GraphView graph_view) {
|
||||
return ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, LITERAL(true),
|
||||
graph_view)
|
||||
.size();
|
||||
};
|
||||
EXPECT_EQ(ExpandSize(GraphView::OLD), 4);
|
||||
EXPECT_EQ(ExpandSize(GraphView::NEW), 4);
|
||||
auto new_vertex = dba.InsertVertex();
|
||||
new_vertex.PropsSet(prop.second, 5);
|
||||
auto edge = dba.InsertEdge(v[4], new_vertex, edge_type);
|
||||
edge.PropsSet(prop.second, 2);
|
||||
EXPECT_EQ(CountIterable(dba.Vertices(false)), 5);
|
||||
EXPECT_EQ(CountIterable(dba.Vertices(true)), 6);
|
||||
EXPECT_EQ(ExpandSize(GraphView::OLD), 4);
|
||||
EXPECT_EQ(ExpandSize(GraphView::NEW), 5);
|
||||
dba.AdvanceCommand();
|
||||
EXPECT_EQ(ExpandSize(GraphView::OLD), 5);
|
||||
EXPECT_EQ(ExpandSize(GraphView::NEW), 5);
|
||||
}
|
||||
|
||||
TEST_F(QueryPlanExpandWeightedShortestPath, ExistingNode) {
|
||||
auto ExpandPreceeding =
|
||||
[this](std::experimental::optional<int> preceeding_node_id) {
|
||||
@ -1101,7 +1049,7 @@ TEST_F(QueryPlanExpandWeightedShortestPath, ExistingNode) {
|
||||
}
|
||||
|
||||
return ExpandWShortest(EdgeAtom::Direction::OUT, 1000, LITERAL(true),
|
||||
GraphView::OLD, std::experimental::nullopt, &n0);
|
||||
std::experimental::nullopt, &n0);
|
||||
};
|
||||
|
||||
EXPECT_EQ(ExpandPreceeding(std::experimental::nullopt).size(), 20);
|
||||
@ -1126,27 +1074,6 @@ TEST_F(QueryPlanExpandWeightedShortestPath, UpperBound) {
|
||||
EXPECT_EQ(GetProp(results[3].vertex), 4);
|
||||
EXPECT_EQ(results[3].total_weight, 9);
|
||||
}
|
||||
{
|
||||
auto new_vertex = dba.InsertVertex();
|
||||
new_vertex.PropsSet(prop.second, 5);
|
||||
auto edge = dba.InsertEdge(v[4], new_vertex, edge_type);
|
||||
edge.PropsSet(prop.second, 2);
|
||||
|
||||
auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 3, LITERAL(true),
|
||||
GraphView::NEW);
|
||||
|
||||
ASSERT_EQ(results.size(), 5);
|
||||
EXPECT_EQ(GetProp(results[0].vertex), 2);
|
||||
EXPECT_EQ(results[0].total_weight, 3);
|
||||
EXPECT_EQ(GetProp(results[1].vertex), 1);
|
||||
EXPECT_EQ(results[1].total_weight, 5);
|
||||
EXPECT_EQ(GetProp(results[2].vertex), 3);
|
||||
EXPECT_EQ(results[2].total_weight, 6);
|
||||
EXPECT_EQ(GetProp(results[3].vertex), 4);
|
||||
EXPECT_EQ(results[3].total_weight, 9);
|
||||
EXPECT_EQ(GetProp(results[4].vertex), 5);
|
||||
EXPECT_EQ(results[4].total_weight, 12);
|
||||
}
|
||||
{
|
||||
auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 2, LITERAL(true));
|
||||
ASSERT_EQ(results.size(), 4);
|
||||
@ -1169,34 +1096,53 @@ TEST_F(QueryPlanExpandWeightedShortestPath, UpperBound) {
|
||||
EXPECT_EQ(GetProp(results[2].vertex), 4);
|
||||
EXPECT_EQ(results[2].total_weight, 12);
|
||||
}
|
||||
{
|
||||
auto new_vertex = dba.InsertVertex();
|
||||
new_vertex.PropsSet(prop.second, 5);
|
||||
auto edge = dba.InsertEdge(v[4], new_vertex, edge_type);
|
||||
edge.PropsSet(prop.second, 2);
|
||||
dba.AdvanceCommand();
|
||||
|
||||
auto results = ExpandWShortest(EdgeAtom::Direction::BOTH, 3, LITERAL(true));
|
||||
|
||||
ASSERT_EQ(results.size(), 5);
|
||||
EXPECT_EQ(GetProp(results[0].vertex), 2);
|
||||
EXPECT_EQ(results[0].total_weight, 3);
|
||||
EXPECT_EQ(GetProp(results[1].vertex), 1);
|
||||
EXPECT_EQ(results[1].total_weight, 5);
|
||||
EXPECT_EQ(GetProp(results[2].vertex), 3);
|
||||
EXPECT_EQ(results[2].total_weight, 6);
|
||||
EXPECT_EQ(GetProp(results[3].vertex), 4);
|
||||
EXPECT_EQ(results[3].total_weight, 9);
|
||||
EXPECT_EQ(GetProp(results[4].vertex), 5);
|
||||
EXPECT_EQ(results[4].total_weight, 12);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(QueryPlanExpandWeightedShortestPath, Exceptions) {
|
||||
{
|
||||
TEST_F(QueryPlanExpandWeightedShortestPath, NonNumericWeight) {
|
||||
auto new_vertex = dba.InsertVertex();
|
||||
new_vertex.PropsSet(prop.second, 5);
|
||||
auto edge = dba.InsertEdge(v[4], new_vertex, edge_type);
|
||||
edge.PropsSet(prop.second, "not a number");
|
||||
EXPECT_THROW(ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, LITERAL(true),
|
||||
GraphView::NEW),
|
||||
dba.AdvanceCommand();
|
||||
EXPECT_THROW(ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, LITERAL(true)),
|
||||
QueryRuntimeException);
|
||||
}
|
||||
{
|
||||
|
||||
TEST_F(QueryPlanExpandWeightedShortestPath, NegativeWeight) {
|
||||
auto new_vertex = dba.InsertVertex();
|
||||
new_vertex.PropsSet(prop.second, 5);
|
||||
auto edge = dba.InsertEdge(v[4], new_vertex, edge_type);
|
||||
edge.PropsSet(prop.second, -10); // negative weight
|
||||
EXPECT_THROW(ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, LITERAL(true),
|
||||
GraphView::NEW),
|
||||
dba.AdvanceCommand();
|
||||
EXPECT_THROW(ExpandWShortest(EdgeAtom::Direction::BOTH, 1000, LITERAL(true)),
|
||||
QueryRuntimeException);
|
||||
}
|
||||
{
|
||||
// negative upper bound
|
||||
EXPECT_THROW(ExpandWShortest(EdgeAtom::Direction::BOTH, -1, LITERAL(true),
|
||||
GraphView::NEW),
|
||||
|
||||
TEST_F(QueryPlanExpandWeightedShortestPath, NegativeUpperBound) {
|
||||
EXPECT_THROW(ExpandWShortest(EdgeAtom::Direction::BOTH, -1, LITERAL(true)),
|
||||
QueryRuntimeException);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(QueryPlan, ExpandOptional) {
|
||||
database::GraphDb db;
|
||||
|
Loading…
Reference in New Issue
Block a user