#pragma once #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int BAD_ARGUMENTS; } class ASTCreateQuery; template static inline ValueType safeGetLiteralValue(const ASTPtr &ast, const String &engine_name) { if (!ast || !ast->as()) throw Exception(ErrorCodes::BAD_ARGUMENTS, "Database engine {} requested literal argument.", engine_name); return ast->as()->value.safeGet(); } class DatabaseFactory : private boost::noncopyable, public IHints<> { public: static DatabaseFactory & instance(); struct Arguments { const String & engine_name; ASTs & engine_args; ASTStorage * storage = nullptr; const ASTCreateQuery & create_query; const String & database_name; const String & metadata_path; const UUID & uuid; ContextPtr & context; }; struct EngineFeatures { bool supports_arguments = false; bool supports_settings = false; bool supports_table_overrides = false; }; using CreatorFn = std::function; struct Creator { CreatorFn creator_fn; EngineFeatures features; }; DatabasePtr get(const ASTCreateQuery & create, const String & metadata_path, ContextPtr context); using DatabaseEngines = std::unordered_map; void registerDatabase(const std::string & name, CreatorFn creator_fn, EngineFeatures features = EngineFeatures{ .supports_arguments = false, .supports_settings = false, .supports_table_overrides = false, }); const DatabaseEngines & getDatabaseEngines() const { return database_engines; } std::vector getAllRegisteredNames() const override { std::vector result; auto getter = [](const auto & pair) { return pair.first; }; std::transform(database_engines.begin(), database_engines.end(), std::back_inserter(result), getter); return result; } private: DatabaseEngines database_engines; DatabasePtr getImpl(const ASTCreateQuery & create, const String & metadata_path, ContextPtr context); /// validate validates the database engine that's specified in the create query for /// engine arguments, settings and table overrides. void validate(const ASTCreateQuery & create_query) const; }; }