#pragma once #include #include #include #include #include namespace DB { class Context; class IFunction; using FunctionPtr = std::shared_ptr; namespace ErrorCodes { extern const int LOGICAL_ERROR; } /** Creates function by name. * Function could use for initialization (take ownership of shared_ptr, for example) * some dictionaries from Context. */ class FunctionFactory : public ext::singleton { friend class StorageSystemFunctions; private: using Creator = FunctionPtr(*)(const Context & context); /// Not std::function, for lower object size and less indirection. std::unordered_map functions; public: FunctionFactory(); FunctionPtr get(const std::string & name, const Context & context) const; /// Throws an exception if not found. FunctionPtr tryGet(const std::string & name, const Context & context) const; /// Returns nullptr if not found. /// No locking, you must register all functions before usage of get, tryGet. template void registerFunction() { static_assert(std::is_same::value, "Function::create has incorrect type"); if (!functions.emplace(std::string(Function::name), &Function::create).second) throw Exception("FunctionFactory: the function name '" + std::string(Function::name) + "' is not unique", ErrorCodes::LOGICAL_ERROR); } }; }