Improve MERGE performance by using indices (#213)
This commit is contained in:
parent
0138d277d4
commit
5a8bda2531
@ -291,16 +291,17 @@ can serve as inputs to others and thus a sequence of operations is formed.")
|
||||
cpp<#)
|
||||
|
||||
(lcp:define-class once (logical-operator)
|
||||
()
|
||||
((symbols "std::vector<Symbol>" :scope :public))
|
||||
(:documentation
|
||||
"A logical operator whose Cursor returns true on the first Pull
|
||||
and false on every following Pull.")
|
||||
(:public
|
||||
#>cpp
|
||||
Once(std::vector<Symbol> symbols = {}) : symbols_{std::move(symbols)} {}
|
||||
DEFVISITABLE(HierarchicalLogicalOperatorVisitor);
|
||||
UniqueCursorPtr MakeCursor(utils::MemoryResource *) const override;
|
||||
std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override {
|
||||
return {};
|
||||
return symbols_;
|
||||
}
|
||||
|
||||
bool HasSingleInput() const override;
|
||||
|
@ -482,9 +482,16 @@ class RuleBasedPlanner {
|
||||
// version when generating the create part.
|
||||
std::unordered_set<Symbol> bound_symbols_copy(context_->bound_symbols);
|
||||
MatchContext match_ctx{matching, *context_->symbol_table, bound_symbols_copy, storage::View::NEW};
|
||||
auto on_match = PlanMatching(match_ctx, nullptr);
|
||||
|
||||
std::vector<Symbol> bound_symbols(context_->bound_symbols.begin(), context_->bound_symbols.end());
|
||||
|
||||
auto once_with_symbols = std::make_unique<Once>(bound_symbols);
|
||||
auto on_match = PlanMatching(match_ctx, std::move(once_with_symbols));
|
||||
|
||||
once_with_symbols = std::make_unique<Once>(std::move(bound_symbols));
|
||||
// Use the original bound_symbols, so we fill it with new symbols.
|
||||
auto on_create = GenCreateForPattern(*merge.pattern_, nullptr, *context_->symbol_table, context_->bound_symbols);
|
||||
auto on_create = GenCreateForPattern(*merge.pattern_, std::move(once_with_symbols), *context_->symbol_table,
|
||||
context_->bound_symbols);
|
||||
for (auto &set : merge.on_create_) {
|
||||
on_create = HandleWriteClause(set, on_create, *context_->symbol_table, context_->bound_symbols);
|
||||
MG_ASSERT(on_create, "Expected SET in MERGE ... ON CREATE");
|
||||
|
@ -774,6 +774,26 @@ TYPED_TEST(TestPlanner, UnwindMergeNodeProperty) {
|
||||
DeleteListContent(&on_create);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestPlanner, UnwindMergeNodePropertyWithIndex) {
|
||||
// Test UNWIND [1] AS i MERGE (n :label {prop: i}) with label-property index
|
||||
AstStorage storage;
|
||||
FakeDbAccessor dba;
|
||||
const auto label_name = "label";
|
||||
const auto label = dba.Label(label_name);
|
||||
const auto property = PROPERTY_PAIR("prop");
|
||||
dba.SetIndexCount(label, property.second, 1);
|
||||
auto node_n = NODE("n", label_name);
|
||||
node_n->properties_[storage.GetPropertyIx(property.first)] = IDENT("i");
|
||||
auto *query = QUERY(SINGLE_QUERY(UNWIND(LIST(LITERAL(1)), AS("i")), MERGE(PATTERN(node_n))));
|
||||
std::list<BaseOpChecker *> on_match{new ExpectScanAllByLabelPropertyValue(label, property, IDENT("i"))};
|
||||
std::list<BaseOpChecker *> on_create{new ExpectCreateNode()};
|
||||
auto symbol_table = query::MakeSymbolTable(query);
|
||||
auto planner = MakePlanner<TypeParam>(&dba, storage, symbol_table, query);
|
||||
CheckPlan(planner.plan(), symbol_table, ExpectUnwind(), ExpectMerge(on_match, on_create));
|
||||
DeleteListContent(&on_match);
|
||||
DeleteListContent(&on_create);
|
||||
}
|
||||
|
||||
TYPED_TEST(TestPlanner, MultipleOptionalMatchReturn) {
|
||||
// Test OPTIONAL MATCH (n) OPTIONAL MATCH (m) RETURN n
|
||||
AstStorage storage;
|
||||
|
Loading…
Reference in New Issue
Block a user