diff --git a/src/query/db_accessor.hpp b/src/query/db_accessor.hpp index 2c269a951..8e3f1c6c9 100644 --- a/src/query/db_accessor.hpp +++ b/src/query/db_accessor.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 @@ -125,6 +125,11 @@ class VertexAccessor final { return impl_.SetProperty(key, value); } + storage::Result> SetProperties( + std::map &properties) { + return impl_.SetBatchProperties(properties); + } + storage::Result RemoveProperty(storage::PropertyId key) { return SetProperty(key, storage::PropertyValue()); } diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index 4465a6f99..3015206c2 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -213,10 +213,14 @@ VertexAccessor &CreateLocalVertex(const NodeCreationInfo &node_info, Frame *fram // when we update PropertyValue with custom allocator. // auto start = std::chrono::steady_clock::now(); + + std::map properties; if (const auto *node_info_properties = std::get_if(&node_info.properties)) { for (const auto &[key, value_expression] : *node_info_properties) { - PropsSetChecked(&new_node, key, value_expression->Accept(evaluator)); + properties.emplace(key, value_expression->Accept(evaluator)); + // PropsSetChecked(&new_node, key, ); } + new_node.SetProperties(properties); } else { auto property_map = evaluator.Visit(*std::get(node_info.properties)); for (const auto &[key, value] : property_map.ValueMap()) { diff --git a/src/storage/v2/property_store.cpp b/src/storage/v2/property_store.cpp index db8982b6f..df5280715 100644 --- a/src/storage/v2/property_store.cpp +++ b/src/storage/v2/property_store.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 @@ -971,6 +971,8 @@ PropertyValue PropertyStore::GetProperty(PropertyId property) const { return value; } +PropertyValue PropertyStore::GetEmptyProperty() const { return PropertyValue(); } + bool PropertyStore::HasProperty(PropertyId property) const { uint64_t size; const uint8_t *data; diff --git a/src/storage/v2/property_store.hpp b/src/storage/v2/property_store.hpp index bd397285f..95de116c7 100644 --- a/src/storage/v2/property_store.hpp +++ b/src/storage/v2/property_store.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 @@ -42,6 +42,8 @@ class PropertyStore { /// complexity of this function is O(n). bool HasProperty(PropertyId property) const; + PropertyValue GetEmptyProperty() const; + /// Checks whether the property `property` is equal to the specified value /// `value`. This function doesn't perform any memory allocations while /// performing the equality check. The time complexity of this function is diff --git a/src/storage/v2/vertex_accessor.cpp b/src/storage/v2/vertex_accessor.cpp index 535e4f2da..9a2fe1c8e 100644 --- a/src/storage/v2/vertex_accessor.cpp +++ b/src/storage/v2/vertex_accessor.cpp @@ -245,6 +245,30 @@ Result VertexAccessor::SetProperty(PropertyId property, const Pro return std::move(current_value); } +Result> VertexAccessor::SetBatchProperties( + std::map &properties) { + // Be careful when calling this function + // It will set properties in batch, without checking if property already exists + + utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; + std::lock_guard guard(vertex_->lock); + + if (!PrepareForWrite(transaction_, vertex_)) return Error::SERIALIZATION_ERROR; + + if (vertex_->deleted) return Error::DELETED_OBJECT; + + std::vector new_values; + for (const auto &[property, value] : properties) { + auto current_value = vertex_->properties.GetEmptyProperty(); + CreateAndLinkDelta(transaction_, vertex_, Delta::SetPropertyTag(), property, current_value); + vertex_->properties.SetProperty(property, value); + UpdateOnSetProperty(indices_, property, value, vertex_, *transaction_); + new_values.emplace_back(current_value); + } + + return new_values; +} + Result> VertexAccessor::ClearProperties() { std::lock_guard guard(vertex_->lock); diff --git a/src/storage/v2/vertex_accessor.hpp b/src/storage/v2/vertex_accessor.hpp index 916c45a20..54a61bd72 100644 --- a/src/storage/v2/vertex_accessor.hpp +++ b/src/storage/v2/vertex_accessor.hpp @@ -68,6 +68,9 @@ class VertexAccessor final { /// @throw std::bad_alloc Result SetProperty(PropertyId property, const PropertyValue &value); + Result> SetBatchProperties( + std::map &properties); + /// Remove all properties and return the values of the removed properties. /// @throw std::bad_alloc Result> ClearProperties();