#pragma once #include #include #include #include #include #include #include #include namespace DB { class Context; class ASTCreateQuery; class ASTStorage; struct StorageID; /** Allows to create a table by the name and parameters of the engine. * In 'columns' Nested data structures must be flattened. * You should subsequently call IStorage::startup method to work with table. */ class StorageFactory : private boost::noncopyable, public IHints<1, StorageFactory> { public: static StorageFactory & instance(); struct Arguments { const String & engine_name; ASTs & engine_args; ASTStorage * storage_def; const ASTCreateQuery & query; /// Path to table data. /// Relative to from server config (possibly of some of some for *MergeTree) const String & relative_data_path; const StorageID & table_id; ContextWeakMutablePtr local_context; ContextWeakMutablePtr context; const ColumnsDescription & columns; const ConstraintsDescription & constraints; bool attach; bool has_force_restore_data_flag; const String & comment; ContextMutablePtr getContext() const; ContextMutablePtr getLocalContext() const; }; /// Analog of the IStorage::supports*() helpers /// (But the former cannot be replaced with StorageFeatures due to nesting) struct StorageFeatures { bool supports_settings = false; bool supports_skipping_indices = false; bool supports_projections = false; bool supports_sort_order = false; bool supports_ttl = false; /// See also IStorage::supportsReplication() bool supports_replication = false; /// See also IStorage::supportsDeduplication() bool supports_deduplication = false; /// See also IStorage::supportsParallelInsert() bool supports_parallel_insert = false; bool supports_schema_inference = false; AccessType source_access_type = AccessType::NONE; }; using CreatorFn = std::function; struct Creator { CreatorFn creator_fn; StorageFeatures features; }; using Storages = std::unordered_map; StoragePtr get( const ASTCreateQuery & query, const String & relative_data_path, ContextMutablePtr local_context, ContextMutablePtr context, const ColumnsDescription & columns, const ConstraintsDescription & constraints, bool has_force_restore_data_flag) const; /// Register a table engine by its name. /// No locking, you must register all engines before usage of get. void registerStorage(const std::string & name, CreatorFn creator_fn, StorageFeatures features = StorageFeatures{ .supports_settings = false, .supports_skipping_indices = false, .supports_projections = false, .supports_sort_order = false, .supports_ttl = false, .supports_replication = false, .supports_deduplication = false, .supports_parallel_insert = false, .supports_schema_inference = false, .source_access_type = AccessType::NONE, }); const Storages & getAllStorages() const { return storages; } std::vector getAllRegisteredNames() const override { std::vector result; auto getter = [](const auto & pair) { return pair.first; }; std::transform(storages.begin(), storages.end(), std::back_inserter(result), getter); return result; } using FeatureMatcherFn = std::function; std::vector getAllRegisteredNamesByFeatureMatcherFn(FeatureMatcherFn feature_matcher_fn) const { std::vector result; for (const auto& pair : storages) if (feature_matcher_fn(pair.second.features)) result.push_back(pair.first); return result; } AccessType getSourceAccessType(const String & table_engine) const; bool checkIfStorageSupportsSchemaInterface(const String & storage_name) { if (storages.contains(storage_name)) return storages[storage_name].features.supports_schema_inference; return false; } private: Storages storages; }; }