From cf76e0e19b6f7052aa133da6aa335c9c4310c8d0 Mon Sep 17 00:00:00 2001 From: gvolfing <gabor.volfinger@memgraph.io> Date: Fri, 20 Jan 2023 08:08:45 +0100 Subject: [PATCH] React to PR comments --- src/query/v2/multiframe.hpp | 8 +- src/query/v2/plan/operator.cpp | 204 +++++------------- src/query/v2/plan/pretty_print.hpp | 2 +- src/query/v2/plan/read_write_type_checker.cpp | 3 +- src/query/v2/plan/read_write_type_checker.hpp | 3 +- src/query/v2/plan/rewrite/index_lookup.hpp | 50 ++++- src/query/v2/plan/vertex_count_cache.hpp | 32 +-- src/storage/v3/shard_rsm.cpp | 6 +- tests/unit/query_common.hpp | 1 - tests/unit/query_plan_checker_v2.hpp | 23 +- 10 files changed, 133 insertions(+), 199 deletions(-) diff --git a/src/query/v2/multiframe.hpp b/src/query/v2/multiframe.hpp index a3b1e4d7d..dc3239393 100644 --- a/src/query/v2/multiframe.hpp +++ b/src/query/v2/multiframe.hpp @@ -200,10 +200,10 @@ class ValidFramesConsumer { explicit ValidFramesConsumer(MultiFrame &multiframe); ~ValidFramesConsumer() noexcept; - ValidFramesConsumer(const ValidFramesConsumer &other) = default; - ValidFramesConsumer(ValidFramesConsumer &&other) noexcept = default; - ValidFramesConsumer &operator=(const ValidFramesConsumer &other) = default; - ValidFramesConsumer &operator=(ValidFramesConsumer &&other) noexcept = default; + ValidFramesConsumer(const ValidFramesConsumer &other) = delete; + ValidFramesConsumer(ValidFramesConsumer &&other) noexcept = delete; + ValidFramesConsumer &operator=(const ValidFramesConsumer &other) = delete; + ValidFramesConsumer &operator=(ValidFramesConsumer &&other) noexcept = delete; struct Iterator { using iterator_category = std::forward_iterator_tag; diff --git a/src/query/v2/plan/operator.cpp b/src/query/v2/plan/operator.cpp index c3140f585..f42bf1bec 100644 --- a/src/query/v2/plan/operator.cpp +++ b/src/query/v2/plan/operator.cpp @@ -465,194 +465,86 @@ class DistributedScanAllAndFilterCursor : public Cursor { class DistributedScanAllByPrimaryKeyCursor : public Cursor { public: - explicit DistributedScanAllByPrimaryKeyCursor( - Symbol output_symbol, UniqueCursorPtr input_cursor, const char *op_name, - std::optional<storage::v3::LabelId> label, - std::optional<std::pair<storage::v3::PropertyId, Expression *>> property_expression_pair, - std::optional<std::vector<Expression *>> filter_expressions, std::optional<std::vector<Expression *>> primary_key) + explicit DistributedScanAllByPrimaryKeyCursor(Symbol output_symbol, UniqueCursorPtr input_cursor, const char *op_name, + storage::v3::LabelId label, + std::optional<std::vector<Expression *>> filter_expressions, + std::vector<Expression *> primary_key) : output_symbol_(output_symbol), input_cursor_(std::move(input_cursor)), op_name_(op_name), label_(label), - property_expression_pair_(property_expression_pair), filter_expressions_(filter_expressions), - primary_key_(primary_key) { - ResetExecutionState(); - } + primary_key_(primary_key) {} enum class State : int8_t { INITIALIZING, COMPLETED }; using VertexAccessor = accessors::VertexAccessor; - bool MakeRequest(RequestRouterInterface &request_router, ExecutionContext &context) { - { - SCOPED_REQUEST_WAIT_PROFILE; - std::optional<std::string> request_label; - if (label_.has_value()) { - request_label = request_router.LabelToName(*label_); - } - current_batch_ = request_router.ScanVertices(request_label); + std::optional<VertexAccessor> MakeRequestSingleFrame(Frame &frame, RequestRouterInterface &request_router, + ExecutionContext &context) { + // Evaluate the expressions that hold the PrimaryKey. + ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router, + storage::v3::View::NEW); + + std::vector<msgs::Value> pk; + for (auto *primary_property : primary_key_) { + pk.push_back(TypedValueToValue(primary_property->Accept(evaluator))); } - current_vertex_it_ = current_batch_.begin(); - request_state_ = State::COMPLETED; - return !current_batch_.empty(); - } - bool MakeRequestSingleFrame(Frame &frame, RequestRouterInterface &request_router, ExecutionContext &context) { - { + msgs::Label label = {.id = msgs::LabelId::FromUint(label_.AsUint())}; + + msgs::GetPropertiesRequest req = {.vertex_ids = {std::make_pair(label, pk)}}; + auto get_prop_result = std::invoke([&context, &request_router, &req]() mutable { SCOPED_REQUEST_WAIT_PROFILE; - std::optional<std::string> request_label = std::nullopt; - if (label_.has_value()) { - request_label = request_router.LabelToName(*label_); - } + return request_router.GetProperties(req); + }); + MG_ASSERT(get_prop_result.size() <= 1); - // Evaluate the expressions that hold the PrimaryKey. - ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router, - storage::v3::View::NEW); - - std::vector<msgs::Value> pk; - MG_ASSERT(primary_key_); - for (auto *primary_property : *primary_key_) { - pk.push_back(TypedValueToValue(primary_key->Accept(evaluator))); - } - - msgs::Label label = {.id = msgs::LabelId::FromUint(label_->AsUint())}; - - msgs::GetPropertiesRequest req = {.vertex_ids = {std::make_pair(label, pk)}}; - auto get_prop_result = request_router.GetProperties(req); - MG_ASSERT(get_prop_result.size() <= 1); - - if (get_prop_result.empty()) { - current_batch_ = std::vector<VertexAccessor>{}; - } else { - auto properties = get_prop_result[0].props; - // TODO (gvolfing) figure out labels when relevant. - msgs::Vertex vertex = {.id = get_prop_result[0].vertex, .labels = {}}; - - current_batch_ = {VertexAccessor(vertex, properties, &request_router)}; - } + if (get_prop_result.empty()) { + return std::nullopt; } - current_vertex_it_ = current_batch_.begin(); - request_state_ = State::COMPLETED; - return !current_batch_.empty(); + auto properties = get_prop_result[0].props; + // TODO (gvolfing) figure out labels when relevant. + msgs::Vertex vertex = {.id = get_prop_result[0].vertex, .labels = {}}; + + return VertexAccessor(vertex, properties, &request_router); } bool Pull(Frame &frame, ExecutionContext &context) override { SCOPED_PROFILE_OP(op_name_); + if (MustAbort(context)) { + throw HintedAbortError(); + } + + if (!input_cursor_->Pull(frame, context)) { + return false; + } + auto &request_router = *context.request_router; - while (true) { - if (MustAbort(context)) { - throw HintedAbortError(); - } - - if (request_state_ == State::INITIALIZING) { - if (!input_cursor_->Pull(frame, context)) { - return false; - } - } - - if (current_vertex_it_ == current_batch_.end() && - (request_state_ == State::COMPLETED || !MakeRequestSingleFrame(frame, request_router, context))) { - ResetExecutionState(); - continue; - } - - frame[output_symbol_] = TypedValue(std::move(*current_vertex_it_)); - ++current_vertex_it_; + auto vertex = MakeRequestSingleFrame(frame, request_router, context); + if (vertex) { + frame[output_symbol_] = TypedValue(std::move(*vertex)); return true; } - } - - void PrepareNextFrames(ExecutionContext &context) { - auto &request_router = *context.request_router; - - input_cursor_->PullMultiple(*own_multi_frames_, context); - valid_frames_consumer_ = own_multi_frames_->GetValidFramesConsumer(); - valid_frames_it_ = valid_frames_consumer_->begin(); - - MakeRequest(request_router, context); - } - - inline bool HasNextFrame() { - return current_vertex_it_ != current_batch_.end() && valid_frames_it_ != valid_frames_consumer_->end(); - } - - FrameWithValidity GetNextFrame(ExecutionContext &context) { - MG_ASSERT(HasNextFrame()); - - auto frame = *valid_frames_it_; - frame[output_symbol_] = TypedValue(*current_vertex_it_); - - ++current_vertex_it_; - if (current_vertex_it_ == current_batch_.end()) { - valid_frames_it_->MakeInvalid(); - ++valid_frames_it_; - - if (valid_frames_it_ == valid_frames_consumer_->end()) { - PrepareNextFrames(context); - } else { - current_vertex_it_ = current_batch_.begin(); - } - }; - - return frame; + return false; } void PullMultiple(MultiFrame &input_multi_frame, ExecutionContext &context) override { - SCOPED_PROFILE_OP(op_name_); - - if (!own_multi_frames_.has_value()) { - own_multi_frames_.emplace(MultiFrame(input_multi_frame.GetFirstFrame().elems().size(), - kNumberOfFramesInMultiframe, input_multi_frame.GetMemoryResource())); - PrepareNextFrames(context); - } - - while (true) { - if (MustAbort(context)) { - throw HintedAbortError(); - } - - auto invalid_frames_populator = input_multi_frame.GetInvalidFramesPopulator(); - auto invalid_frame_it = invalid_frames_populator.begin(); - auto has_modified_at_least_one_frame = false; - - while (invalid_frames_populator.end() != invalid_frame_it && HasNextFrame()) { - has_modified_at_least_one_frame = true; - *invalid_frame_it = GetNextFrame(context); - ++invalid_frame_it; - } - - if (!has_modified_at_least_one_frame) { - return; - } - } + throw utils::NotYetImplemented("Multiframe version of ScanAllByPrimaryKey is yet to be implemented."); }; + void Reset() override { input_cursor_->Reset(); } + void Shutdown() override { input_cursor_->Shutdown(); } - void ResetExecutionState() { - current_batch_.clear(); - current_vertex_it_ = current_batch_.end(); - request_state_ = State::INITIALIZING; - } - - void Reset() override { - input_cursor_->Reset(); - ResetExecutionState(); - } - private: const Symbol output_symbol_; const UniqueCursorPtr input_cursor_; const char *op_name_; - std::vector<VertexAccessor> current_batch_; - std::vector<VertexAccessor>::iterator current_vertex_it_; - State request_state_ = State::INITIALIZING; - std::optional<storage::v3::LabelId> label_; - std::optional<std::pair<storage::v3::PropertyId, Expression *>> property_expression_pair_; + storage::v3::LabelId label_; std::optional<std::vector<Expression *>> filter_expressions_; - std::optional<std::vector<Expression *>> primary_key_; + std::vector<Expression *> primary_key_; std::optional<MultiFrame> own_multi_frames_; std::optional<ValidFramesConsumer> valid_frames_consumer_; ValidFramesConsumer::Iterator valid_frames_it_; @@ -767,9 +659,9 @@ ACCEPT_WITH_INPUT(ScanAllByPrimaryKey) UniqueCursorPtr ScanAllByPrimaryKey::MakeCursor(utils::MemoryResource *mem) const { EventCounter::IncrementCounter(EventCounter::ScanAllByPrimaryKeyOperator); - return MakeUniqueCursorPtr<DistributedScanAllByPrimaryKeyCursor>( - mem, output_symbol_, input_->MakeCursor(mem), "ScanAllByPrimaryKey", label_, - std::nullopt /*property_expression_pair*/, std::nullopt /*filter_expressions*/, primary_key_); + return MakeUniqueCursorPtr<DistributedScanAllByPrimaryKeyCursor>(mem, output_symbol_, input_->MakeCursor(mem), + "ScanAllByPrimaryKey", label_, + std::nullopt /*filter_expressions*/, primary_key_); } Expand::Expand(const std::shared_ptr<LogicalOperator> &input, Symbol input_symbol, Symbol node_symbol, diff --git a/src/query/v2/plan/pretty_print.hpp b/src/query/v2/plan/pretty_print.hpp index 30ab87978..d1dad22b7 100644 --- a/src/query/v2/plan/pretty_print.hpp +++ b/src/query/v2/plan/pretty_print.hpp @@ -67,7 +67,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor { bool PreVisit(ScanAllByLabelPropertyValue &) override; bool PreVisit(ScanAllByLabelPropertyRange &) override; bool PreVisit(ScanAllByLabelProperty &) override; - bool PreVisit(ScanAllByPrimaryKey & /*unused*/) override; + bool PreVisit(ScanAllByPrimaryKey &) override; bool PreVisit(Expand &) override; bool PreVisit(ExpandVariable &) override; diff --git a/src/query/v2/plan/read_write_type_checker.cpp b/src/query/v2/plan/read_write_type_checker.cpp index ec1459f6a..d1e037d1f 100644 --- a/src/query/v2/plan/read_write_type_checker.cpp +++ b/src/query/v2/plan/read_write_type_checker.cpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source @@ -35,6 +35,7 @@ PRE_VISIT(ScanAllByLabel, RWType::R, true) PRE_VISIT(ScanAllByLabelPropertyRange, RWType::R, true) PRE_VISIT(ScanAllByLabelPropertyValue, RWType::R, true) PRE_VISIT(ScanAllByLabelProperty, RWType::R, true) +PRE_VISIT(ScanAllByPrimaryKey, RWType::R, true) PRE_VISIT(Expand, RWType::R, true) PRE_VISIT(ExpandVariable, RWType::R, true) diff --git a/src/query/v2/plan/read_write_type_checker.hpp b/src/query/v2/plan/read_write_type_checker.hpp index e5f429035..62d7af8b9 100644 --- a/src/query/v2/plan/read_write_type_checker.hpp +++ b/src/query/v2/plan/read_write_type_checker.hpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source @@ -59,6 +59,7 @@ class ReadWriteTypeChecker : public virtual HierarchicalLogicalOperatorVisitor { bool PreVisit(ScanAllByLabelPropertyValue &) override; bool PreVisit(ScanAllByLabelPropertyRange &) override; bool PreVisit(ScanAllByLabelProperty &) override; + bool PreVisit(ScanAllByPrimaryKey &) override; bool PreVisit(Expand &) override; bool PreVisit(ExpandVariable &) override; diff --git a/src/query/v2/plan/rewrite/index_lookup.hpp b/src/query/v2/plan/rewrite/index_lookup.hpp index 30f2c21f6..37c14129e 100644 --- a/src/query/v2/plan/rewrite/index_lookup.hpp +++ b/src/query/v2/plan/rewrite/index_lookup.hpp @@ -569,8 +569,8 @@ class IndexLookupRewriter final : public HierarchicalLogicalOperatorVisitor { const auto &modified_symbols = scan.ModifiedSymbols(*symbol_table_); std::unordered_set<Symbol> bound_symbols(modified_symbols.begin(), modified_symbols.end()); - // Try to see if we can use label+property index. If not, try to use - // just the label index. + // Try to see if we can use label + primary-key or label + property index. + // If not, try to use just the label index. const auto labels = filters_.FilteredLabels(node_symbol); if (labels.empty()) { // Without labels, we cannot generate any indexed ScanAll. @@ -583,19 +583,57 @@ class IndexLookupRewriter final : public HierarchicalLogicalOperatorVisitor { query::v2::LabelIx prim_label; std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> primary_key; + auto extract_primary_key = [this](storage::v3::LabelId label, + std::vector<query::v2::plan::FilterInfo> property_filters) + -> std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> { + std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> pk_temp; + std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> pk; + std::vector<memgraph::storage::v3::SchemaProperty> schema = db_->GetSchemaForLabel(label); + + std::vector<storage::v3::PropertyId> schema_properties; + schema_properties.reserve(schema.size()); + + std::transform(schema.begin(), schema.end(), std::back_inserter(schema_properties), + [](const auto &schema_elem) { return schema_elem.property_id; }); + + for (const auto &property_filter : property_filters) { + const auto &property_id = db_->NameToProperty(property_filter.property_filter->property_.name); + if (std::find(schema_properties.begin(), schema_properties.end(), property_id) != schema_properties.end()) { + pk_temp.emplace_back(std::make_pair(property_filter.expression, property_filter)); + } + } + + // Make sure pk is in the same order as schema_properties. + for (const auto &schema_prop : schema_properties) { + for (auto &pk_temp_prop : pk_temp) { + const auto &property_id = db_->NameToProperty(pk_temp_prop.second.property_filter->property_.name); + if (schema_prop == property_id) { + pk.push_back(pk_temp_prop); + } + } + } + MG_ASSERT(pk.size() == pk_temp.size(), + "The two vectors should represent the same primary key with a possibly different order of contained " + "elements."); + + return pk.size() == schema_properties.size() + ? pk + : std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>>{}; + }; + if (!property_filters.empty()) { for (const auto &label : labels) { - if (db_->LabelIndexExists(GetLabel(label))) { + if (db_->PrimaryLabelExists(GetLabel(label))) { prim_label = label; - primary_key = db_->ExtractPrimaryKey(GetLabel(prim_label), property_filters); + primary_key = extract_primary_key(GetLabel(prim_label), property_filters); break; } } if (!primary_key.empty()) { // Mark the expressions so they won't be used for an additional, unnecessary filter. for (const auto &primary_property : primary_key) { - filter_exprs_for_removal_.insert(pk.first); - filters_.EraseFilter(pk.second); + filter_exprs_for_removal_.insert(primary_property.first); + filters_.EraseFilter(primary_property.second); } EraseLabelFilters(node_symbol, prim_label); std::vector<query::v2::Expression *> pk_expressions; diff --git a/src/query/v2/plan/vertex_count_cache.hpp b/src/query/v2/plan/vertex_count_cache.hpp index a5f7b42b7..7e3fc8530 100644 --- a/src/query/v2/plan/vertex_count_cache.hpp +++ b/src/query/v2/plan/vertex_count_cache.hpp @@ -1,4 +1,4 @@ -// Copyright 2022 Memgraph Ltd. +// Copyright 2023 Memgraph Ltd. // // Use of this software is governed by the Business Source License // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source @@ -22,6 +22,7 @@ #include "storage/v3/id_types.hpp" #include "storage/v3/property_value.hpp" #include "utils/bound.hpp" +#include "utils/exceptions.hpp" #include "utils/fnv.hpp" namespace memgraph::query::v2::plan { @@ -54,31 +55,16 @@ class VertexCountCache { return 1; } - bool LabelIndexExists(storage::v3::LabelId label) { return request_router_->IsPrimaryLabel(label); } + bool LabelIndexExists(storage::v3::LabelId label) { + throw utils::NotYetImplemented("Label indicies are yet to be implemented."); + } + + bool PrimaryLabelExists(storage::v3::LabelId label) { return request_router_->IsPrimaryLabel(label); } bool LabelPropertyIndexExists(storage::v3::LabelId /*label*/, storage::v3::PropertyId /*property*/) { return false; } - std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> ExtractPrimaryKey( - storage::v3::LabelId label, std::vector<query::v2::plan::FilterInfo> property_filters) { - std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> pk; - const auto schema = request_router_->GetSchemaForLabel(label); - - std::vector<storage::v3::PropertyId> schema_properties; - schema_properties.reserve(schema.size()); - - std::transform(schema.begin(), schema.end(), std::back_inserter(schema_properties), - [](const auto &schema_elem) { return schema_elem.property_id; }); - - for (const auto &property_filter : property_filters) { - const auto &property_id = NameToProperty(property_filter.property_filter->property_.name); - if (std::find(schema_properties.begin(), schema_properties.end(), property_id) != schema_properties.end()) { - pk.emplace_back(std::make_pair(property_filter.expression, property_filter)); - } - } - - return pk.size() == schema_properties.size() - ? pk - : std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>>{}; + std::vector<memgraph::storage::v3::SchemaProperty> GetSchemaForLabel(storage::v3::LabelId label) { + return request_router_->GetSchemaForLabel(label); } RequestRouterInterface *request_router_; diff --git a/src/storage/v3/shard_rsm.cpp b/src/storage/v3/shard_rsm.cpp index c23d31ebc..881796a70 100644 --- a/src/storage/v3/shard_rsm.cpp +++ b/src/storage/v3/shard_rsm.cpp @@ -539,12 +539,12 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::GetPropertiesRequest &&req) { const VertexAccessor &v_acc, const std::optional<EdgeAccessor> &e_acc) -> ShardResult<std::map<PropertyId, Value>> { if (!req.property_ids) { - const auto *schema = shard_->GetSchema(shard_->PrimaryLabel()); - MG_ASSERT(schema); - if (e_acc) { return CollectAllPropertiesFromAccessor(*e_acc, view); } + const auto *schema = shard_->GetSchema(shard_->PrimaryLabel()); + MG_ASSERT(schema); + return CollectAllPropertiesFromAccessor(v_acc, view, *schema); } diff --git a/tests/unit/query_common.hpp b/tests/unit/query_common.hpp index d497b76ba..784df5e21 100644 --- a/tests/unit/query_common.hpp +++ b/tests/unit/query_common.hpp @@ -486,7 +486,6 @@ auto GetForeach(AstStorage &storage, NamedExpression *named_expr, const std::vec #define EDGE(...) memgraph::query::test_common::GetEdge(storage, __VA_ARGS__) #define EDGE_VARIABLE(...) memgraph::query::test_common::GetEdgeVariable(storage, __VA_ARGS__) #define PATTERN(...) memgraph::query::test_common::GetPattern(storage, {__VA_ARGS__}) -#define PATTERN(...) memgraph::query::test_common::GetPattern(storage, {__VA_ARGS__}) #define NAMED_PATTERN(name, ...) memgraph::query::test_common::GetPattern(storage, name, {__VA_ARGS__}) #define OPTIONAL_MATCH(...) \ memgraph::query::test_common::GetWithPatterns(storage.Create<memgraph::query::Match>(true), {__VA_ARGS__}) diff --git a/tests/unit/query_plan_checker_v2.hpp b/tests/unit/query_plan_checker_v2.hpp index 1a971c4f0..0d7a6bc5f 100644 --- a/tests/unit/query_plan_checker_v2.hpp +++ b/tests/unit/query_plan_checker_v2.hpp @@ -17,6 +17,7 @@ #include "query/v2/plan/operator.hpp" #include "query/v2/plan/planner.hpp" #include "query/v2/plan/preprocess.hpp" +#include "utils/exceptions.hpp" namespace memgraph::query::v2::plan { @@ -289,7 +290,7 @@ class FakeDistributedDbAccessor { } bool LabelIndexExists(memgraph::storage::v3::LabelId label) const { - return label_index_.find(label) != label_index_.end(); + throw utils::NotYetImplemented("Label indicies are yet to be implemented."); } bool LabelPropertyIndexExists(memgraph::storage::v3::LabelId label, @@ -302,6 +303,8 @@ class FakeDistributedDbAccessor { return false; } + bool PrimaryLabelExists(storage::v3::LabelId label) { return label_index_.find(label) != label_index_.end(); } + void SetIndexCount(memgraph::storage::v3::LabelId label, int64_t count) { label_index_[label] = count; } void SetIndexCount(memgraph::storage::v3::LabelId label, memgraph::storage::v3::PropertyId property, int64_t count) { @@ -382,13 +385,27 @@ class FakeDistributedDbAccessor { return memgraph::storage::v3::PropertyId::FromUint(0); } + std::vector<memgraph::storage::v3::SchemaProperty> GetSchemaForLabel(storage::v3::LabelId label) { + auto schema_properties = schemas_.at(label); + std::vector<memgraph::storage::v3::SchemaProperty> ret; + std::transform(schema_properties.begin(), schema_properties.end(), std::back_inserter(ret), [](const auto &prop) { + memgraph::storage::v3::SchemaProperty schema_prop = { + .property_id = prop, + // This should not be hardcoded, but for testing purposes it will suffice. + .type = memgraph::common::SchemaType::INT}; + + return schema_prop; + }); + return ret; + } + std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> ExtractPrimaryKey( storage::v3::LabelId label, std::vector<query::v2::plan::FilterInfo> property_filters) { MG_ASSERT(schemas_.contains(label), "You did not specify the Schema for this label! Use FakeDistributedDbAccessor::CreateSchema(...)."); std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>> pk; - const auto schema = GetSchemaForLabel(label); + const auto schema = GetSchemaPropertiesForLabel(label); std::vector<storage::v3::PropertyId> schema_properties; schema_properties.reserve(schema.size()); @@ -408,7 +425,7 @@ class FakeDistributedDbAccessor { : std::vector<std::pair<query::v2::Expression *, query::v2::plan::FilterInfo>>{}; } - std::vector<memgraph::storage::v3::PropertyId> GetSchemaForLabel(storage::v3::LabelId label) { + std::vector<memgraph::storage::v3::PropertyId> GetSchemaPropertiesForLabel(storage::v3::LabelId label) { return schemas_.at(label); }