Move FindProcedure to module.hpp
Summary: The function will also be used during AST construction in order to support `CALL ... YIELD *` syntax. Reviewers: mferencevic, ipaljak Reviewed By: mferencevic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2586
This commit is contained in:
parent
8da71873a7
commit
d9abb7ccf1
@ -3735,34 +3735,6 @@ std::vector<Symbol> CallProcedure::ModifiedSymbols(
|
||||
|
||||
namespace {
|
||||
|
||||
// Return the ModulePtr and `mgp_proc *` of the found procedure after resolving
|
||||
// `fully_qualified_procedure_name`. `memory` is used for temporary allocations
|
||||
// inside this function. ModulePtr must be kept alive to make sure it won't be
|
||||
// unloaded.
|
||||
// @throw QueryRuntimeException if unable to find the procedure.
|
||||
std::pair<procedure::ModulePtr, const mgp_proc *> FindProcedureOrThrow(
|
||||
const std::string_view &fully_qualified_procedure_name,
|
||||
utils::MemoryResource *memory) {
|
||||
utils::pmr::vector<std::string_view> name_parts(memory);
|
||||
utils::Split(&name_parts, fully_qualified_procedure_name, ".");
|
||||
if (name_parts.size() == 1U) {
|
||||
throw QueryRuntimeException("There's no top-level procedure '{}'",
|
||||
fully_qualified_procedure_name);
|
||||
}
|
||||
auto last_dot_pos = fully_qualified_procedure_name.find_last_of('.');
|
||||
CHECK(last_dot_pos != std::string_view::npos);
|
||||
const auto &module_name =
|
||||
fully_qualified_procedure_name.substr(0, last_dot_pos);
|
||||
const auto &proc_name = name_parts.back();
|
||||
auto module = procedure::gModuleRegistry.GetModuleNamed(module_name);
|
||||
if (!module) throw QueryRuntimeException("'{}' isn't loaded!", module_name);
|
||||
const auto &proc_it = module->procedures.find(proc_name);
|
||||
if (proc_it == module->procedures.end())
|
||||
throw QueryRuntimeException("'{}' does not have a procedure named '{}'",
|
||||
module_name, proc_name);
|
||||
return {std::move(module), &proc_it->second};
|
||||
}
|
||||
|
||||
void CallCustomProcedure(const std::string_view &fully_qualified_procedure_name,
|
||||
const mgp_proc &proc,
|
||||
const std::vector<Expression *> &args,
|
||||
@ -3880,8 +3852,14 @@ class CallProcedureCursor : public Cursor {
|
||||
// it's not possible for a single thread to request multiple read locks.
|
||||
// Builtin module registration in query/procedure/module.cpp depends on
|
||||
// this locking scheme.
|
||||
const auto &[module, proc] = FindProcedureOrThrow(
|
||||
self_->procedure_name_, context.evaluation_context.memory);
|
||||
const auto &maybe_found = procedure::FindProcedure(
|
||||
procedure::gModuleRegistry, self_->procedure_name_,
|
||||
context.evaluation_context.memory);
|
||||
if (!maybe_found) {
|
||||
throw QueryRuntimeException("There is no procedure named '{}'.",
|
||||
self_->procedure_name_);
|
||||
}
|
||||
const auto &[module, proc] = *maybe_found;
|
||||
result_.signature = &proc->results;
|
||||
// Use evaluation memory, as invoking a procedure is akin to a simple
|
||||
// evaluation of an expression.
|
||||
|
@ -6,6 +6,9 @@ extern "C" {
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "utils/pmr/vector.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
namespace query::procedure {
|
||||
|
||||
ModuleRegistry gModuleRegistry;
|
||||
@ -213,7 +216,7 @@ bool ModuleRegistry::LoadModuleLibrary(std::filesystem::path path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ModulePtr ModuleRegistry::GetModuleNamed(const std::string_view &name) {
|
||||
ModulePtr ModuleRegistry::GetModuleNamed(const std::string_view &name) const {
|
||||
std::shared_lock<utils::RWLock> guard(lock_);
|
||||
auto found_it = modules_.find(name);
|
||||
if (found_it == modules_.end()) return nullptr;
|
||||
@ -270,4 +273,23 @@ void ModuleRegistry::UnloadAllModules() {
|
||||
modules_.clear();
|
||||
}
|
||||
|
||||
std::optional<std::pair<procedure::ModulePtr, const mgp_proc *>> FindProcedure(
|
||||
const ModuleRegistry &module_registry,
|
||||
const std::string_view &fully_qualified_procedure_name,
|
||||
utils::MemoryResource *memory) {
|
||||
utils::pmr::vector<std::string_view> name_parts(memory);
|
||||
utils::Split(&name_parts, fully_qualified_procedure_name, ".");
|
||||
if (name_parts.size() == 1U) return std::nullopt;
|
||||
auto last_dot_pos = fully_qualified_procedure_name.find_last_of('.');
|
||||
CHECK(last_dot_pos != std::string_view::npos);
|
||||
const auto &module_name =
|
||||
fully_qualified_procedure_name.substr(0, last_dot_pos);
|
||||
const auto &proc_name = name_parts.back();
|
||||
auto module = module_registry.GetModuleNamed(module_name);
|
||||
if (!module) return std::nullopt;
|
||||
const auto &proc_it = module->procedures.find(proc_name);
|
||||
if (proc_it == module->procedures.end()) return std::nullopt;
|
||||
return std::make_pair(std::move(module), &proc_it->second);
|
||||
}
|
||||
|
||||
} // namespace query::procedure
|
||||
|
@ -4,12 +4,14 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "query/procedure/mg_procedure_impl.hpp"
|
||||
#include "utils/memory.hpp"
|
||||
#include "utils/rw_lock.hpp"
|
||||
|
||||
namespace query::procedure {
|
||||
@ -47,7 +49,7 @@ class ModulePtr final {
|
||||
/// Thread-safe registration of modules from libraries, uses utils::RWLock.
|
||||
class ModuleRegistry final {
|
||||
std::map<std::string, Module, std::less<>> modules_;
|
||||
utils::RWLock lock_{utils::RWLock::Priority::WRITE};
|
||||
mutable utils::RWLock lock_{utils::RWLock::Priority::WRITE};
|
||||
|
||||
public:
|
||||
ModuleRegistry();
|
||||
@ -63,7 +65,7 @@ class ModuleRegistry final {
|
||||
|
||||
/// Find a module with given name or return nullptr.
|
||||
/// Takes a read lock.
|
||||
ModulePtr GetModuleNamed(const std::string_view &name);
|
||||
ModulePtr GetModuleNamed(const std::string_view &name) const;
|
||||
|
||||
/// Reload a module with given name and return true if successful.
|
||||
/// Takes a write lock. Builtin modules cannot be reloaded, though true will
|
||||
@ -85,4 +87,13 @@ class ModuleRegistry final {
|
||||
/// Single, global module registry.
|
||||
extern ModuleRegistry gModuleRegistry;
|
||||
|
||||
/// Return the ModulePtr and `mgp_proc *` of the found procedure after resolving
|
||||
/// `fully_qualified_procedure_name`. `memory` is used for temporary allocations
|
||||
/// inside this function. ModulePtr must be kept alive to make sure it won't be
|
||||
/// unloaded.
|
||||
std::optional<std::pair<procedure::ModulePtr, const mgp_proc *>> FindProcedure(
|
||||
const ModuleRegistry &module_registry,
|
||||
const std::string_view &fully_qualified_procedure_name,
|
||||
utils::MemoryResource *memory);
|
||||
|
||||
} // namespace query::procedure
|
||||
|
Loading…
Reference in New Issue
Block a user