mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-30 05:30:51 +00:00
refactor InterpreterCreateQuery::createTable(...)
This commit is contained in:
parent
3eaa96e666
commit
9c461ff143
@ -269,16 +269,8 @@ void DatabaseOrdinary::alterTable(
|
|||||||
ASTPtr new_constraints = InterpreterCreateQuery::formatConstraints(constraints);
|
ASTPtr new_constraints = InterpreterCreateQuery::formatConstraints(constraints);
|
||||||
|
|
||||||
ast_create_query.columns_list->replace(ast_create_query.columns_list->columns, new_columns);
|
ast_create_query.columns_list->replace(ast_create_query.columns_list->columns, new_columns);
|
||||||
|
ast_create_query.columns_list->setOrReplace(ast_create_query.columns_list->indices, new_indices);
|
||||||
if (ast_create_query.columns_list->indices)
|
ast_create_query.columns_list->setOrReplace(ast_create_query.columns_list->constraints, new_constraints);
|
||||||
ast_create_query.columns_list->replace(ast_create_query.columns_list->indices, new_indices);
|
|
||||||
else
|
|
||||||
ast_create_query.columns_list->set(ast_create_query.columns_list->indices, new_indices);
|
|
||||||
|
|
||||||
if (ast_create_query.columns_list->constraints)
|
|
||||||
ast_create_query.columns_list->replace(ast_create_query.columns_list->constraints, new_constraints);
|
|
||||||
else
|
|
||||||
ast_create_query.columns_list->set(ast_create_query.columns_list->constraints, new_constraints);
|
|
||||||
|
|
||||||
if (storage_modifier)
|
if (storage_modifier)
|
||||||
storage_modifier(*ast_create_query.storage);
|
storage_modifier(*ast_create_query.storage);
|
||||||
|
@ -402,83 +402,96 @@ ConstraintsDescription InterpreterCreateQuery::getConstraintsDescription(const A
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ColumnsDescription InterpreterCreateQuery::setProperties(
|
InterpreterCreateQuery::TableProperties InterpreterCreateQuery::setProperties(ASTCreateQuery & create) const
|
||||||
ASTCreateQuery & create, const Block & as_select_sample, const StoragePtr & as_storage) const
|
|
||||||
{
|
{
|
||||||
ColumnsDescription columns;
|
TableProperties properties;
|
||||||
IndicesDescription indices;
|
TableStructureReadLockHolder as_storage_lock;
|
||||||
ConstraintsDescription constraints;
|
|
||||||
|
|
||||||
if (create.columns_list)
|
if (create.columns_list)
|
||||||
{
|
{
|
||||||
if (create.columns_list->columns)
|
if (create.columns_list->columns)
|
||||||
columns = getColumnsDescription(*create.columns_list->columns, context);
|
properties.columns = getColumnsDescription(*create.columns_list->columns, context);
|
||||||
|
|
||||||
if (create.columns_list->indices)
|
if (create.columns_list->indices)
|
||||||
for (const auto & index : create.columns_list->indices->children)
|
for (const auto & index : create.columns_list->indices->children)
|
||||||
indices.indices.push_back(
|
properties.indices.indices.push_back(
|
||||||
std::dynamic_pointer_cast<ASTIndexDeclaration>(index->clone()));
|
std::dynamic_pointer_cast<ASTIndexDeclaration>(index->clone()));
|
||||||
|
|
||||||
if (create.columns_list->constraints)
|
properties.constraints = getConstraintsDescription(create.columns_list->constraints);
|
||||||
for (const auto & constraint : create.columns_list->constraints->children)
|
|
||||||
constraints.constraints.push_back(
|
|
||||||
std::dynamic_pointer_cast<ASTConstraintDeclaration>(constraint->clone()));
|
|
||||||
}
|
}
|
||||||
else if (!create.as_table.empty())
|
else if (!create.as_table.empty())
|
||||||
{
|
{
|
||||||
columns = as_storage->getColumns();
|
String as_database_name = create.as_database.empty() ? context.getCurrentDatabase() : create.as_database;
|
||||||
|
StoragePtr as_storage = context.getTable(as_database_name, create.as_table);
|
||||||
|
|
||||||
|
/// as_storage->getColumns() and setEngine(...) must be called under structure lock of other_table for CREATE ... AS other_table.
|
||||||
|
as_storage_lock = as_storage->lockStructureForShare(false, context.getCurrentQueryId());
|
||||||
|
properties.columns = as_storage->getColumns();
|
||||||
|
|
||||||
/// Secondary indices make sense only for MergeTree family of storage engines.
|
/// Secondary indices make sense only for MergeTree family of storage engines.
|
||||||
/// We should not copy them for other storages.
|
/// We should not copy them for other storages.
|
||||||
if (create.storage && endsWith(create.storage->engine->name, "MergeTree"))
|
if (create.storage && endsWith(create.storage->engine->name, "MergeTree"))
|
||||||
indices = as_storage->getIndices();
|
properties.indices = as_storage->getIndices();
|
||||||
|
|
||||||
constraints = as_storage->getConstraints();
|
properties.constraints = as_storage->getConstraints();
|
||||||
}
|
}
|
||||||
else if (create.select)
|
else if (create.select)
|
||||||
{
|
{
|
||||||
columns = ColumnsDescription(as_select_sample.getNamesAndTypesList());
|
Block as_select_sample = InterpreterSelectWithUnionQuery::getSampleBlock(create.select->clone(), context);
|
||||||
|
properties.columns = ColumnsDescription(as_select_sample.getNamesAndTypesList());
|
||||||
}
|
}
|
||||||
|
else if (create.as_table_function)
|
||||||
|
return {};
|
||||||
else
|
else
|
||||||
throw Exception("Incorrect CREATE query: required list of column descriptions or AS section or SELECT.", ErrorCodes::INCORRECT_QUERY);
|
throw Exception("Incorrect CREATE query: required list of column descriptions or AS section or SELECT.", ErrorCodes::INCORRECT_QUERY);
|
||||||
|
|
||||||
/// Even if query has list of columns, canonicalize it (unfold Nested columns).
|
|
||||||
ASTPtr new_columns = formatColumns(columns);
|
|
||||||
ASTPtr new_indices = formatIndices(indices);
|
|
||||||
ASTPtr new_constraints = formatConstraints(constraints);
|
|
||||||
|
|
||||||
|
/// Even if query has list of columns, canonicalize it (unfold Nested columns).
|
||||||
if (!create.columns_list)
|
if (!create.columns_list)
|
||||||
{
|
create.set(create.columns_list, std::make_shared<ASTColumns>());
|
||||||
auto new_columns_list = std::make_shared<ASTColumns>();
|
|
||||||
create.set(create.columns_list, new_columns_list);
|
ASTPtr new_columns = formatColumns(properties.columns);
|
||||||
|
ASTPtr new_indices = formatIndices(properties.indices);
|
||||||
|
ASTPtr new_constraints = formatConstraints(properties.constraints);
|
||||||
|
|
||||||
|
create.columns_list->setOrReplace(create.columns_list->columns, new_columns);
|
||||||
|
create.columns_list->setOrReplace(create.columns_list->indices, new_indices);
|
||||||
|
create.columns_list->setOrReplace(create.columns_list->constraints, new_constraints);
|
||||||
|
|
||||||
|
validateTableStructure(create, properties);
|
||||||
|
|
||||||
|
/// Set the table engine if it was not specified explicitly.
|
||||||
|
setEngine(create);
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create.columns_list->columns)
|
void InterpreterCreateQuery::validateTableStructure(const ASTCreateQuery & create,
|
||||||
create.columns_list->replace(create.columns_list->columns, new_columns);
|
const InterpreterCreateQuery::TableProperties & properties) const
|
||||||
else
|
{
|
||||||
create.columns_list->set(create.columns_list->columns, new_columns);
|
|
||||||
|
|
||||||
if (new_indices && create.columns_list->indices)
|
|
||||||
create.columns_list->replace(create.columns_list->indices, new_indices);
|
|
||||||
else if (new_indices)
|
|
||||||
create.columns_list->set(create.columns_list->indices, new_indices);
|
|
||||||
|
|
||||||
if (new_constraints && create.columns_list->constraints)
|
|
||||||
create.columns_list->replace(create.columns_list->constraints, new_constraints);
|
|
||||||
else if (new_constraints)
|
|
||||||
create.columns_list->set(create.columns_list->constraints, new_constraints);
|
|
||||||
|
|
||||||
/// Check for duplicates
|
/// Check for duplicates
|
||||||
std::set<String> all_columns;
|
std::set<String> all_columns;
|
||||||
for (const auto & column : columns)
|
for (const auto & column : properties.columns)
|
||||||
{
|
{
|
||||||
if (!all_columns.emplace(column.name).second)
|
if (!all_columns.emplace(column.name).second)
|
||||||
throw Exception("Column " + backQuoteIfNeed(column.name) + " already exists", ErrorCodes::DUPLICATE_COLUMN);
|
throw Exception("Column " + backQuoteIfNeed(column.name) + " already exists", ErrorCodes::DUPLICATE_COLUMN);
|
||||||
}
|
}
|
||||||
|
|
||||||
return columns;
|
/// Check low cardinality types in creating table if it was not allowed in setting
|
||||||
|
if (!create.attach && !context.getSettingsRef().allow_suspicious_low_cardinality_types && !create.is_materialized_view)
|
||||||
|
{
|
||||||
|
for (const auto & name_and_type_pair : properties.columns.getAllPhysical())
|
||||||
|
{
|
||||||
|
if (const auto * current_type_ptr = typeid_cast<const DataTypeLowCardinality *>(name_and_type_pair.type.get()))
|
||||||
|
{
|
||||||
|
if (!isStringOrFixedString(*removeNullable(current_type_ptr->getDictionaryType())))
|
||||||
|
throw Exception("Creating columns of type " + current_type_ptr->getName() + " is prohibited by default "
|
||||||
|
"due to expected negative impact on performance. "
|
||||||
|
"It can be enabled with the \"allow_suspicious_low_cardinality_types\" setting.",
|
||||||
|
ErrorCodes::SUSPICIOUS_TYPE_FOR_LOW_CARDINALITY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
|
void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
|
||||||
{
|
{
|
||||||
@ -541,12 +554,10 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
throw Exception("Temporary tables cannot be inside a database. You should not specify a database for a temporary table.",
|
throw Exception("Temporary tables cannot be inside a database. You should not specify a database for a temporary table.",
|
||||||
ErrorCodes::BAD_DATABASE_FOR_TEMPORARY_TABLE);
|
ErrorCodes::BAD_DATABASE_FOR_TEMPORARY_TABLE);
|
||||||
|
|
||||||
String path = context.getPath();
|
|
||||||
String current_database = context.getCurrentDatabase();
|
String current_database = context.getCurrentDatabase();
|
||||||
|
|
||||||
String database_name = create.database.empty() ? current_database : create.database;
|
String database_name = create.database.empty() ? current_database : create.database;
|
||||||
String table_name = create.table;
|
String table_name = create.table;
|
||||||
String table_name_escaped = escapeForFileName(table_name);
|
|
||||||
|
|
||||||
// If this is a stub ATTACH query, read the query definition from the database
|
// If this is a stub ATTACH query, read the query definition from the database
|
||||||
if (create.attach && !create.storage && !create.columns_list)
|
if (create.attach && !create.storage && !create.columns_list)
|
||||||
@ -566,68 +577,35 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
visitor.visit(*create.select);
|
visitor.visit(*create.select);
|
||||||
}
|
}
|
||||||
|
|
||||||
Block as_select_sample;
|
/// Set and retrieve list of columns, indices and constraints. Set table engine if needed. Rewrite query in canonical way.
|
||||||
if (create.select && (!create.attach || !create.columns_list))
|
TableProperties properties = setProperties(create);
|
||||||
as_select_sample = InterpreterSelectWithUnionQuery::getSampleBlock(create.select->clone(), context);
|
|
||||||
|
|
||||||
String as_database_name = create.as_database.empty() ? current_database : create.as_database;
|
/// Actually creates table
|
||||||
String as_table_name = create.as_table;
|
bool created = doCreateTable(create, properties, database_name);
|
||||||
|
if (!created)
|
||||||
|
return {};
|
||||||
|
|
||||||
StoragePtr as_storage;
|
return fillTableIfNeeded(create, database_name);
|
||||||
TableStructureReadLockHolder as_storage_lock;
|
|
||||||
|
|
||||||
if (!as_table_name.empty())
|
|
||||||
{
|
|
||||||
as_storage = context.getTable(as_database_name, as_table_name);
|
|
||||||
as_storage_lock = as_storage->lockStructureForShare(false, context.getCurrentQueryId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnsDescription columns;
|
|
||||||
ConstraintsDescription constraints;
|
|
||||||
StoragePtr res;
|
|
||||||
|
|
||||||
if (create.as_table_function)
|
|
||||||
{
|
|
||||||
const auto & table_function = create.as_table_function->as<ASTFunction &>();
|
|
||||||
const auto & factory = TableFunctionFactory::instance();
|
|
||||||
res = factory.get(table_function.name, context)->execute(create.as_table_function, context, create.table);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/// Set and retrieve list of columns.
|
|
||||||
columns = setProperties(create, as_select_sample, as_storage);
|
|
||||||
constraints = getConstraintsDescription(create.columns_list->constraints);
|
|
||||||
|
|
||||||
/// Check low cardinality types in creating table if it was not allowed in setting
|
|
||||||
if (!create.attach && !context.getSettingsRef().allow_suspicious_low_cardinality_types && !create.is_materialized_view)
|
|
||||||
{
|
|
||||||
for (const auto & name_and_type_pair : columns.getAllPhysical())
|
|
||||||
{
|
|
||||||
if (const auto * current_type_ptr = typeid_cast<const DataTypeLowCardinality *>(name_and_type_pair.type.get()))
|
|
||||||
{
|
|
||||||
if (!isStringOrFixedString(*removeNullable(current_type_ptr->getDictionaryType())))
|
|
||||||
throw Exception("Creating columns of type " + current_type_ptr->getName() + " is prohibited by default due to expected negative impact on performance. It can be enabled with the \"allow_suspicious_low_cardinality_types\" setting.",
|
|
||||||
ErrorCodes::SUSPICIOUS_TYPE_FOR_LOW_CARDINALITY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the table engine if it was not specified explicitly.
|
|
||||||
setEngine(create);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterpreterCreateQuery::doCreateTable(const ASTCreateQuery & create,
|
||||||
|
const InterpreterCreateQuery::TableProperties & properties,
|
||||||
|
const String & database_name)
|
||||||
{
|
{
|
||||||
std::unique_ptr<DDLGuard> guard;
|
std::unique_ptr<DDLGuard> guard;
|
||||||
|
|
||||||
String data_path;
|
String data_path;
|
||||||
DatabasePtr database;
|
DatabasePtr database;
|
||||||
|
|
||||||
if (!create.temporary || create.is_live_view)
|
const String & table_name = create.table;
|
||||||
|
bool need_add_to_database = !create.temporary || create.is_live_view;
|
||||||
|
if (need_add_to_database)
|
||||||
{
|
{
|
||||||
database = context.getDatabase(database_name);
|
database = context.getDatabase(database_name);
|
||||||
if (!create.uuid.empty() && database->getEngineName() != "Atomic")
|
if (!create.uuid.empty() && database->getEngineName() != "Atomic")
|
||||||
throw Exception("Table UUID specified, but engine of database " + database_name + " is not Atomic",
|
throw Exception("Table UUID specified, but engine of database " + database_name + " is not Atomic",
|
||||||
ErrorCodes::INCORRECT_QUERY);
|
ErrorCodes::INCORRECT_QUERY);
|
||||||
|
|
||||||
data_path = database->getDataPath();
|
data_path = database->getDataPath();
|
||||||
|
|
||||||
/** If the request specifies IF NOT EXISTS, we allow concurrent CREATE queries (which do nothing).
|
/** If the request specifies IF NOT EXISTS, we allow concurrent CREATE queries (which do nothing).
|
||||||
@ -639,7 +617,7 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
if (database->isTableExist(context, table_name))
|
if (database->isTableExist(context, table_name))
|
||||||
{
|
{
|
||||||
if (create.if_not_exists)
|
if (create.if_not_exists)
|
||||||
return {};
|
return false;
|
||||||
else if (create.replace_view)
|
else if (create.replace_view)
|
||||||
{
|
{
|
||||||
/// when executing CREATE OR REPLACE VIEW, drop current existing view
|
/// when executing CREATE OR REPLACE VIEW, drop current existing view
|
||||||
@ -656,9 +634,16 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (context.tryGetExternalTable(table_name) && create.if_not_exists)
|
else if (context.tryGetExternalTable(table_name) && create.if_not_exists)
|
||||||
return {};
|
return false;
|
||||||
|
|
||||||
if (!create.as_table_function)
|
StoragePtr res;
|
||||||
|
if (create.as_table_function)
|
||||||
|
{
|
||||||
|
const auto & table_function = create.as_table_function->as<ASTFunction &>();
|
||||||
|
const auto & factory = TableFunctionFactory::instance();
|
||||||
|
res = factory.get(table_function.name, context)->execute(create.as_table_function, context, create.table);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
res = StorageFactory::instance().get(create,
|
res = StorageFactory::instance().get(create,
|
||||||
data_path,
|
data_path,
|
||||||
@ -666,16 +651,16 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
database_name,
|
database_name,
|
||||||
context,
|
context,
|
||||||
context.getGlobalContext(),
|
context.getGlobalContext(),
|
||||||
columns,
|
properties.columns,
|
||||||
constraints,
|
properties.constraints,
|
||||||
create.attach,
|
create.attach,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create.temporary && !create.is_live_view)
|
if (need_add_to_database)
|
||||||
context.getSessionContext().addExternalTable(table_name, res, query_ptr);
|
|
||||||
else
|
|
||||||
database->createTable(context, table_name, res, query_ptr);
|
database->createTable(context, table_name, res, query_ptr);
|
||||||
|
else
|
||||||
|
context.getSessionContext().addExternalTable(table_name, res, query_ptr);
|
||||||
|
|
||||||
/// We must call "startup" and "shutdown" while holding DDLGuard.
|
/// We must call "startup" and "shutdown" while holding DDLGuard.
|
||||||
/// Because otherwise method "shutdown" (from InterpreterDropQuery) can be called before startup
|
/// Because otherwise method "shutdown" (from InterpreterDropQuery) can be called before startup
|
||||||
@ -687,8 +672,11 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
/// and the task will use references to freed data.
|
/// and the task will use references to freed data.
|
||||||
|
|
||||||
res->startup();
|
res->startup();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BlockIO InterpreterCreateQuery::fillTableIfNeeded(const ASTCreateQuery & create, const String & database_name)
|
||||||
|
{
|
||||||
/// If the query is a CREATE SELECT, insert the data into the table.
|
/// If the query is a CREATE SELECT, insert the data into the table.
|
||||||
if (create.select && !create.attach
|
if (create.select && !create.attach
|
||||||
&& !create.is_view && !create.is_live_view && (!create.is_materialized_view || create.is_populate))
|
&& !create.is_view && !create.is_live_view && (!create.is_materialized_view || create.is_populate))
|
||||||
@ -698,7 +686,7 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
|
|||||||
if (!create.temporary)
|
if (!create.temporary)
|
||||||
insert->database = database_name;
|
insert->database = database_name;
|
||||||
|
|
||||||
insert->table = table_name;
|
insert->table = create.table;
|
||||||
insert->select = create.select->clone();
|
insert->select = create.select->clone();
|
||||||
|
|
||||||
if (create.temporary && !context.getSessionContext().hasQueryContext())
|
if (create.temporary && !context.getSessionContext().hasQueryContext())
|
||||||
|
@ -49,14 +49,27 @@ public:
|
|||||||
static ConstraintsDescription getConstraintsDescription(const ASTExpressionList * constraints);
|
static ConstraintsDescription getConstraintsDescription(const ASTExpressionList * constraints);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct TableProperties
|
||||||
|
{
|
||||||
|
ColumnsDescription columns;
|
||||||
|
IndicesDescription indices;
|
||||||
|
ConstraintsDescription constraints;
|
||||||
|
};
|
||||||
|
|
||||||
BlockIO createDatabase(ASTCreateQuery & create);
|
BlockIO createDatabase(ASTCreateQuery & create);
|
||||||
BlockIO createTable(ASTCreateQuery & create);
|
BlockIO createTable(ASTCreateQuery & create);
|
||||||
|
|
||||||
/// Calculate list of columns, constraints, indices, etc... of table and return columns.
|
/// Calculate list of columns, constraints, indices, etc... of table. Rewrite query in canonical way.
|
||||||
ColumnsDescription setProperties(ASTCreateQuery & create, const Block & as_select_sample, const StoragePtr & as_storage) const;
|
TableProperties setProperties(ASTCreateQuery & create) const;
|
||||||
|
void validateTableStructure(const ASTCreateQuery & create, const TableProperties & properties) const;
|
||||||
void setEngine(ASTCreateQuery & create) const;
|
void setEngine(ASTCreateQuery & create) const;
|
||||||
void checkAccess(const ASTCreateQuery & create);
|
void checkAccess(const ASTCreateQuery & create);
|
||||||
|
|
||||||
|
/// Create IStorage and add it to database. If table already exists and IF NOT EXISTS specified, do nothing and return false.
|
||||||
|
bool doCreateTable(const ASTCreateQuery & create, const TableProperties & properties, const String & database_name);
|
||||||
|
/// Inserts data in created table if it's CREATE ... SELECT
|
||||||
|
BlockIO fillTableIfNeeded(const ASTCreateQuery & create, const String & database_name);
|
||||||
|
|
||||||
ASTPtr query_ptr;
|
ASTPtr query_ptr;
|
||||||
Context & context;
|
Context & context;
|
||||||
|
|
||||||
|
@ -146,6 +146,15 @@ public:
|
|||||||
throw Exception("AST subtree not found in children", ErrorCodes::LOGICAL_ERROR);
|
throw Exception("AST subtree not found in children", ErrorCodes::LOGICAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void setOrReplace(T * & field, const ASTPtr & child)
|
||||||
|
{
|
||||||
|
if (field)
|
||||||
|
replace(field, child);
|
||||||
|
else
|
||||||
|
set(field, child);
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert to a string.
|
/// Convert to a string.
|
||||||
|
|
||||||
/// Format settings.
|
/// Format settings.
|
||||||
|
@ -39,7 +39,7 @@ void StorageFactory::registerStorage(const std::string & name, Creator creator)
|
|||||||
|
|
||||||
|
|
||||||
StoragePtr StorageFactory::get(
|
StoragePtr StorageFactory::get(
|
||||||
ASTCreateQuery & query,
|
const ASTCreateQuery & query,
|
||||||
const String & data_path,
|
const String & data_path,
|
||||||
const String & table_name,
|
const String & table_name,
|
||||||
const String & database_name,
|
const String & database_name,
|
||||||
|
@ -46,7 +46,7 @@ public:
|
|||||||
using Creator = std::function<StoragePtr(const Arguments & arguments)>;
|
using Creator = std::function<StoragePtr(const Arguments & arguments)>;
|
||||||
|
|
||||||
StoragePtr get(
|
StoragePtr get(
|
||||||
ASTCreateQuery & query,
|
const ASTCreateQuery & query,
|
||||||
const String & data_path,
|
const String & data_path,
|
||||||
const String & table_name,
|
const String & table_name,
|
||||||
const String & database_name,
|
const String & database_name,
|
||||||
|
Loading…
Reference in New Issue
Block a user