From 93992a275be553b7188929ac0810a37c3c6aeb16 Mon Sep 17 00:00:00 2001
From: Antonio Filipovic <61245998+antoniofilipovic@users.noreply.github.com>
Date: Wed, 6 Sep 2023 00:12:27 +0200
Subject: [PATCH] Improve NameToId mapper on set properties (#1147)

---
 src/query/plan/operator.cpp | 19 +++++++++++++------
 src/query/plan/operator.hpp |  1 +
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp
index 12f111903..a275cedc6 100644
--- a/src/query/plan/operator.cpp
+++ b/src/query/plan/operator.cpp
@@ -2724,7 +2724,8 @@ concept AccessorWithProperties = requires(T value, storage::PropertyId property_
 ///     RecordAccessor<Edge>
 template <AccessorWithProperties TRecordAccessor>
 void SetPropertiesOnRecord(TRecordAccessor *record, const TypedValue &rhs, SetProperties::Op op,
-                           ExecutionContext *context) {
+                           ExecutionContext *context,
+                           std::unordered_map<std::string, storage::PropertyId> &cached_name_id) {
   using PropertiesMap = std::map<storage::PropertyId, storage::PropertyValue>;
   std::optional<PropertiesMap> old_values;
   const bool should_register_change =
@@ -2808,9 +2809,15 @@ void SetPropertiesOnRecord(TRecordAccessor *record, const TypedValue &rhs, SetPr
     }
     case TypedValue::Type::Map: {
       PropertiesMap new_properties;
-      for (const auto &[prop_id, prop_value] : rhs.ValueMap()) {
-        auto key = context->db_accessor->NameToProperty(prop_id);
-        new_properties.emplace(key, prop_value);
+      for (const auto &[string_key, value] : rhs.ValueMap()) {
+        storage::PropertyId property_id;
+        if (auto it = cached_name_id.find(std::string(string_key)); it != cached_name_id.end()) [[likely]] {
+          property_id = it->second;
+        } else {
+          property_id = context->db_accessor->NameToProperty(string_key);
+          cached_name_id.emplace(string_key, property_id);
+        }
+        new_properties.emplace(property_id, value);
       }
       update_props(new_properties);
       break;
@@ -2853,7 +2860,7 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &co
         throw QueryRuntimeException("Vertex properties not set due to not having enough permission!");
       }
 #endif
-      SetPropertiesOnRecord(&lhs.ValueVertex(), rhs, self_.op_, &context);
+      SetPropertiesOnRecord(&lhs.ValueVertex(), rhs, self_.op_, &context, cached_name_id_);
       break;
     case TypedValue::Type::Edge:
 #ifdef MG_ENTERPRISE
@@ -2862,7 +2869,7 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &co
         throw QueryRuntimeException("Edge properties not set due to not having enough permission!");
       }
 #endif
-      SetPropertiesOnRecord(&lhs.ValueEdge(), rhs, self_.op_, &context);
+      SetPropertiesOnRecord(&lhs.ValueEdge(), rhs, self_.op_, &context, cached_name_id_);
       break;
     case TypedValue::Type::Null:
       // Skip setting properties on Null (can occur in optional match).
diff --git a/src/query/plan/operator.hpp b/src/query/plan/operator.hpp
index 1ca3028c8..b17254e8d 100644
--- a/src/query/plan/operator.hpp
+++ b/src/query/plan/operator.hpp
@@ -1263,6 +1263,7 @@ class SetProperties : public memgraph::query::plan::LogicalOperator {
    private:
     const SetProperties &self_;
     const UniqueCursorPtr input_cursor_;
+    std::unordered_map<std::string, storage::PropertyId> cached_name_id_{};
   };
 };