diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index e042f4a63..1ee23236f 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -1095,9 +1095,9 @@ std::shared_ptr<Interpreter::CachedPlan> Interpreter::CypherQueryToPlan( } } return plan_cache_access - .insert(query_hash, - std::make_shared<CachedPlan>(MakeLogicalPlan( - query, std::move(ast_storage), parameters, db_accessor))) + .insert({query_hash, + std::make_shared<CachedPlan>(MakeLogicalPlan( + query, std::move(ast_storage), parameters, db_accessor))}) .first->second; } @@ -1148,9 +1148,9 @@ Interpreter::ParsedQuery Interpreter::ParseQuery( CachedQuery cached_query{std::move(cached_ast_storage), visitor.query(), query::GetRequiredPrivileges(visitor.query())}; // Cache it. - ast_it = - ast_cache_accessor.insert(stripped_query_hash, std::move(cached_query)) - .first; + ast_it = ast_cache_accessor + .insert({stripped_query_hash, std::move(cached_query)}) + .first; } ast_storage->properties_ = ast_it->second.ast_storage.properties_; ast_storage->labels_ = ast_it->second.ast_storage.labels_; diff --git a/src/query/interpreter.hpp b/src/query/interpreter.hpp index ab869dfb6..23a5b84b5 100644 --- a/src/query/interpreter.hpp +++ b/src/query/interpreter.hpp @@ -2,7 +2,6 @@ #include <gflags/gflags.h> -#include "data_structures/concurrent/concurrent_map.hpp" #include "database/graph_db.hpp" #include "database/graph_db_accessor.hpp" #include "query/context.hpp" @@ -11,6 +10,7 @@ #include "query/frontend/stripped.hpp" #include "query/interpret/frame.hpp" #include "query/plan/operator.hpp" +#include "utils/skip_list.hpp" #include "utils/spin_lock.hpp" #include "utils/timer.hpp" @@ -66,8 +66,6 @@ class Interpreter { std::vector<AuthQuery::Privilege> required_privileges; }; - using PlanCacheT = ConcurrentMap<HashType, std::shared_ptr<CachedPlan>>; - public: /** * Wraps a `Query` that was created as a result of parsing a query string @@ -244,8 +242,41 @@ class Interpreter { const plan::LogicalOperator *); private: - ConcurrentMap<HashType, CachedQuery> ast_cache_; - PlanCacheT plan_cache_; + struct QueryCacheEntry { + bool operator==(const QueryCacheEntry &other) const { + return first == other.first; + } + bool operator<(const QueryCacheEntry &other) const { + return first < other.first; + } + bool operator==(const HashType &other) const { return first == other; } + bool operator<(const HashType &other) const { return first < other; } + + HashType first; + // TODO: Maybe store the query string here and use it as a key with the hash + // so that we eliminate the risk of hash collisions. + CachedQuery second; + }; + + struct PlanCacheEntry { + bool operator==(const PlanCacheEntry &other) const { + return first == other.first; + } + bool operator<(const PlanCacheEntry &other) const { + return first < other.first; + } + bool operator==(const HashType &other) const { return first == other; } + bool operator<(const HashType &other) const { return first < other; } + + HashType first; + // TODO: Maybe store the query string here and use it as a key with the hash + // so that we eliminate the risk of hash collisions. + std::shared_ptr<CachedPlan> second; + }; + + utils::SkipList<QueryCacheEntry> ast_cache_; + utils::SkipList<PlanCacheEntry> plan_cache_; + // Antlr has singleton instance that is shared between threads. It is // protected by locks inside of antlr. Unfortunately, they are not protected // in a very good way. Once we have antlr version without race conditions we