Merge pull request #69201 from NikBarykin/allow_arguments_in_custom_database_engines

Allow custom settings in database engine
This commit is contained in:
Vitaly Baranov 2024-09-17 18:26:57 +00:00 committed by GitHub
commit 4f88ccb6a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 54 additions and 31 deletions

View File

@ -59,35 +59,27 @@ void cckMetadataPathForOrdinary(const ASTCreateQuery & create, const String & me
} }
/// validate validates the database engine that's specified in the create query for void DatabaseFactory::validate(const ASTCreateQuery & create_query) const
/// engine arguments, settings and table overrides.
void validate(const ASTCreateQuery & create_query)
{ {
auto * storage = create_query.storage; auto * storage = create_query.storage;
/// Check engine may have arguments
static const std::unordered_set<std::string_view> engines_with_arguments{"MySQL", "MaterializeMySQL", "MaterializedMySQL",
"Lazy", "Replicated", "PostgreSQL", "MaterializedPostgreSQL", "SQLite", "Filesystem", "S3", "HDFS"};
const String & engine_name = storage->engine->name; const String & engine_name = storage->engine->name;
bool engine_may_have_arguments = engines_with_arguments.contains(engine_name); const EngineFeatures & engine_features = database_engines.at(engine_name).features;
if (storage->engine->arguments && !engine_may_have_arguments) /// Check engine may have arguments
if (storage->engine->arguments && !engine_features.supports_arguments)
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Database engine `{}` cannot have arguments", engine_name); throw Exception(ErrorCodes::BAD_ARGUMENTS, "Database engine `{}` cannot have arguments", engine_name);
/// Check engine may have settings /// Check engine may have settings
bool may_have_settings = endsWith(engine_name, "MySQL") || engine_name == "Replicated" || engine_name == "MaterializedPostgreSQL";
bool has_unexpected_element = storage->engine->parameters || storage->partition_by || bool has_unexpected_element = storage->engine->parameters || storage->partition_by ||
storage->primary_key || storage->order_by || storage->primary_key || storage->order_by ||
storage->sample_by; storage->sample_by;
if (has_unexpected_element || (!may_have_settings && storage->settings)) if (has_unexpected_element || (!engine_features.supports_settings && storage->settings))
throw Exception(ErrorCodes::UNKNOWN_ELEMENT_IN_AST, throw Exception(ErrorCodes::UNKNOWN_ELEMENT_IN_AST,
"Database engine `{}` cannot have parameters, primary_key, order_by, sample_by, settings", engine_name); "Database engine `{}` cannot have parameters, primary_key, order_by, sample_by, settings", engine_name);
/// Check engine with table overrides /// Check engine with table overrides
static const std::unordered_set<std::string_view> engines_with_table_overrides{"MaterializeMySQL", "MaterializedMySQL", "MaterializedPostgreSQL"}; if (create_query.table_overrides && !engine_features.supports_table_overrides)
if (create_query.table_overrides && !engines_with_table_overrides.contains(engine_name))
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Database engine `{}` cannot have table overrides", engine_name); throw Exception(ErrorCodes::BAD_ARGUMENTS, "Database engine `{}` cannot have table overrides", engine_name);
} }
@ -121,9 +113,9 @@ DatabasePtr DatabaseFactory::get(const ASTCreateQuery & create, const String & m
return impl; return impl;
} }
void DatabaseFactory::registerDatabase(const std::string & name, CreatorFn creator_fn) void DatabaseFactory::registerDatabase(const std::string & name, CreatorFn creator_fn, EngineFeatures features)
{ {
if (!database_engines.emplace(name, std::move(creator_fn)).second) if (!database_engines.emplace(name, Creator{std::move(creator_fn), features}).second)
throw Exception(ErrorCodes::LOGICAL_ERROR, "DatabaseFactory: the database engine name '{}' is not unique", name); throw Exception(ErrorCodes::LOGICAL_ERROR, "DatabaseFactory: the database engine name '{}' is not unique", name);
} }
@ -154,7 +146,7 @@ DatabasePtr DatabaseFactory::getImpl(const ASTCreateQuery & create, const String
.context = context}; .context = context};
// creator_fn creates and returns a DatabasePtr with the supplied arguments // creator_fn creates and returns a DatabasePtr with the supplied arguments
auto creator_fn = database_engines.at(engine_name); auto creator_fn = database_engines.at(engine_name).creator_fn;
return creator_fn(arguments); return creator_fn(arguments);
} }

View File

@ -43,13 +43,30 @@ public:
ContextPtr & context; ContextPtr & context;
}; };
DatabasePtr get(const ASTCreateQuery & create, const String & metadata_path, ContextPtr context); struct EngineFeatures
{
bool supports_arguments = false;
bool supports_settings = false;
bool supports_table_overrides = false;
};
using CreatorFn = std::function<DatabasePtr(const Arguments & arguments)>; using CreatorFn = std::function<DatabasePtr(const Arguments & arguments)>;
using DatabaseEngines = std::unordered_map<std::string, CreatorFn>; struct Creator
{
CreatorFn creator_fn;
EngineFeatures features;
};
void registerDatabase(const std::string & name, CreatorFn creator_fn); DatabasePtr get(const ASTCreateQuery & create, const String & metadata_path, ContextPtr context);
using DatabaseEngines = std::unordered_map<std::string, Creator>;
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; } const DatabaseEngines & getDatabaseEngines() const { return database_engines; }
@ -65,6 +82,10 @@ private:
DatabaseEngines database_engines; DatabaseEngines database_engines;
DatabasePtr getImpl(const ASTCreateQuery & create, const String & metadata_path, ContextPtr context); 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;
}; };
} }

View File

@ -257,6 +257,6 @@ void registerDatabaseFilesystem(DatabaseFactory & factory)
return std::make_shared<DatabaseFilesystem>(args.database_name, init_path, args.context); return std::make_shared<DatabaseFilesystem>(args.database_name, init_path, args.context);
}; };
factory.registerDatabase("Filesystem", create_fn); factory.registerDatabase("Filesystem", create_fn, {.supports_arguments = true});
} }
} }

View File

@ -253,7 +253,7 @@ void registerDatabaseHDFS(DatabaseFactory & factory)
return std::make_shared<DatabaseHDFS>(args.database_name, source_url, args.context); return std::make_shared<DatabaseHDFS>(args.database_name, source_url, args.context);
}; };
factory.registerDatabase("HDFS", create_fn); factory.registerDatabase("HDFS", create_fn, {.supports_arguments = true});
} }
} // DB } // DB

View File

@ -398,6 +398,6 @@ void registerDatabaseLazy(DatabaseFactory & factory)
cache_expiration_time_seconds, cache_expiration_time_seconds,
args.context); args.context);
}; };
factory.registerDatabase("Lazy", create_fn); factory.registerDatabase("Lazy", create_fn, {.supports_arguments = true});
} }
} }

View File

@ -2001,6 +2001,6 @@ void registerDatabaseReplicated(DatabaseFactory & factory)
replica_name, replica_name,
std::move(database_replicated_settings), args.context); std::move(database_replicated_settings), args.context);
}; };
factory.registerDatabase("Replicated", create_fn); factory.registerDatabase("Replicated", create_fn, {.supports_arguments = true, .supports_settings = true});
} }
} }

View File

@ -326,7 +326,7 @@ void registerDatabaseS3(DatabaseFactory & factory)
return std::make_shared<DatabaseS3>(args.database_name, config, args.context); return std::make_shared<DatabaseS3>(args.database_name, config, args.context);
}; };
factory.registerDatabase("S3", create_fn); factory.registerDatabase("S3", create_fn, {.supports_arguments = true});
} }
} }
#endif #endif

View File

@ -290,8 +290,14 @@ void registerDatabaseMaterializedMySQL(DatabaseFactory & factory)
binlog_client, binlog_client,
std::move(materialize_mode_settings)); std::move(materialize_mode_settings));
}; };
factory.registerDatabase("MaterializeMySQL", create_fn);
factory.registerDatabase("MaterializedMySQL", create_fn); DatabaseFactory::EngineFeatures features{
.supports_arguments = true,
.supports_settings = true,
.supports_table_overrides = true,
};
factory.registerDatabase("MaterializeMySQL", create_fn, features);
factory.registerDatabase("MaterializedMySQL", create_fn, features);
} }
} }

View File

@ -584,7 +584,7 @@ void registerDatabaseMySQL(DatabaseFactory & factory)
throw Exception(ErrorCodes::CANNOT_CREATE_DATABASE, "Cannot create MySQL database, because {}", exception_message); throw Exception(ErrorCodes::CANNOT_CREATE_DATABASE, "Cannot create MySQL database, because {}", exception_message);
} }
}; };
factory.registerDatabase("MySQL", create_fn); factory.registerDatabase("MySQL", create_fn, {.supports_arguments = true, .supports_settings = true});
} }
} }

View File

@ -546,7 +546,11 @@ void registerDatabaseMaterializedPostgreSQL(DatabaseFactory & factory)
args.database_name, configuration.database, connection_info, args.database_name, configuration.database, connection_info,
std::move(postgresql_replica_settings)); std::move(postgresql_replica_settings));
}; };
factory.registerDatabase("MaterializedPostgreSQL", create_fn); factory.registerDatabase("MaterializedPostgreSQL", create_fn, {
.supports_arguments = true,
.supports_settings = true,
.supports_table_overrides = true,
});
} }
} }

View File

@ -558,7 +558,7 @@ void registerDatabasePostgreSQL(DatabaseFactory & factory)
pool, pool,
use_table_cache); use_table_cache);
}; };
factory.registerDatabase("PostgreSQL", create_fn); factory.registerDatabase("PostgreSQL", create_fn, {.supports_arguments = true});
} }
} }

View File

@ -220,7 +220,7 @@ void registerDatabaseSQLite(DatabaseFactory & factory)
return std::make_shared<DatabaseSQLite>(args.context, engine_define, args.create_query.attach, database_path); return std::make_shared<DatabaseSQLite>(args.context, engine_define, args.create_query.attach, database_path);
}; };
factory.registerDatabase("SQLite", create_fn); factory.registerDatabase("SQLite", create_fn, {.supports_arguments = true});
} }
} }