mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
Merge branch 'master' into mmap-for-storage-file
This commit is contained in:
commit
743146da5d
@ -37,7 +37,7 @@
|
|||||||
#include <AggregateFunctions/registerAggregateFunctions.h>
|
#include <AggregateFunctions/registerAggregateFunctions.h>
|
||||||
#include <TableFunctions/registerTableFunctions.h>
|
#include <TableFunctions/registerTableFunctions.h>
|
||||||
#include <Storages/registerStorages.h>
|
#include <Storages/registerStorages.h>
|
||||||
#include <Storages/NamedCollections.h>
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
#include <Dictionaries/registerDictionaries.h>
|
#include <Dictionaries/registerDictionaries.h>
|
||||||
#include <Disks/registerDisks.h>
|
#include <Disks/registerDisks.h>
|
||||||
#include <Formats/registerFormats.h>
|
#include <Formats/registerFormats.h>
|
||||||
@ -120,7 +120,7 @@ void LocalServer::initialize(Poco::Util::Application & self)
|
|||||||
config().getUInt("max_io_thread_pool_free_size", 0),
|
config().getUInt("max_io_thread_pool_free_size", 0),
|
||||||
config().getUInt("io_thread_pool_queue_size", 10000));
|
config().getUInt("io_thread_pool_queue_size", 10000));
|
||||||
|
|
||||||
NamedCollectionFactory::instance().initialize(config());
|
NamedCollectionUtils::loadFromConfig(config());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -212,6 +212,8 @@ void LocalServer::tryInitPath()
|
|||||||
|
|
||||||
global_context->setUserFilesPath(""); // user's files are everywhere
|
global_context->setUserFilesPath(""); // user's files are everywhere
|
||||||
|
|
||||||
|
NamedCollectionUtils::loadFromSQL(global_context);
|
||||||
|
|
||||||
/// top_level_domains_lists
|
/// top_level_domains_lists
|
||||||
const std::string & top_level_domains_path = config().getString("top_level_domains_path", path + "top_level_domains/");
|
const std::string & top_level_domains_path = config().getString("top_level_domains_path", path + "top_level_domains/");
|
||||||
if (!top_level_domains_path.empty())
|
if (!top_level_domains_path.empty())
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
#include <Storages/System/attachInformationSchemaTables.h>
|
#include <Storages/System/attachInformationSchemaTables.h>
|
||||||
#include <Storages/Cache/ExternalDataSourceCache.h>
|
#include <Storages/Cache/ExternalDataSourceCache.h>
|
||||||
#include <Storages/Cache/registerRemoteFileMetadatas.h>
|
#include <Storages/Cache/registerRemoteFileMetadatas.h>
|
||||||
#include <Storages/NamedCollections.h>
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
#include <AggregateFunctions/registerAggregateFunctions.h>
|
#include <AggregateFunctions/registerAggregateFunctions.h>
|
||||||
#include <Functions/UserDefined/IUserDefinedSQLObjectsLoader.h>
|
#include <Functions/UserDefined/IUserDefinedSQLObjectsLoader.h>
|
||||||
#include <Functions/registerFunctions.h>
|
#include <Functions/registerFunctions.h>
|
||||||
@ -782,7 +782,7 @@ try
|
|||||||
config().getUInt("max_io_thread_pool_free_size", 0),
|
config().getUInt("max_io_thread_pool_free_size", 0),
|
||||||
config().getUInt("io_thread_pool_queue_size", 10000));
|
config().getUInt("io_thread_pool_queue_size", 10000));
|
||||||
|
|
||||||
NamedCollectionFactory::instance().initialize(config());
|
NamedCollectionUtils::loadFromConfig(config());
|
||||||
|
|
||||||
/// Initialize global local cache for remote filesystem.
|
/// Initialize global local cache for remote filesystem.
|
||||||
if (config().has("local_cache_for_remote_fs"))
|
if (config().has("local_cache_for_remote_fs"))
|
||||||
@ -1168,6 +1168,8 @@ try
|
|||||||
SensitiveDataMasker::setInstance(std::make_unique<SensitiveDataMasker>(config(), "query_masking_rules"));
|
SensitiveDataMasker::setInstance(std::make_unique<SensitiveDataMasker>(config(), "query_masking_rules"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NamedCollectionUtils::loadFromSQL(global_context);
|
||||||
|
|
||||||
auto main_config_reloader = std::make_unique<ConfigReloader>(
|
auto main_config_reloader = std::make_unique<ConfigReloader>(
|
||||||
config_path,
|
config_path,
|
||||||
include_from_path,
|
include_from_path,
|
||||||
@ -1336,7 +1338,8 @@ try
|
|||||||
#if USE_SSL
|
#if USE_SSL
|
||||||
CertificateReloader::instance().tryLoad(*config);
|
CertificateReloader::instance().tryLoad(*config);
|
||||||
#endif
|
#endif
|
||||||
NamedCollectionFactory::instance().reload(*config);
|
NamedCollectionUtils::reloadFromConfig(*config);
|
||||||
|
|
||||||
ProfileEvents::increment(ProfileEvents::MainConfigLoads);
|
ProfileEvents::increment(ProfileEvents::MainConfigLoads);
|
||||||
|
|
||||||
/// Must be the last.
|
/// Must be the last.
|
||||||
|
@ -104,7 +104,7 @@ public:
|
|||||||
/// The same as allColumnFlags().
|
/// The same as allColumnFlags().
|
||||||
static AccessFlags allFlagsGrantableOnColumnLevel();
|
static AccessFlags allFlagsGrantableOnColumnLevel();
|
||||||
|
|
||||||
static constexpr size_t SIZE = 128;
|
static constexpr size_t SIZE = 256;
|
||||||
private:
|
private:
|
||||||
using Flags = std::bitset<SIZE>;
|
using Flags = std::bitset<SIZE>;
|
||||||
Flags flags;
|
Flags flags;
|
||||||
|
@ -69,6 +69,7 @@ enum class AccessType
|
|||||||
M(ALTER_FREEZE_PARTITION, "FREEZE PARTITION, UNFREEZE", TABLE, ALTER_TABLE) \
|
M(ALTER_FREEZE_PARTITION, "FREEZE PARTITION, UNFREEZE", TABLE, ALTER_TABLE) \
|
||||||
\
|
\
|
||||||
M(ALTER_DATABASE_SETTINGS, "ALTER DATABASE SETTING, ALTER MODIFY DATABASE SETTING, MODIFY DATABASE SETTING", DATABASE, ALTER_DATABASE) /* allows to execute ALTER MODIFY SETTING */\
|
M(ALTER_DATABASE_SETTINGS, "ALTER DATABASE SETTING, ALTER MODIFY DATABASE SETTING, MODIFY DATABASE SETTING", DATABASE, ALTER_DATABASE) /* allows to execute ALTER MODIFY SETTING */\
|
||||||
|
M(ALTER_NAMED_COLLECTION, "", GROUP, ALTER) /* allows to execute ALTER NAMED COLLECTION */\
|
||||||
\
|
\
|
||||||
M(ALTER_TABLE, "", GROUP, ALTER) \
|
M(ALTER_TABLE, "", GROUP, ALTER) \
|
||||||
M(ALTER_DATABASE, "", GROUP, ALTER) \
|
M(ALTER_DATABASE, "", GROUP, ALTER) \
|
||||||
@ -88,6 +89,7 @@ enum class AccessType
|
|||||||
M(CREATE_TEMPORARY_TABLE, "", GLOBAL, CREATE) /* allows to create and manipulate temporary tables;
|
M(CREATE_TEMPORARY_TABLE, "", GLOBAL, CREATE) /* allows to create and manipulate temporary tables;
|
||||||
implicitly enabled by the grant CREATE_TABLE on any table */ \
|
implicitly enabled by the grant CREATE_TABLE on any table */ \
|
||||||
M(CREATE_FUNCTION, "", GLOBAL, CREATE) /* allows to execute CREATE FUNCTION */ \
|
M(CREATE_FUNCTION, "", GLOBAL, CREATE) /* allows to execute CREATE FUNCTION */ \
|
||||||
|
M(CREATE_NAMED_COLLECTION, "", GLOBAL, CREATE) /* allows to execute CREATE NAMED COLLECTION */ \
|
||||||
M(CREATE, "", GROUP, ALL) /* allows to execute {CREATE|ATTACH} */ \
|
M(CREATE, "", GROUP, ALL) /* allows to execute {CREATE|ATTACH} */ \
|
||||||
\
|
\
|
||||||
M(DROP_DATABASE, "", DATABASE, DROP) /* allows to execute {DROP|DETACH} DATABASE */\
|
M(DROP_DATABASE, "", DATABASE, DROP) /* allows to execute {DROP|DETACH} DATABASE */\
|
||||||
@ -96,6 +98,7 @@ enum class AccessType
|
|||||||
implicitly enabled by the grant DROP_TABLE */\
|
implicitly enabled by the grant DROP_TABLE */\
|
||||||
M(DROP_DICTIONARY, "", DICTIONARY, DROP) /* allows to execute {DROP|DETACH} DICTIONARY */\
|
M(DROP_DICTIONARY, "", DICTIONARY, DROP) /* allows to execute {DROP|DETACH} DICTIONARY */\
|
||||||
M(DROP_FUNCTION, "", GLOBAL, DROP) /* allows to execute DROP FUNCTION */\
|
M(DROP_FUNCTION, "", GLOBAL, DROP) /* allows to execute DROP FUNCTION */\
|
||||||
|
M(DROP_NAMED_COLLECTION, "", GLOBAL, DROP) /* allows to execute DROP NAMED COLLECTION */\
|
||||||
M(DROP, "", GROUP, ALL) /* allows to execute {DROP|DETACH} */\
|
M(DROP, "", GROUP, ALL) /* allows to execute {DROP|DETACH} */\
|
||||||
\
|
\
|
||||||
M(TRUNCATE, "TRUNCATE TABLE", TABLE, ALL) \
|
M(TRUNCATE, "TRUNCATE TABLE", TABLE, ALL) \
|
||||||
|
@ -637,8 +637,9 @@
|
|||||||
M(666, CANNOT_USE_CACHE) \
|
M(666, CANNOT_USE_CACHE) \
|
||||||
M(667, NOT_INITIALIZED) \
|
M(667, NOT_INITIALIZED) \
|
||||||
M(668, INVALID_STATE) \
|
M(668, INVALID_STATE) \
|
||||||
M(669, UNKNOWN_NAMED_COLLECTION) \
|
M(669, NAMED_COLLECTION_DOESNT_EXIST) \
|
||||||
M(670, NAMED_COLLECTION_ALREADY_EXISTS) \
|
M(670, NAMED_COLLECTION_ALREADY_EXISTS) \
|
||||||
|
M(671, NAMED_COLLECTION_IS_IMMUTABLE) \
|
||||||
\
|
\
|
||||||
M(999, KEEPER_EXCEPTION) \
|
M(999, KEEPER_EXCEPTION) \
|
||||||
M(1000, POCO_EXCEPTION) \
|
M(1000, POCO_EXCEPTION) \
|
||||||
|
28
src/Interpreters/InterpreterAlterNamedCollectionQuery.cpp
Normal file
28
src/Interpreters/InterpreterAlterNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <Interpreters/InterpreterAlterNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTAlterNamedCollectionQuery.h>
|
||||||
|
#include <Access/ContextAccess.h>
|
||||||
|
#include <Interpreters/Context.h>
|
||||||
|
#include <Interpreters/executeDDLQueryOnCluster.h>
|
||||||
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
BlockIO InterpreterAlterNamedCollectionQuery::execute()
|
||||||
|
{
|
||||||
|
auto current_context = getContext();
|
||||||
|
current_context->checkAccess(AccessType::ALTER_NAMED_COLLECTION);
|
||||||
|
|
||||||
|
const auto & query = query_ptr->as<const ASTAlterNamedCollectionQuery &>();
|
||||||
|
if (!query.cluster.empty())
|
||||||
|
{
|
||||||
|
DDLQueryOnClusterParams params;
|
||||||
|
return executeDDLQueryOnCluster(query_ptr, current_context, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedCollectionUtils::updateFromSQL(query, current_context);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
src/Interpreters/InterpreterAlterNamedCollectionQuery.h
Normal file
22
src/Interpreters/InterpreterAlterNamedCollectionQuery.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Interpreters/IInterpreter.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class Context;
|
||||||
|
|
||||||
|
class InterpreterAlterNamedCollectionQuery : public IInterpreter, WithMutableContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InterpreterAlterNamedCollectionQuery(const ASTPtr & query_ptr_, ContextMutablePtr context_)
|
||||||
|
: WithMutableContext(context_), query_ptr(query_ptr_) {}
|
||||||
|
|
||||||
|
BlockIO execute() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASTPtr query_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
30
src/Interpreters/InterpreterCreateNamedCollectionQuery.cpp
Normal file
30
src/Interpreters/InterpreterCreateNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include <Interpreters/InterpreterCreateNamedCollectionQuery.h>
|
||||||
|
|
||||||
|
#include <Parsers/ASTCreateNamedCollectionQuery.h>
|
||||||
|
#include <Access/ContextAccess.h>
|
||||||
|
#include <Interpreters/Context.h>
|
||||||
|
#include <Interpreters/executeDDLQueryOnCluster.h>
|
||||||
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
BlockIO InterpreterCreateNamedCollectionQuery::execute()
|
||||||
|
{
|
||||||
|
auto current_context = getContext();
|
||||||
|
current_context->checkAccess(AccessType::CREATE_NAMED_COLLECTION);
|
||||||
|
|
||||||
|
const auto & query = query_ptr->as<const ASTCreateNamedCollectionQuery &>();
|
||||||
|
|
||||||
|
if (!query.cluster.empty())
|
||||||
|
{
|
||||||
|
DDLQueryOnClusterParams params;
|
||||||
|
return executeDDLQueryOnCluster(query_ptr, current_context, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedCollectionUtils::createFromSQL(query, current_context);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
src/Interpreters/InterpreterCreateNamedCollectionQuery.h
Normal file
23
src/Interpreters/InterpreterCreateNamedCollectionQuery.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Interpreters/IInterpreter.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class InterpreterCreateNamedCollectionQuery : public IInterpreter, WithMutableContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InterpreterCreateNamedCollectionQuery(const ASTPtr & query_ptr_, ContextMutablePtr context_)
|
||||||
|
: WithMutableContext(context_), query_ptr(query_ptr_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockIO execute() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASTPtr query_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
32
src/Interpreters/InterpreterDropNamedCollectionQuery.cpp
Normal file
32
src/Interpreters/InterpreterDropNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include <Interpreters/InterpreterDropNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTDropNamedCollectionQuery.h>
|
||||||
|
#include <Access/ContextAccess.h>
|
||||||
|
#include <Interpreters/Context.h>
|
||||||
|
#include <Interpreters/executeDDLQueryOnCluster.h>
|
||||||
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
BlockIO InterpreterDropNamedCollectionQuery::execute()
|
||||||
|
{
|
||||||
|
auto current_context = getContext();
|
||||||
|
current_context->checkAccess(AccessType::DROP_NAMED_COLLECTION);
|
||||||
|
|
||||||
|
const auto & query = query_ptr->as<const ASTDropNamedCollectionQuery &>();
|
||||||
|
if (!query.cluster.empty())
|
||||||
|
{
|
||||||
|
DDLQueryOnClusterParams params;
|
||||||
|
return executeDDLQueryOnCluster(query_ptr, current_context, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query.if_exists)
|
||||||
|
NamedCollectionUtils::removeIfExistsFromSQL(query.collection_name, current_context);
|
||||||
|
else
|
||||||
|
NamedCollectionUtils::removeFromSQL(query.collection_name, current_context);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
src/Interpreters/InterpreterDropNamedCollectionQuery.h
Normal file
22
src/Interpreters/InterpreterDropNamedCollectionQuery.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Interpreters/IInterpreter.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class Context;
|
||||||
|
|
||||||
|
class InterpreterDropNamedCollectionQuery : public IInterpreter, WithMutableContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InterpreterDropNamedCollectionQuery(const ASTPtr & query_ptr_, ContextMutablePtr context_)
|
||||||
|
: WithMutableContext(context_), query_ptr(query_ptr_) {}
|
||||||
|
|
||||||
|
BlockIO execute() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ASTPtr query_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -21,6 +21,9 @@
|
|||||||
#include <Parsers/ASTShowTablesQuery.h>
|
#include <Parsers/ASTShowTablesQuery.h>
|
||||||
#include <Parsers/ASTUseQuery.h>
|
#include <Parsers/ASTUseQuery.h>
|
||||||
#include <Parsers/ASTWatchQuery.h>
|
#include <Parsers/ASTWatchQuery.h>
|
||||||
|
#include <Parsers/ASTCreateNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTDropNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTAlterNamedCollectionQuery.h>
|
||||||
#include <Parsers/MySQL/ASTCreateQuery.h>
|
#include <Parsers/MySQL/ASTCreateQuery.h>
|
||||||
#include <Parsers/ASTTransactionControl.h>
|
#include <Parsers/ASTTransactionControl.h>
|
||||||
#include <Parsers/TablePropertiesQueriesASTs.h>
|
#include <Parsers/TablePropertiesQueriesASTs.h>
|
||||||
@ -47,6 +50,9 @@
|
|||||||
#include <Interpreters/InterpreterCreateFunctionQuery.h>
|
#include <Interpreters/InterpreterCreateFunctionQuery.h>
|
||||||
#include <Interpreters/InterpreterCreateIndexQuery.h>
|
#include <Interpreters/InterpreterCreateIndexQuery.h>
|
||||||
#include <Interpreters/InterpreterCreateQuery.h>
|
#include <Interpreters/InterpreterCreateQuery.h>
|
||||||
|
#include <Interpreters/InterpreterCreateNamedCollectionQuery.h>
|
||||||
|
#include <Interpreters/InterpreterDropNamedCollectionQuery.h>
|
||||||
|
#include <Interpreters/InterpreterAlterNamedCollectionQuery.h>
|
||||||
#include <Interpreters/InterpreterDeleteQuery.h>
|
#include <Interpreters/InterpreterDeleteQuery.h>
|
||||||
#include <Interpreters/InterpreterDescribeQuery.h>
|
#include <Interpreters/InterpreterDescribeQuery.h>
|
||||||
#include <Interpreters/InterpreterDescribeCacheQuery.h>
|
#include <Interpreters/InterpreterDescribeCacheQuery.h>
|
||||||
@ -230,6 +236,10 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, ContextMut
|
|||||||
{
|
{
|
||||||
return std::make_unique<InterpreterAlterQuery>(query, context);
|
return std::make_unique<InterpreterAlterQuery>(query, context);
|
||||||
}
|
}
|
||||||
|
else if (query->as<ASTAlterNamedCollectionQuery>())
|
||||||
|
{
|
||||||
|
return std::make_unique<InterpreterAlterNamedCollectionQuery>(query, context);
|
||||||
|
}
|
||||||
else if (query->as<ASTCheckQuery>())
|
else if (query->as<ASTCheckQuery>())
|
||||||
{
|
{
|
||||||
return std::make_unique<InterpreterCheckQuery>(query, context);
|
return std::make_unique<InterpreterCheckQuery>(query, context);
|
||||||
@ -270,6 +280,10 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, ContextMut
|
|||||||
{
|
{
|
||||||
return std::make_unique<InterpreterDropAccessEntityQuery>(query, context);
|
return std::make_unique<InterpreterDropAccessEntityQuery>(query, context);
|
||||||
}
|
}
|
||||||
|
else if (query->as<ASTDropNamedCollectionQuery>())
|
||||||
|
{
|
||||||
|
return std::make_unique<InterpreterDropNamedCollectionQuery>(query, context);
|
||||||
|
}
|
||||||
else if (query->as<ASTGrantQuery>())
|
else if (query->as<ASTGrantQuery>())
|
||||||
{
|
{
|
||||||
return std::make_unique<InterpreterGrantQuery>(query, context);
|
return std::make_unique<InterpreterGrantQuery>(query, context);
|
||||||
@ -314,6 +328,10 @@ std::unique_ptr<IInterpreter> InterpreterFactory::get(ASTPtr & query, ContextMut
|
|||||||
{
|
{
|
||||||
return std::make_unique<InterpreterCreateIndexQuery>(query, context);
|
return std::make_unique<InterpreterCreateIndexQuery>(query, context);
|
||||||
}
|
}
|
||||||
|
else if (query->as<ASTCreateNamedCollectionQuery>())
|
||||||
|
{
|
||||||
|
return std::make_unique<InterpreterCreateNamedCollectionQuery>(query, context);
|
||||||
|
}
|
||||||
else if (query->as<ASTDropIndexQuery>())
|
else if (query->as<ASTDropIndexQuery>())
|
||||||
{
|
{
|
||||||
return std::make_unique<InterpreterDropIndexQuery>(query, context);
|
return std::make_unique<InterpreterDropIndexQuery>(query, context);
|
||||||
|
54
src/Parsers/ASTAlterNamedCollectionQuery.cpp
Normal file
54
src/Parsers/ASTAlterNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include <Common/quoteString.h>
|
||||||
|
#include <Common/FieldVisitorToString.h>
|
||||||
|
#include <IO/Operators.h>
|
||||||
|
#include <Parsers/ASTAlterNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/formatSettingName.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTAlterNamedCollectionQuery::clone() const
|
||||||
|
{
|
||||||
|
return std::make_shared<ASTAlterNamedCollectionQuery>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTAlterNamedCollectionQuery::formatImpl(const IAST::FormatSettings & settings, IAST::FormatState &, IAST::FormatStateStacked) const
|
||||||
|
{
|
||||||
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << "Alter NAMED COLLECTION ";
|
||||||
|
settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(collection_name) << (settings.hilite ? hilite_none : "");
|
||||||
|
formatOnCluster(settings);
|
||||||
|
if (!changes.empty())
|
||||||
|
{
|
||||||
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << " SET " << (settings.hilite ? hilite_none : "");
|
||||||
|
bool first = true;
|
||||||
|
for (const auto & change : changes)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
settings.ostr << ", ";
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
formatSettingName(change.name, settings.ostr);
|
||||||
|
if (settings.show_secrets)
|
||||||
|
settings.ostr << " = " << applyVisitor(FieldVisitorToString(), change.value);
|
||||||
|
else
|
||||||
|
settings.ostr << " = '[HIDDEN]'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!delete_keys.empty())
|
||||||
|
{
|
||||||
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << " DELETE " << (settings.hilite ? hilite_none : "");
|
||||||
|
bool first = true;
|
||||||
|
for (const auto & key : delete_keys)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
settings.ostr << ", ";
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
formatSettingName(key, settings.ostr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/Parsers/ASTAlterNamedCollectionQuery.h
Normal file
28
src/Parsers/ASTAlterNamedCollectionQuery.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/ASTQueryWithOnCluster.h>
|
||||||
|
#include <Common/SettingsChanges.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTAlterNamedCollectionQuery : public IAST, public ASTQueryWithOnCluster
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string collection_name;
|
||||||
|
SettingsChanges changes;
|
||||||
|
std::vector<std::string> delete_keys;
|
||||||
|
bool if_exists = false;
|
||||||
|
|
||||||
|
String getID(char) const override { return "AlterNamedCollectionQuery"; }
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
void formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const override;
|
||||||
|
|
||||||
|
ASTPtr getRewrittenASTWithoutOnCluster(const WithoutOnClusterASTRewriteParams &) const override { return removeOnCluster<ASTAlterNamedCollectionQuery>(clone()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
43
src/Parsers/ASTCreateNamedCollectionQuery.cpp
Normal file
43
src/Parsers/ASTCreateNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <Common/quoteString.h>
|
||||||
|
#include <IO/Operators.h>
|
||||||
|
#include <Parsers/ASTCreateNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/formatSettingName.h>
|
||||||
|
#include <Parsers/ASTExpressionList.h>
|
||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Common/FieldVisitorToString.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTCreateNamedCollectionQuery::clone() const
|
||||||
|
{
|
||||||
|
return std::make_shared<ASTCreateNamedCollectionQuery>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTCreateNamedCollectionQuery::formatImpl(const IAST::FormatSettings & settings, IAST::FormatState &, IAST::FormatStateStacked) const
|
||||||
|
{
|
||||||
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << "CREATE NAMED COLLECTION ";
|
||||||
|
settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(collection_name) << (settings.hilite ? hilite_none : "");
|
||||||
|
|
||||||
|
formatOnCluster(settings);
|
||||||
|
|
||||||
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << " AS " << (settings.hilite ? hilite_none : "");
|
||||||
|
bool first = true;
|
||||||
|
for (const auto & change : changes)
|
||||||
|
{
|
||||||
|
if (!first)
|
||||||
|
settings.ostr << ", ";
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
formatSettingName(change.name, settings.ostr);
|
||||||
|
|
||||||
|
if (settings.show_secrets)
|
||||||
|
settings.ostr << " = " << applyVisitor(FieldVisitorToString(), change.value);
|
||||||
|
else
|
||||||
|
settings.ostr << " = '[HIDDEN]'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/Parsers/ASTCreateNamedCollectionQuery.h
Normal file
28
src/Parsers/ASTCreateNamedCollectionQuery.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/ASTQueryWithOnCluster.h>
|
||||||
|
#include <Common/SettingsChanges.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTCreateNamedCollectionQuery : public IAST, public ASTQueryWithOnCluster
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string collection_name;
|
||||||
|
SettingsChanges changes;
|
||||||
|
|
||||||
|
String getID(char) const override { return "CreateNamedCollectionQuery"; }
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
void formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const override;
|
||||||
|
|
||||||
|
ASTPtr getRewrittenASTWithoutOnCluster(const WithoutOnClusterASTRewriteParams &) const override { return removeOnCluster<ASTCreateNamedCollectionQuery>(clone()); }
|
||||||
|
|
||||||
|
std::string getCollectionName() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
20
src/Parsers/ASTDropNamedCollectionQuery.cpp
Normal file
20
src/Parsers/ASTDropNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <Parsers/ASTDropNamedCollectionQuery.h>
|
||||||
|
#include <Common/quoteString.h>
|
||||||
|
#include <IO/Operators.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
ASTPtr ASTDropNamedCollectionQuery::clone() const
|
||||||
|
{
|
||||||
|
return std::make_shared<ASTDropNamedCollectionQuery>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTDropNamedCollectionQuery::formatImpl(const IAST::FormatSettings & settings, IAST::FormatState &, IAST::FormatStateStacked) const
|
||||||
|
{
|
||||||
|
settings.ostr << (settings.hilite ? hilite_keyword : "") << "DROP NAMED COLLECTION ";
|
||||||
|
settings.ostr << (settings.hilite ? hilite_identifier : "") << backQuoteIfNeed(collection_name) << (settings.hilite ? hilite_none : "");
|
||||||
|
formatOnCluster(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
src/Parsers/ASTDropNamedCollectionQuery.h
Normal file
25
src/Parsers/ASTDropNamedCollectionQuery.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Parsers/ASTQueryWithOnCluster.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTDropNamedCollectionQuery : public IAST, public ASTQueryWithOnCluster
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string collection_name;
|
||||||
|
bool if_exists = false;
|
||||||
|
|
||||||
|
String getID(char) const override { return "DropNamedCollectionQuery"; }
|
||||||
|
|
||||||
|
ASTPtr clone() const override;
|
||||||
|
|
||||||
|
void formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const override;
|
||||||
|
|
||||||
|
ASTPtr getRewrittenASTWithoutOnCluster(const WithoutOnClusterASTRewriteParams &) const override { return removeOnCluster<ASTDropNamedCollectionQuery>(clone()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
85
src/Parsers/ParserAlterNamedCollectionQuery.cpp
Normal file
85
src/Parsers/ParserAlterNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/ParserAlterNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ParserSetQuery.h>
|
||||||
|
#include <Parsers/ASTAlterNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTSetQuery.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
bool ParserAlterNamedCollectionQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ParserKeyword s_alter("ALTER");
|
||||||
|
ParserKeyword s_collection("NAMED COLLECTION");
|
||||||
|
ParserKeyword s_delete("DELETE");
|
||||||
|
|
||||||
|
ParserIdentifier name_p;
|
||||||
|
ParserSetQuery set_p;
|
||||||
|
ParserToken s_comma(TokenType::Comma);
|
||||||
|
|
||||||
|
String cluster_str;
|
||||||
|
bool if_exists = false;
|
||||||
|
|
||||||
|
ASTPtr collection_name;
|
||||||
|
ASTPtr set;
|
||||||
|
std::vector<std::string> delete_keys;
|
||||||
|
|
||||||
|
if (!s_alter.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!s_collection.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!name_p.parse(pos, collection_name, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword{"ON"}.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parsed_delete = false;
|
||||||
|
if (!set_p.parse(pos, set, expected))
|
||||||
|
{
|
||||||
|
if (!s_delete.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
parsed_delete = true;
|
||||||
|
}
|
||||||
|
else if (s_delete.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
parsed_delete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsed_delete)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!delete_keys.empty() && !s_comma.ignore(pos))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ASTPtr key;
|
||||||
|
if (!name_p.parse(pos, key, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
delete_keys.push_back(getIdentifierName(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query = std::make_shared<ASTAlterNamedCollectionQuery>();
|
||||||
|
|
||||||
|
query->collection_name = getIdentifierName(collection_name);
|
||||||
|
query->if_exists = if_exists;
|
||||||
|
query->cluster = std::move(cluster_str);
|
||||||
|
if (set)
|
||||||
|
query->changes = set->as<ASTSetQuery>()->changes;
|
||||||
|
query->delete_keys = delete_keys;
|
||||||
|
|
||||||
|
node = query;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
src/Parsers/ParserAlterNamedCollectionQuery.h
Normal file
14
src/Parsers/ParserAlterNamedCollectionQuery.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IParserBase.h"
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ParserAlterNamedCollectionQuery : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "Alter NAMED COLLECTION query"; }
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#include <Parsers/ASTProjectionDeclaration.h>
|
#include <Parsers/ASTProjectionDeclaration.h>
|
||||||
#include <Parsers/ASTSelectWithUnionQuery.h>
|
#include <Parsers/ASTSelectWithUnionQuery.h>
|
||||||
#include <Parsers/ASTSetQuery.h>
|
#include <Parsers/ASTSetQuery.h>
|
||||||
|
#include <Parsers/ASTCreateNamedCollectionQuery.h>
|
||||||
#include <Parsers/ASTTableOverrides.h>
|
#include <Parsers/ASTTableOverrides.h>
|
||||||
#include <Parsers/ExpressionListParsers.h>
|
#include <Parsers/ExpressionListParsers.h>
|
||||||
#include <Parsers/ParserCreateQuery.h>
|
#include <Parsers/ParserCreateQuery.h>
|
||||||
@ -1383,6 +1384,59 @@ bool ParserCreateViewQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ParserCreateNamedCollectionQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ParserKeyword s_create("CREATE");
|
||||||
|
ParserKeyword s_attach("ATTACH");
|
||||||
|
ParserKeyword s_named_collection("NAMED COLLECTION");
|
||||||
|
ParserKeyword s_as("AS");
|
||||||
|
|
||||||
|
ParserToken s_comma(TokenType::Comma);
|
||||||
|
ParserIdentifier name_p;
|
||||||
|
|
||||||
|
ASTPtr collection_name;
|
||||||
|
String cluster_str;
|
||||||
|
|
||||||
|
if (!s_create.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!s_named_collection.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!name_p.parse(pos, collection_name, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword{"ON"}.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_as.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SettingsChanges changes;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (!changes.empty() && !s_comma.ignore(pos))
|
||||||
|
break;
|
||||||
|
|
||||||
|
changes.push_back(SettingChange{});
|
||||||
|
|
||||||
|
if (!ParserSetQuery::parseNameValuePair(changes.back(), pos, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query = std::make_shared<ASTCreateNamedCollectionQuery>();
|
||||||
|
|
||||||
|
tryGetIdentifierNameInto(collection_name, query->collection_name);
|
||||||
|
query->changes = changes;
|
||||||
|
|
||||||
|
node = query;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ParserCreateDictionaryQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
bool ParserCreateDictionaryQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
{
|
{
|
||||||
ParserKeyword s_create("CREATE");
|
ParserKeyword s_create("CREATE");
|
||||||
|
@ -522,6 +522,13 @@ protected:
|
|||||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ParserCreateNamedCollectionQuery : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "CREATE NAMED COLLECTION"; }
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Query like this:
|
/** Query like this:
|
||||||
* CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name
|
* CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name
|
||||||
|
50
src/Parsers/ParserDropNamedCollectionQuery.cpp
Normal file
50
src/Parsers/ParserDropNamedCollectionQuery.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include <Parsers/ASTIdentifier.h>
|
||||||
|
#include <Parsers/CommonParsers.h>
|
||||||
|
#include <Parsers/ExpressionElementParsers.h>
|
||||||
|
#include <Parsers/ParserDropNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTDropNamedCollectionQuery.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
bool ParserDropNamedCollectionQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
|
{
|
||||||
|
ParserKeyword s_drop("DROP");
|
||||||
|
ParserKeyword s_collection("NAMED COLLECTION");
|
||||||
|
ParserKeyword s_if_exists("IF EXISTS");
|
||||||
|
ParserIdentifier name_p;
|
||||||
|
|
||||||
|
String cluster_str;
|
||||||
|
bool if_exists = false;
|
||||||
|
|
||||||
|
ASTPtr collection_name;
|
||||||
|
|
||||||
|
if (!s_drop.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!s_collection.ignore(pos, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (s_if_exists.ignore(pos, expected))
|
||||||
|
if_exists = true;
|
||||||
|
|
||||||
|
if (!name_p.parse(pos, collection_name, expected))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ParserKeyword{"ON"}.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto query = std::make_shared<ASTDropNamedCollectionQuery>();
|
||||||
|
|
||||||
|
tryGetIdentifierNameInto(collection_name, query->collection_name);
|
||||||
|
query->if_exists = if_exists;
|
||||||
|
query->cluster = std::move(cluster_str);
|
||||||
|
|
||||||
|
node = query;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
14
src/Parsers/ParserDropNamedCollectionQuery.h
Normal file
14
src/Parsers/ParserDropNamedCollectionQuery.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IParserBase.h"
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ParserDropNamedCollectionQuery : public IParserBase
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const char * getName() const override { return "DROP NAMED COLLECTION query"; }
|
||||||
|
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override;
|
||||||
|
};
|
||||||
|
}
|
@ -5,6 +5,8 @@
|
|||||||
#include <Parsers/ParserCreateIndexQuery.h>
|
#include <Parsers/ParserCreateIndexQuery.h>
|
||||||
#include <Parsers/ParserDropFunctionQuery.h>
|
#include <Parsers/ParserDropFunctionQuery.h>
|
||||||
#include <Parsers/ParserDropIndexQuery.h>
|
#include <Parsers/ParserDropIndexQuery.h>
|
||||||
|
#include <Parsers/ParserDropNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ParserAlterNamedCollectionQuery.h>
|
||||||
#include <Parsers/ParserDropQuery.h>
|
#include <Parsers/ParserDropQuery.h>
|
||||||
#include <Parsers/ParserInsertQuery.h>
|
#include <Parsers/ParserInsertQuery.h>
|
||||||
#include <Parsers/ParserOptimizeQuery.h>
|
#include <Parsers/ParserOptimizeQuery.h>
|
||||||
@ -46,6 +48,9 @@ bool ParserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
|||||||
ParserCreateSettingsProfileQuery create_settings_profile_p;
|
ParserCreateSettingsProfileQuery create_settings_profile_p;
|
||||||
ParserCreateFunctionQuery create_function_p;
|
ParserCreateFunctionQuery create_function_p;
|
||||||
ParserDropFunctionQuery drop_function_p;
|
ParserDropFunctionQuery drop_function_p;
|
||||||
|
ParserCreateNamedCollectionQuery create_named_collection_p;
|
||||||
|
ParserDropNamedCollectionQuery drop_named_collection_p;
|
||||||
|
ParserAlterNamedCollectionQuery alter_named_collection_p;
|
||||||
ParserCreateIndexQuery create_index_p;
|
ParserCreateIndexQuery create_index_p;
|
||||||
ParserDropIndexQuery drop_index_p;
|
ParserDropIndexQuery drop_index_p;
|
||||||
ParserDropAccessEntityQuery drop_access_entity_p;
|
ParserDropAccessEntityQuery drop_access_entity_p;
|
||||||
@ -69,6 +74,9 @@ bool ParserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
|||||||
|| create_settings_profile_p.parse(pos, node, expected)
|
|| create_settings_profile_p.parse(pos, node, expected)
|
||||||
|| create_function_p.parse(pos, node, expected)
|
|| create_function_p.parse(pos, node, expected)
|
||||||
|| drop_function_p.parse(pos, node, expected)
|
|| drop_function_p.parse(pos, node, expected)
|
||||||
|
|| create_named_collection_p.parse(pos, node, expected)
|
||||||
|
|| drop_named_collection_p.parse(pos, node, expected)
|
||||||
|
|| alter_named_collection_p.parse(pos, node, expected)
|
||||||
|| create_index_p.parse(pos, node, expected)
|
|| create_index_p.parse(pos, node, expected)
|
||||||
|| drop_index_p.parse(pos, node, expected)
|
|| drop_index_p.parse(pos, node, expected)
|
||||||
|| drop_access_entity_p.parse(pos, node, expected)
|
|| drop_access_entity_p.parse(pos, node, expected)
|
||||||
|
174
src/Storages/NamedCollectionConfiguration.cpp
Normal file
174
src/Storages/NamedCollectionConfiguration.cpp
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
#include <Storages/NamedCollectionConfiguration.h>
|
||||||
|
#include <Poco/Util/XMLConfiguration.h>
|
||||||
|
#include <Common/Exception.h>
|
||||||
|
#include <Common/SettingsChanges.h>
|
||||||
|
#include <Common/FieldVisitorToString.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int BAD_ARGUMENTS;
|
||||||
|
extern const int NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace NamedCollectionConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T> T getConfigValue(
|
||||||
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path)
|
||||||
|
{
|
||||||
|
return getConfigValueOrDefault<T>(config, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> T getConfigValueOrDefault(
|
||||||
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path,
|
||||||
|
const T * default_value)
|
||||||
|
{
|
||||||
|
if (!config.has(path))
|
||||||
|
{
|
||||||
|
if (!default_value)
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "No such key `{}`", path);
|
||||||
|
return *default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, String>)
|
||||||
|
return config.getString(path);
|
||||||
|
else if constexpr (std::is_same_v<T, UInt64>)
|
||||||
|
return config.getUInt64(path);
|
||||||
|
else if constexpr (std::is_same_v<T, Int64>)
|
||||||
|
return config.getInt64(path);
|
||||||
|
else if constexpr (std::is_same_v<T, Float64>)
|
||||||
|
return config.getDouble(path);
|
||||||
|
else
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NOT_IMPLEMENTED,
|
||||||
|
"Unsupported type in getConfigValueOrDefault(). "
|
||||||
|
"Supported types are String, UInt64, Int64, Float64");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> void setConfigValue(
|
||||||
|
Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path,
|
||||||
|
const T & value,
|
||||||
|
bool update)
|
||||||
|
{
|
||||||
|
if (!update && config.has(path))
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Key `{}` already exists", path);
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, String>)
|
||||||
|
config.setString(path, value);
|
||||||
|
else if constexpr (std::is_same_v<T, UInt64>)
|
||||||
|
config.setUInt64(path, value);
|
||||||
|
else if constexpr (std::is_same_v<T, Int64>)
|
||||||
|
config.setInt64(path, value);
|
||||||
|
else if constexpr (std::is_same_v<T, Float64>)
|
||||||
|
config.setDouble(path, value);
|
||||||
|
else
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NOT_IMPLEMENTED,
|
||||||
|
"Unsupported type in setConfigValue(). "
|
||||||
|
"Supported types are String, UInt64, Int64, Float64");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void copyConfigValue(
|
||||||
|
const Poco::Util::AbstractConfiguration & from_config,
|
||||||
|
const std::string & from_path,
|
||||||
|
Poco::Util::AbstractConfiguration & to_config,
|
||||||
|
const std::string & to_path)
|
||||||
|
{
|
||||||
|
if (!from_config.has(from_path))
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "No such key `{}`", from_path);
|
||||||
|
|
||||||
|
if (to_config.has(to_path))
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Key `{}` already exists", to_path);
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, String>)
|
||||||
|
to_config.setString(to_path, from_config.getString(from_path));
|
||||||
|
else if constexpr (std::is_same_v<T, UInt64>)
|
||||||
|
to_config.setUInt64(to_path, from_config.getUInt64(from_path));
|
||||||
|
else if constexpr (std::is_same_v<T, Int64>)
|
||||||
|
to_config.setInt64(to_path, from_config.getInt64(from_path));
|
||||||
|
else if constexpr (std::is_same_v<T, Float64>)
|
||||||
|
to_config.setDouble(to_path, from_config.getDouble(from_path));
|
||||||
|
else
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NOT_IMPLEMENTED,
|
||||||
|
"Unsupported type in copyConfigValue(). "
|
||||||
|
"Supported types are String, UInt64, Int64, Float64");
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeConfigValue(
|
||||||
|
Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path)
|
||||||
|
{
|
||||||
|
if (!config.has(path))
|
||||||
|
throw Exception(ErrorCodes::BAD_ARGUMENTS, "No such key `{}`", path);
|
||||||
|
config.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationPtr createEmptyConfiguration(const std::string & root_name)
|
||||||
|
{
|
||||||
|
using DocumentPtr = Poco::AutoPtr<Poco::XML::Document>;
|
||||||
|
using ElementPtr = Poco::AutoPtr<Poco::XML::Element>;
|
||||||
|
|
||||||
|
DocumentPtr xml_document(new Poco::XML::Document());
|
||||||
|
ElementPtr root_element(xml_document->createElement(root_name));
|
||||||
|
xml_document->appendChild(root_element);
|
||||||
|
|
||||||
|
ConfigurationPtr config(new Poco::Util::XMLConfiguration(xml_document));
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigurationPtr createConfiguration(const std::string & root_name, const SettingsChanges & settings)
|
||||||
|
{
|
||||||
|
namespace Configuration = NamedCollectionConfiguration;
|
||||||
|
|
||||||
|
auto config = Configuration::createEmptyConfiguration(root_name);
|
||||||
|
for (const auto & [name, value] : settings)
|
||||||
|
Configuration::setConfigValue<String>(*config, name, convertFieldToString(value));
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
template String getConfigValue<String>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path);
|
||||||
|
template UInt64 getConfigValue<UInt64>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path);
|
||||||
|
template Int64 getConfigValue<Int64>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path);
|
||||||
|
template Float64 getConfigValue<Float64>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path);
|
||||||
|
|
||||||
|
template String getConfigValueOrDefault<String>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const String * default_value);
|
||||||
|
template UInt64 getConfigValueOrDefault<UInt64>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const UInt64 * default_value);
|
||||||
|
template Int64 getConfigValueOrDefault<Int64>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const Int64 * default_value);
|
||||||
|
template Float64 getConfigValueOrDefault<Float64>(const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const Float64 * default_value);
|
||||||
|
|
||||||
|
template void setConfigValue<String>(Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const String & value, bool update);
|
||||||
|
template void setConfigValue<UInt64>(Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const UInt64 & value, bool update);
|
||||||
|
template void setConfigValue<Int64>(Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const Int64 & value, bool update);
|
||||||
|
template void setConfigValue<Float64>(Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path, const Float64 & value, bool update);
|
||||||
|
|
||||||
|
template void copyConfigValue<String>(const Poco::Util::AbstractConfiguration & from_config, const std::string & from_path,
|
||||||
|
Poco::Util::AbstractConfiguration & to_config, const std::string & to_path);
|
||||||
|
template void copyConfigValue<UInt64>(const Poco::Util::AbstractConfiguration & from_config, const std::string & from_path,
|
||||||
|
Poco::Util::AbstractConfiguration & to_config, const std::string & to_path);
|
||||||
|
template void copyConfigValue<Int64>(const Poco::Util::AbstractConfiguration & from_config, const std::string & from_path,
|
||||||
|
Poco::Util::AbstractConfiguration & to_config, const std::string & to_path);
|
||||||
|
template void copyConfigValue<Float64>(const Poco::Util::AbstractConfiguration & from_config, const std::string & from_path,
|
||||||
|
Poco::Util::AbstractConfiguration & to_config, const std::string & to_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
src/Storages/NamedCollectionConfiguration.h
Normal file
44
src/Storages/NamedCollectionConfiguration.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Poco/Util/AbstractConfiguration.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
using ConfigurationPtr = Poco::AutoPtr<Poco::Util::AbstractConfiguration>;
|
||||||
|
class SettingsChanges;
|
||||||
|
|
||||||
|
namespace NamedCollectionConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
ConfigurationPtr createEmptyConfiguration(const std::string & root_name);
|
||||||
|
|
||||||
|
template <typename T> T getConfigValue(
|
||||||
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path);
|
||||||
|
|
||||||
|
template <typename T> T getConfigValueOrDefault(
|
||||||
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path,
|
||||||
|
const T * default_value = nullptr);
|
||||||
|
|
||||||
|
template<typename T> void setConfigValue(
|
||||||
|
Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path,
|
||||||
|
const T & value,
|
||||||
|
bool update = false);
|
||||||
|
|
||||||
|
template <typename T> void copyConfigValue(
|
||||||
|
const Poco::Util::AbstractConfiguration & from_config,
|
||||||
|
const std::string & from_path,
|
||||||
|
Poco::Util::AbstractConfiguration & to_config,
|
||||||
|
const std::string & to_path);
|
||||||
|
|
||||||
|
void removeConfigValue(
|
||||||
|
Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & path);
|
||||||
|
|
||||||
|
ConfigurationPtr createConfiguration(const std::string & root_name, const SettingsChanges & settings);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
434
src/Storages/NamedCollectionUtils.cpp
Normal file
434
src/Storages/NamedCollectionUtils.cpp
Normal file
@ -0,0 +1,434 @@
|
|||||||
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
|
#include <Common/escapeForFileName.h>
|
||||||
|
#include <Common/FieldVisitorToString.h>
|
||||||
|
#include <Common/logger_useful.h>
|
||||||
|
#include <IO/WriteBufferFromFile.h>
|
||||||
|
#include <IO/ReadBufferFromFile.h>
|
||||||
|
#include <IO/WriteHelpers.h>
|
||||||
|
#include <Parsers/formatAST.h>
|
||||||
|
#include <Parsers/ASTCreateNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTAlterNamedCollectionQuery.h>
|
||||||
|
#include <Parsers/ASTSetQuery.h>
|
||||||
|
#include <Parsers/ASTCreateQuery.h>
|
||||||
|
#include <Parsers/parseQuery.h>
|
||||||
|
#include <Parsers/ParserCreateQuery.h>
|
||||||
|
#include <Interpreters/Context.h>
|
||||||
|
#include <Storages/NamedCollections.h>
|
||||||
|
#include <Storages/NamedCollectionConfiguration.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace ErrorCodes
|
||||||
|
{
|
||||||
|
extern const int NAMED_COLLECTION_ALREADY_EXISTS;
|
||||||
|
extern const int NAMED_COLLECTION_DOESNT_EXIST;
|
||||||
|
extern const int BAD_ARGUMENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace NamedCollectionUtils
|
||||||
|
{
|
||||||
|
|
||||||
|
class LoadFromConfig
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const Poco::Util::AbstractConfiguration & config;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LoadFromConfig(const Poco::Util::AbstractConfiguration & config_)
|
||||||
|
: config(config_) {}
|
||||||
|
|
||||||
|
std::vector<std::string> listCollections() const
|
||||||
|
{
|
||||||
|
Poco::Util::AbstractConfiguration::Keys collections_names;
|
||||||
|
config.keys(NAMED_COLLECTIONS_CONFIG_PREFIX, collections_names);
|
||||||
|
return collections_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedCollectionsMap getAll() const
|
||||||
|
{
|
||||||
|
NamedCollectionsMap result;
|
||||||
|
for (const auto & collection_name : listCollections())
|
||||||
|
{
|
||||||
|
if (result.contains(collection_name))
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NAMED_COLLECTION_ALREADY_EXISTS,
|
||||||
|
"Found duplicate named collection `{}`",
|
||||||
|
collection_name);
|
||||||
|
}
|
||||||
|
result.emplace(collection_name, get(collection_name));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableNamedCollectionPtr get(const std::string & collection_name) const
|
||||||
|
{
|
||||||
|
const auto collection_prefix = getCollectionPrefix(collection_name);
|
||||||
|
std::queue<std::string> enumerate_input;
|
||||||
|
std::set<std::string> enumerate_result;
|
||||||
|
|
||||||
|
enumerate_input.push(collection_prefix);
|
||||||
|
collectKeys(config, std::move(enumerate_input), enumerate_result);
|
||||||
|
|
||||||
|
/// Collection does not have any keys.
|
||||||
|
/// (`enumerate_result` == <collection_path>).
|
||||||
|
const bool collection_is_empty = enumerate_result.size() == 1
|
||||||
|
&& *enumerate_result.begin() == collection_prefix;
|
||||||
|
std::set<std::string> keys;
|
||||||
|
if (!collection_is_empty)
|
||||||
|
{
|
||||||
|
/// Skip collection prefix and add +1 to avoid '.' in the beginning.
|
||||||
|
for (const auto & path : enumerate_result)
|
||||||
|
keys.emplace(path.substr(collection_prefix.size() + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NamedCollection::create(
|
||||||
|
config, collection_name, collection_prefix, keys, SourceId::CONFIG, /* is_mutable */false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr auto NAMED_COLLECTIONS_CONFIG_PREFIX = "named_collections";
|
||||||
|
|
||||||
|
static std::string getCollectionPrefix(const std::string & collection_name)
|
||||||
|
{
|
||||||
|
return fmt::format("{}.{}", NAMED_COLLECTIONS_CONFIG_PREFIX, collection_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enumerate keys paths of the config recursively.
|
||||||
|
/// E.g. if `enumerate_paths` = {"root.key1"} and config like
|
||||||
|
/// <root>
|
||||||
|
/// <key0></key0>
|
||||||
|
/// <key1>
|
||||||
|
/// <key2></key2>
|
||||||
|
/// <key3>
|
||||||
|
/// <key4></key4>
|
||||||
|
/// </key3>
|
||||||
|
/// </key1>
|
||||||
|
/// </root>
|
||||||
|
/// the `result` will contain two strings: "root.key1.key2" and "root.key1.key3.key4"
|
||||||
|
static void collectKeys(
|
||||||
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
|
std::queue<std::string> enumerate_paths,
|
||||||
|
std::set<std::string> & result)
|
||||||
|
{
|
||||||
|
if (enumerate_paths.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto initial_paths = std::move(enumerate_paths);
|
||||||
|
enumerate_paths = {};
|
||||||
|
while (!initial_paths.empty())
|
||||||
|
{
|
||||||
|
auto path = initial_paths.front();
|
||||||
|
initial_paths.pop();
|
||||||
|
|
||||||
|
Poco::Util::AbstractConfiguration::Keys keys;
|
||||||
|
config.keys(path, keys);
|
||||||
|
|
||||||
|
if (keys.empty())
|
||||||
|
{
|
||||||
|
result.insert(path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const auto & key : keys)
|
||||||
|
enumerate_paths.emplace(path + '.' + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collectKeys(config, enumerate_paths, result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LoadFromSQL : private WithContext
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const std::string metadata_path;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit LoadFromSQL(ContextPtr context_)
|
||||||
|
: WithContext(context_)
|
||||||
|
, metadata_path(
|
||||||
|
fs::canonical(context_->getPath()) / NAMED_COLLECTIONS_METADATA_DIRECTORY)
|
||||||
|
{
|
||||||
|
if (fs::exists(metadata_path))
|
||||||
|
cleanUp();
|
||||||
|
else
|
||||||
|
fs::create_directories(metadata_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> listCollections() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> collection_names;
|
||||||
|
fs::directory_iterator it{metadata_path};
|
||||||
|
for (; it != fs::directory_iterator{}; ++it)
|
||||||
|
{
|
||||||
|
const auto & current_path = it->path();
|
||||||
|
if (current_path.extension() == ".sql")
|
||||||
|
{
|
||||||
|
collection_names.push_back(it->path().stem());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_WARNING(
|
||||||
|
&Poco::Logger::get("NamedCollectionsLoadFromSQL"),
|
||||||
|
"Unexpected file {} in named collections directory",
|
||||||
|
current_path.filename().string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collection_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedCollectionsMap getAll() const
|
||||||
|
{
|
||||||
|
NamedCollectionsMap result;
|
||||||
|
for (const auto & collection_name : listCollections())
|
||||||
|
{
|
||||||
|
if (result.contains(collection_name))
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NAMED_COLLECTION_ALREADY_EXISTS,
|
||||||
|
"Found duplicate named collection `{}`",
|
||||||
|
collection_name);
|
||||||
|
}
|
||||||
|
result.emplace(collection_name, get(collection_name));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableNamedCollectionPtr get(const std::string & collection_name) const
|
||||||
|
{
|
||||||
|
const auto query = readCreateQueryFromMetadata(
|
||||||
|
getMetadataPath(collection_name),
|
||||||
|
getContext()->getSettingsRef());
|
||||||
|
return createNamedCollectionFromAST(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableNamedCollectionPtr create(const ASTCreateNamedCollectionQuery & query)
|
||||||
|
{
|
||||||
|
writeCreateQueryToMetadata(
|
||||||
|
query,
|
||||||
|
getMetadataPath(query.collection_name),
|
||||||
|
getContext()->getSettingsRef());
|
||||||
|
|
||||||
|
return createNamedCollectionFromAST(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(const ASTAlterNamedCollectionQuery & query)
|
||||||
|
{
|
||||||
|
const auto path = getMetadataPath(query.collection_name);
|
||||||
|
auto create_query = readCreateQueryFromMetadata(path, getContext()->getSettings());
|
||||||
|
|
||||||
|
std::unordered_map<std::string, Field> result_changes_map;
|
||||||
|
for (const auto & [name, value] : query.changes)
|
||||||
|
{
|
||||||
|
auto [it, inserted] = result_changes_map.emplace(name, value);
|
||||||
|
if (!inserted)
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
|
"Value with key `{}` is used twice in the SET query",
|
||||||
|
name, query.collection_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto & [name, value] : create_query.changes)
|
||||||
|
result_changes_map.emplace(name, value);
|
||||||
|
|
||||||
|
for (const auto & delete_key : query.delete_keys)
|
||||||
|
{
|
||||||
|
auto it = result_changes_map.find(delete_key);
|
||||||
|
if (it == result_changes_map.end())
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::BAD_ARGUMENTS,
|
||||||
|
"Cannot delete key `{}` because it does not exist in collection",
|
||||||
|
delete_key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result_changes_map.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_query.changes.clear();
|
||||||
|
for (const auto & [name, value] : result_changes_map)
|
||||||
|
create_query.changes.emplace_back(name, value);
|
||||||
|
|
||||||
|
writeCreateQueryToMetadata(
|
||||||
|
create_query,
|
||||||
|
getMetadataPath(query.collection_name),
|
||||||
|
getContext()->getSettingsRef(),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(const std::string & collection_name)
|
||||||
|
{
|
||||||
|
if (!removeIfExists(collection_name))
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NAMED_COLLECTION_DOESNT_EXIST,
|
||||||
|
"Cannot remove collection `{}`, because it doesn't exist",
|
||||||
|
collection_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool removeIfExists(const std::string & collection_name)
|
||||||
|
{
|
||||||
|
auto collection_path = getMetadataPath(collection_name);
|
||||||
|
if (fs::exists(collection_path))
|
||||||
|
{
|
||||||
|
fs::remove(collection_path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr auto NAMED_COLLECTIONS_METADATA_DIRECTORY = "named_collections";
|
||||||
|
|
||||||
|
static MutableNamedCollectionPtr createNamedCollectionFromAST(
|
||||||
|
const ASTCreateNamedCollectionQuery & query)
|
||||||
|
{
|
||||||
|
const auto & collection_name = query.collection_name;
|
||||||
|
const auto config = NamedCollectionConfiguration::createConfiguration(
|
||||||
|
collection_name, query.changes);
|
||||||
|
|
||||||
|
std::set<std::string> keys;
|
||||||
|
for (const auto & [name, _] : query.changes)
|
||||||
|
keys.insert(name);
|
||||||
|
|
||||||
|
return NamedCollection::create(
|
||||||
|
*config, collection_name, "", keys, SourceId::SQL, /* is_mutable */true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getMetadataPath(const std::string & collection_name) const
|
||||||
|
{
|
||||||
|
return fs::path(metadata_path) / (escapeForFileName(collection_name) + ".sql");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete .tmp files. They could be left undeleted in case of
|
||||||
|
/// some exception or abrupt server restart.
|
||||||
|
void cleanUp()
|
||||||
|
{
|
||||||
|
fs::directory_iterator it{metadata_path};
|
||||||
|
std::vector<std::string> files_to_remove;
|
||||||
|
for (; it != fs::directory_iterator{}; ++it)
|
||||||
|
{
|
||||||
|
const auto & current_path = it->path();
|
||||||
|
if (current_path.extension() == ".tmp")
|
||||||
|
files_to_remove.push_back(current_path);
|
||||||
|
}
|
||||||
|
for (const auto & file : files_to_remove)
|
||||||
|
fs::remove(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ASTCreateNamedCollectionQuery readCreateQueryFromMetadata(
|
||||||
|
const std::string & path,
|
||||||
|
const Settings & settings)
|
||||||
|
{
|
||||||
|
ReadBufferFromFile in(path);
|
||||||
|
std::string query;
|
||||||
|
readStringUntilEOF(query, in);
|
||||||
|
|
||||||
|
ParserCreateNamedCollectionQuery parser;
|
||||||
|
auto ast = parseQuery(parser, query, "in file " + path, 0, settings.max_parser_depth);
|
||||||
|
const auto & create_query = ast->as<const ASTCreateNamedCollectionQuery &>();
|
||||||
|
return create_query;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void writeCreateQueryToMetadata(
|
||||||
|
const ASTCreateNamedCollectionQuery & query,
|
||||||
|
const std::string & path,
|
||||||
|
const Settings & settings,
|
||||||
|
bool replace = false)
|
||||||
|
{
|
||||||
|
if (!replace && fs::exists(path))
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NAMED_COLLECTION_ALREADY_EXISTS,
|
||||||
|
"Metadata file {} for named collection already exists",
|
||||||
|
path);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto tmp_path = path + ".tmp";
|
||||||
|
String formatted_query = serializeAST(query);
|
||||||
|
WriteBufferFromFile out(tmp_path, formatted_query.size(), O_WRONLY | O_CREAT | O_EXCL);
|
||||||
|
writeString(formatted_query, out);
|
||||||
|
|
||||||
|
out.next();
|
||||||
|
if (settings.fsync_metadata)
|
||||||
|
out.sync();
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
fs::rename(tmp_path, path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> lockNamedCollectionsTransaction()
|
||||||
|
{
|
||||||
|
static std::mutex transaction_lock;
|
||||||
|
return std::unique_lock(transaction_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadFromConfig(const Poco::Util::AbstractConfiguration & config)
|
||||||
|
{
|
||||||
|
auto lock = lockNamedCollectionsTransaction();
|
||||||
|
NamedCollectionFactory::instance().add(LoadFromConfig(config).getAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
void reloadFromConfig(const Poco::Util::AbstractConfiguration & config)
|
||||||
|
{
|
||||||
|
auto lock = lockNamedCollectionsTransaction();
|
||||||
|
auto collections = LoadFromConfig(config).getAll();
|
||||||
|
auto & instance = NamedCollectionFactory::instance();
|
||||||
|
instance.removeById(SourceId::CONFIG);
|
||||||
|
instance.add(collections);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadFromSQL(ContextPtr context)
|
||||||
|
{
|
||||||
|
auto lock = lockNamedCollectionsTransaction();
|
||||||
|
NamedCollectionFactory::instance().add(LoadFromSQL(context).getAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromSQL(const std::string & collection_name, ContextPtr context)
|
||||||
|
{
|
||||||
|
auto lock = lockNamedCollectionsTransaction();
|
||||||
|
LoadFromSQL(context).remove(collection_name);
|
||||||
|
NamedCollectionFactory::instance().remove(collection_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeIfExistsFromSQL(const std::string & collection_name, ContextPtr context)
|
||||||
|
{
|
||||||
|
auto lock = lockNamedCollectionsTransaction();
|
||||||
|
LoadFromSQL(context).removeIfExists(collection_name);
|
||||||
|
NamedCollectionFactory::instance().removeIfExists(collection_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createFromSQL(const ASTCreateNamedCollectionQuery & query, ContextPtr context)
|
||||||
|
{
|
||||||
|
auto lock = lockNamedCollectionsTransaction();
|
||||||
|
NamedCollectionFactory::instance().add(query.collection_name, LoadFromSQL(context).create(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateFromSQL(const ASTAlterNamedCollectionQuery & query, ContextPtr context)
|
||||||
|
{
|
||||||
|
auto lock = lockNamedCollectionsTransaction();
|
||||||
|
LoadFromSQL(context).update(query);
|
||||||
|
|
||||||
|
auto collection = NamedCollectionFactory::instance().getMutable(query.collection_name);
|
||||||
|
auto collection_lock = collection->lock();
|
||||||
|
|
||||||
|
for (const auto & [name, value] : query.changes)
|
||||||
|
collection->setOrUpdate<String, true>(name, convertFieldToString(value));
|
||||||
|
|
||||||
|
for (const auto & key : query.delete_keys)
|
||||||
|
collection->remove<true>(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
src/Storages/NamedCollectionUtils.h
Normal file
40
src/Storages/NamedCollectionUtils.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Interpreters/Context_fwd.h>
|
||||||
|
|
||||||
|
namespace Poco { namespace Util { class AbstractConfiguration; } }
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTCreateNamedCollectionQuery;
|
||||||
|
class ASTAlterNamedCollectionQuery;
|
||||||
|
|
||||||
|
namespace NamedCollectionUtils
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class SourceId
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
CONFIG = 1,
|
||||||
|
SQL = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
void loadFromConfig(const Poco::Util::AbstractConfiguration & config);
|
||||||
|
void reloadFromConfig(const Poco::Util::AbstractConfiguration & config);
|
||||||
|
|
||||||
|
/// Load named collections from `context->getPath() / named_collections /`.
|
||||||
|
void loadFromSQL(ContextPtr context);
|
||||||
|
|
||||||
|
/// Remove collection as well as its metadata from `context->getPath() / named_collections /`.
|
||||||
|
void removeFromSQL(const std::string & collection_name, ContextPtr context);
|
||||||
|
void removeIfExistsFromSQL(const std::string & collection_name, ContextPtr context);
|
||||||
|
|
||||||
|
/// Create a new collection from AST and put it to `context->getPath() / named_collections /`.
|
||||||
|
void createFromSQL(const ASTCreateNamedCollectionQuery & query, ContextPtr context);
|
||||||
|
|
||||||
|
/// Update definition of already existing collection from AST and update result in `context->getPath() / named_collections /`.
|
||||||
|
void updateFromSQL(const ASTAlterNamedCollectionQuery & query, ContextPtr context);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,17 +1,11 @@
|
|||||||
#include "NamedCollections.h"
|
#include "NamedCollections.h"
|
||||||
|
|
||||||
#include <base/find_symbols.h>
|
|
||||||
#include <Common/assert_cast.h>
|
|
||||||
#include <Common/FieldVisitorToString.h>
|
|
||||||
#include <Interpreters/Context.h>
|
#include <Interpreters/Context.h>
|
||||||
#include <Interpreters/evaluateConstantExpression.h>
|
|
||||||
#include <Parsers/ASTIdentifier.h>
|
|
||||||
#include <Parsers/ASTFunction.h>
|
|
||||||
#include <Parsers/ASTLiteral.h>
|
|
||||||
#include <Poco/Util/AbstractConfiguration.h>
|
|
||||||
#include <Poco/Util/XMLConfiguration.h>
|
|
||||||
#include <IO/WriteBufferFromString.h>
|
#include <IO/WriteBufferFromString.h>
|
||||||
#include <IO/Operators.h>
|
#include <IO/Operators.h>
|
||||||
|
#include <Storages/NamedCollectionConfiguration.h>
|
||||||
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
|
#include <Poco/Util/AbstractConfiguration.h>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
|
|
||||||
@ -20,66 +14,13 @@ namespace DB
|
|||||||
|
|
||||||
namespace ErrorCodes
|
namespace ErrorCodes
|
||||||
{
|
{
|
||||||
extern const int UNKNOWN_NAMED_COLLECTION;
|
extern const int NAMED_COLLECTION_DOESNT_EXIST;
|
||||||
extern const int NAMED_COLLECTION_ALREADY_EXISTS;
|
extern const int NAMED_COLLECTION_ALREADY_EXISTS;
|
||||||
extern const int BAD_ARGUMENTS;
|
extern const int NAMED_COLLECTION_IS_IMMUTABLE;
|
||||||
extern const int NOT_IMPLEMENTED;
|
|
||||||
extern const int LOGICAL_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace Configuration = NamedCollectionConfiguration;
|
||||||
{
|
|
||||||
constexpr auto NAMED_COLLECTIONS_CONFIG_PREFIX = "named_collections";
|
|
||||||
|
|
||||||
std::string getCollectionPrefix(const std::string & collection_name)
|
|
||||||
{
|
|
||||||
return fmt::format("{}.{}", NAMED_COLLECTIONS_CONFIG_PREFIX, collection_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Enumerate keys paths of the config recursively.
|
|
||||||
/// E.g. if `enumerate_paths` = {"root.key1"} and config like
|
|
||||||
/// <root>
|
|
||||||
/// <key0></key0>
|
|
||||||
/// <key1>
|
|
||||||
/// <key2></key2>
|
|
||||||
/// <key3>
|
|
||||||
/// <key4></key4>
|
|
||||||
/// </key3>
|
|
||||||
/// </key1>
|
|
||||||
/// </root>
|
|
||||||
/// the `result` will contain two strings: "root.key1.key2" and "root.key1.key3.key4"
|
|
||||||
void collectKeys(
|
|
||||||
const Poco::Util::AbstractConfiguration & config,
|
|
||||||
std::queue<std::string> enumerate_paths,
|
|
||||||
std::set<std::string> & result)
|
|
||||||
{
|
|
||||||
if (enumerate_paths.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto initial_paths = std::move(enumerate_paths);
|
|
||||||
enumerate_paths = {};
|
|
||||||
while (!initial_paths.empty())
|
|
||||||
{
|
|
||||||
auto path = initial_paths.front();
|
|
||||||
initial_paths.pop();
|
|
||||||
|
|
||||||
Poco::Util::AbstractConfiguration::Keys keys;
|
|
||||||
config.keys(path, keys);
|
|
||||||
|
|
||||||
if (keys.empty())
|
|
||||||
{
|
|
||||||
result.insert(path);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (const auto & key : keys)
|
|
||||||
enumerate_paths.emplace(path + '.' + key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
collectKeys(config, enumerate_paths, result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NamedCollectionFactory & NamedCollectionFactory::instance()
|
NamedCollectionFactory & NamedCollectionFactory::instance()
|
||||||
{
|
{
|
||||||
@ -87,38 +28,6 @@ NamedCollectionFactory & NamedCollectionFactory::instance()
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamedCollectionFactory::initialize(const Poco::Util::AbstractConfiguration & config_)
|
|
||||||
{
|
|
||||||
std::lock_guard lock(mutex);
|
|
||||||
if (is_initialized)
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::LOGICAL_ERROR,
|
|
||||||
"Named collection factory already initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
config = &config_;
|
|
||||||
is_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedCollectionFactory::reload(const Poco::Util::AbstractConfiguration & config_)
|
|
||||||
{
|
|
||||||
std::lock_guard lock(mutex);
|
|
||||||
config = &config_;
|
|
||||||
loaded_named_collections.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedCollectionFactory::assertInitialized(
|
|
||||||
std::lock_guard<std::mutex> & /* lock */) const
|
|
||||||
{
|
|
||||||
if (!is_initialized)
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::LOGICAL_ERROR,
|
|
||||||
"Named collection factory must be initialized before being used");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NamedCollectionFactory::exists(const std::string & collection_name) const
|
bool NamedCollectionFactory::exists(const std::string & collection_name) const
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
@ -127,62 +36,84 @@ bool NamedCollectionFactory::exists(const std::string & collection_name) const
|
|||||||
|
|
||||||
bool NamedCollectionFactory::existsUnlocked(
|
bool NamedCollectionFactory::existsUnlocked(
|
||||||
const std::string & collection_name,
|
const std::string & collection_name,
|
||||||
std::lock_guard<std::mutex> & lock) const
|
std::lock_guard<std::mutex> & /* lock */) const
|
||||||
{
|
{
|
||||||
assertInitialized(lock);
|
return loaded_named_collections.contains(collection_name);
|
||||||
/// Named collections can be added via SQL command or via config.
|
|
||||||
/// Named collections from config are loaded on first access,
|
|
||||||
/// therefore it might not be in `named_collections` map yet.
|
|
||||||
return loaded_named_collections.contains(collection_name)
|
|
||||||
|| config->has(getCollectionPrefix(collection_name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedCollectionPtr NamedCollectionFactory::get(const std::string & collection_name) const
|
NamedCollectionPtr NamedCollectionFactory::get(const std::string & collection_name) const
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
assertInitialized(lock);
|
auto collection = tryGetUnlocked(collection_name, lock);
|
||||||
|
if (!collection)
|
||||||
if (!existsUnlocked(collection_name, lock))
|
|
||||||
{
|
{
|
||||||
throw Exception(
|
throw Exception(
|
||||||
ErrorCodes::UNKNOWN_NAMED_COLLECTION,
|
ErrorCodes::NAMED_COLLECTION_DOESNT_EXIST,
|
||||||
"There is no named collection `{}`",
|
"There is no named collection `{}`",
|
||||||
collection_name);
|
collection_name);
|
||||||
}
|
}
|
||||||
|
return collection;
|
||||||
return getImpl(collection_name, lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedCollectionPtr NamedCollectionFactory::tryGet(const std::string & collection_name) const
|
NamedCollectionPtr NamedCollectionFactory::tryGet(const std::string & collection_name) const
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
assertInitialized(lock);
|
return tryGetUnlocked(collection_name, lock);
|
||||||
|
|
||||||
if (!existsUnlocked(collection_name, lock))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return getImpl(collection_name, lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedCollectionPtr NamedCollectionFactory::getImpl(
|
MutableNamedCollectionPtr NamedCollectionFactory::getMutable(
|
||||||
|
const std::string & collection_name) const
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
auto collection = tryGetUnlocked(collection_name, lock);
|
||||||
|
if (!collection)
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NAMED_COLLECTION_DOESNT_EXIST,
|
||||||
|
"There is no named collection `{}`",
|
||||||
|
collection_name);
|
||||||
|
}
|
||||||
|
else if (!collection->isMutable())
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NAMED_COLLECTION_IS_IMMUTABLE,
|
||||||
|
"Cannot get collection `{}` for modification, "
|
||||||
|
"because collection was defined as immutable",
|
||||||
|
collection_name);
|
||||||
|
}
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableNamedCollectionPtr NamedCollectionFactory::tryGetUnlocked(
|
||||||
const std::string & collection_name,
|
const std::string & collection_name,
|
||||||
std::lock_guard<std::mutex> & /* lock */) const
|
std::lock_guard<std::mutex> & /* lock */) const
|
||||||
{
|
{
|
||||||
auto it = loaded_named_collections.find(collection_name);
|
auto it = loaded_named_collections.find(collection_name);
|
||||||
if (it == loaded_named_collections.end())
|
if (it == loaded_named_collections.end())
|
||||||
{
|
return nullptr;
|
||||||
it = loaded_named_collections.emplace(
|
|
||||||
collection_name,
|
|
||||||
NamedCollection::create(*config, collection_name)).first;
|
|
||||||
}
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamedCollectionFactory::add(
|
void NamedCollectionFactory::add(
|
||||||
const std::string & collection_name,
|
const std::string & collection_name,
|
||||||
NamedCollectionPtr collection)
|
MutableNamedCollectionPtr collection)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
|
return addUnlocked(collection_name, collection, lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NamedCollectionFactory::add(NamedCollectionsMap collections)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
for (const auto & [collection_name, collection] : collections)
|
||||||
|
addUnlocked(collection_name, collection, lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NamedCollectionFactory::addUnlocked(
|
||||||
|
const std::string & collection_name,
|
||||||
|
MutableNamedCollectionPtr collection,
|
||||||
|
std::lock_guard<std::mutex> & /* lock */)
|
||||||
|
{
|
||||||
auto [it, inserted] = loaded_named_collections.emplace(collection_name, collection);
|
auto [it, inserted] = loaded_named_collections.emplace(collection_name, collection);
|
||||||
if (!inserted)
|
if (!inserted)
|
||||||
{
|
{
|
||||||
@ -196,93 +127,104 @@ void NamedCollectionFactory::add(
|
|||||||
void NamedCollectionFactory::remove(const std::string & collection_name)
|
void NamedCollectionFactory::remove(const std::string & collection_name)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
assertInitialized(lock);
|
bool removed = removeIfExistsUnlocked(collection_name, lock);
|
||||||
|
if (!removed)
|
||||||
if (!existsUnlocked(collection_name, lock))
|
|
||||||
{
|
{
|
||||||
throw Exception(
|
throw Exception(
|
||||||
ErrorCodes::UNKNOWN_NAMED_COLLECTION,
|
ErrorCodes::NAMED_COLLECTION_DOESNT_EXIST,
|
||||||
"There is no named collection `{}`",
|
"There is no named collection `{}`",
|
||||||
collection_name);
|
collection_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->has(collection_name))
|
|
||||||
{
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::NOT_IMPLEMENTED,
|
|
||||||
"Collection {} is defined in config and cannot be removed",
|
|
||||||
collection_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]] auto removed = loaded_named_collections.erase(collection_name);
|
|
||||||
assert(removed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedCollectionFactory::NamedCollections NamedCollectionFactory::getAll() const
|
void NamedCollectionFactory::removeIfExists(const std::string & collection_name)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
assertInitialized(lock);
|
removeIfExistsUnlocked(collection_name, lock);
|
||||||
|
}
|
||||||
|
|
||||||
NamedCollections result(loaded_named_collections);
|
bool NamedCollectionFactory::removeIfExistsUnlocked(
|
||||||
|
const std::string & collection_name,
|
||||||
|
std::lock_guard<std::mutex> & lock)
|
||||||
|
{
|
||||||
|
auto collection = tryGetUnlocked(collection_name, lock);
|
||||||
|
if (!collection)
|
||||||
|
return false;
|
||||||
|
|
||||||
Poco::Util::AbstractConfiguration::Keys config_collections_names;
|
if (!collection->isMutable())
|
||||||
config->keys(NAMED_COLLECTIONS_CONFIG_PREFIX, config_collections_names);
|
|
||||||
|
|
||||||
for (const auto & collection_name : config_collections_names)
|
|
||||||
{
|
{
|
||||||
if (result.contains(collection_name))
|
throw Exception(
|
||||||
continue;
|
ErrorCodes::NAMED_COLLECTION_IS_IMMUTABLE,
|
||||||
|
"Cannot get collection `{}` for modification, "
|
||||||
result.emplace(collection_name, NamedCollection::create(*config, collection_name));
|
"because collection was defined as immutable",
|
||||||
|
collection_name);
|
||||||
}
|
}
|
||||||
|
loaded_named_collections.erase(collection_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
void NamedCollectionFactory::removeById(NamedCollectionUtils::SourceId id)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
std::erase_if(
|
||||||
|
loaded_named_collections,
|
||||||
|
[&](const auto & value) { return value.second->getSourceId() == id; });
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedCollectionsMap NamedCollectionFactory::getAll() const
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
return loaded_named_collections;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NamedCollection::Impl
|
class NamedCollection::Impl
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using ConfigurationPtr = Poco::AutoPtr<Poco::Util::AbstractConfiguration>;
|
|
||||||
|
|
||||||
/// Named collection configuration
|
|
||||||
/// <collection1>
|
|
||||||
/// ...
|
|
||||||
/// </collection1>
|
|
||||||
ConfigurationPtr config;
|
ConfigurationPtr config;
|
||||||
Keys keys;
|
Keys keys;
|
||||||
|
|
||||||
|
Impl(ConfigurationPtr config_, const Keys & keys_) : config(config_) , keys(keys_) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Impl(const Poco::Util::AbstractConfiguration & config_,
|
static ImplPtr create(
|
||||||
const std::string & collection_name_,
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
const Keys & keys_)
|
const std::string & collection_name,
|
||||||
: config(createEmptyConfiguration(collection_name_))
|
const std::string & collection_path,
|
||||||
, keys(keys_)
|
const Keys & keys)
|
||||||
{
|
{
|
||||||
auto collection_path = getCollectionPrefix(collection_name_);
|
auto collection_config = NamedCollectionConfiguration::createEmptyConfiguration(collection_name);
|
||||||
for (const auto & key : keys)
|
for (const auto & key : keys)
|
||||||
copyConfigValue<String>(config_, collection_path + '.' + key, *config, key);
|
Configuration::copyConfigValue<String>(
|
||||||
|
config, collection_path + '.' + key, *collection_config, key);
|
||||||
|
|
||||||
|
return std::unique_ptr<Impl>(new Impl(collection_config, keys));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> T get(const Key & key) const
|
template <typename T> T get(const Key & key) const
|
||||||
{
|
{
|
||||||
return getConfigValue<T>(*config, key);
|
return Configuration::getConfigValue<T>(*config, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> T getOrDefault(const Key & key, const T & default_value) const
|
template <typename T> T getOrDefault(const Key & key, const T & default_value) const
|
||||||
{
|
{
|
||||||
return getConfigValueOrDefault<T>(*config, key, &default_value);
|
return Configuration::getConfigValueOrDefault<T>(*config, key, &default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void set(const Key & key, const T & value, bool update_if_exists)
|
template <typename T> void set(const Key & key, const T & value, bool update_if_exists)
|
||||||
{
|
{
|
||||||
setConfigValue<T>(*config, key, value, update_if_exists);
|
Configuration::setConfigValue<T>(*config, key, value, update_if_exists);
|
||||||
if (!keys.contains(key))
|
if (!keys.contains(key))
|
||||||
keys.insert(key);
|
keys.insert(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImplPtr createCopy(const std::string & collection_name_) const
|
||||||
|
{
|
||||||
|
return create(*config, collection_name_, "", keys);
|
||||||
|
}
|
||||||
|
|
||||||
void remove(const Key & key)
|
void remove(const Key & key)
|
||||||
{
|
{
|
||||||
removeConfigValue(*config, key);
|
Configuration::removeConfigValue(*config, key);
|
||||||
[[maybe_unused]] auto removed = keys.erase(key);
|
[[maybe_unused]] auto removed = keys.erase(key);
|
||||||
assert(removed);
|
assert(removed);
|
||||||
}
|
}
|
||||||
@ -292,11 +234,6 @@ public:
|
|||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImplPtr copy() const
|
|
||||||
{
|
|
||||||
return std::make_unique<Impl>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string dumpStructure() const
|
std::string dumpStructure() const
|
||||||
{
|
{
|
||||||
/// Convert a collection config like
|
/// Convert a collection config like
|
||||||
@ -347,186 +284,108 @@ public:
|
|||||||
}
|
}
|
||||||
return wb.str();
|
return wb.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
template <typename T> static T getConfigValue(
|
|
||||||
const Poco::Util::AbstractConfiguration & config,
|
|
||||||
const std::string & path)
|
|
||||||
{
|
|
||||||
return getConfigValueOrDefault<T>(config, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> static T getConfigValueOrDefault(
|
|
||||||
const Poco::Util::AbstractConfiguration & config,
|
|
||||||
const std::string & path,
|
|
||||||
const T * default_value = nullptr)
|
|
||||||
{
|
|
||||||
if (!config.has(path))
|
|
||||||
{
|
|
||||||
if (!default_value)
|
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "No such key `{}`", path);
|
|
||||||
return *default_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, String>)
|
|
||||||
return config.getString(path);
|
|
||||||
else if constexpr (std::is_same_v<T, UInt64>)
|
|
||||||
return config.getUInt64(path);
|
|
||||||
else if constexpr (std::is_same_v<T, Int64>)
|
|
||||||
return config.getInt64(path);
|
|
||||||
else if constexpr (std::is_same_v<T, Float64>)
|
|
||||||
return config.getDouble(path);
|
|
||||||
else
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::NOT_IMPLEMENTED,
|
|
||||||
"Unsupported type in getConfigValueOrDefault(). "
|
|
||||||
"Supported types are String, UInt64, Int64, Float64");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> static void setConfigValue(
|
|
||||||
Poco::Util::AbstractConfiguration & config,
|
|
||||||
const std::string & path,
|
|
||||||
const T & value,
|
|
||||||
bool update = false)
|
|
||||||
{
|
|
||||||
if (!update && config.has(path))
|
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Key `{}` already exists", path);
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, String>)
|
|
||||||
config.setString(path, value);
|
|
||||||
else if constexpr (std::is_same_v<T, UInt64>)
|
|
||||||
config.setUInt64(path, value);
|
|
||||||
else if constexpr (std::is_same_v<T, Int64>)
|
|
||||||
config.setInt64(path, value);
|
|
||||||
else if constexpr (std::is_same_v<T, Float64>)
|
|
||||||
config.setDouble(path, value);
|
|
||||||
else
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::NOT_IMPLEMENTED,
|
|
||||||
"Unsupported type in setConfigValue(). "
|
|
||||||
"Supported types are String, UInt64, Int64, Float64");
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> static void copyConfigValue(
|
|
||||||
const Poco::Util::AbstractConfiguration & from_config,
|
|
||||||
const std::string & from_path,
|
|
||||||
Poco::Util::AbstractConfiguration & to_config,
|
|
||||||
const std::string & to_path)
|
|
||||||
{
|
|
||||||
if (!from_config.has(from_path))
|
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "No such key `{}`", from_path);
|
|
||||||
|
|
||||||
if (to_config.has(to_path))
|
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Key `{}` already exists", to_path);
|
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, String>)
|
|
||||||
to_config.setString(to_path, from_config.getString(from_path));
|
|
||||||
else if constexpr (std::is_same_v<T, std::string>)
|
|
||||||
to_config.setString(to_path, from_config.getString(from_path));
|
|
||||||
else if constexpr (std::is_same_v<T, UInt64>)
|
|
||||||
to_config.setUInt64(to_path, from_config.getUInt64(from_path));
|
|
||||||
else if constexpr (std::is_same_v<T, Int64>)
|
|
||||||
to_config.setInt64(to_path, from_config.getInt64(from_path));
|
|
||||||
else if constexpr (std::is_same_v<T, Float64>)
|
|
||||||
to_config.setDouble(to_path, from_config.getDouble(from_path));
|
|
||||||
else
|
|
||||||
throw Exception(
|
|
||||||
ErrorCodes::NOT_IMPLEMENTED,
|
|
||||||
"Unsupported type in copyConfigValue(). "
|
|
||||||
"Supported types are String, UInt64, Int64, Float64");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void removeConfigValue(
|
|
||||||
Poco::Util::AbstractConfiguration & config,
|
|
||||||
const std::string & path)
|
|
||||||
{
|
|
||||||
if (!config.has(path))
|
|
||||||
throw Exception(ErrorCodes::BAD_ARGUMENTS, "No such key `{}`", path);
|
|
||||||
config.remove(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ConfigurationPtr createEmptyConfiguration(const std::string & root_name)
|
|
||||||
{
|
|
||||||
using DocumentPtr = Poco::AutoPtr<Poco::XML::Document>;
|
|
||||||
DocumentPtr xml_document(new Poco::XML::Document());
|
|
||||||
xml_document->appendChild(xml_document->createElement(root_name));
|
|
||||||
ConfigurationPtr config(new Poco::Util::XMLConfiguration(xml_document));
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NamedCollection::NamedCollection(
|
NamedCollection::NamedCollection(
|
||||||
const Poco::Util::AbstractConfiguration & config,
|
ImplPtr pimpl_,
|
||||||
const std::string & collection_path,
|
const std::string & collection_name_,
|
||||||
const Keys & keys)
|
SourceId source_id_,
|
||||||
: NamedCollection(std::make_unique<Impl>(config, collection_path, keys))
|
bool is_mutable_)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NamedCollection::NamedCollection(ImplPtr pimpl_)
|
|
||||||
: pimpl(std::move(pimpl_))
|
: pimpl(std::move(pimpl_))
|
||||||
|
, collection_name(collection_name_)
|
||||||
|
, source_id(source_id_)
|
||||||
|
, is_mutable(is_mutable_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedCollectionPtr NamedCollection::create(
|
MutableNamedCollectionPtr NamedCollection::create(
|
||||||
const Poco::Util::AbstractConfiguration & config,
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
const std::string & collection_name)
|
const std::string & collection_name,
|
||||||
|
const std::string & collection_path,
|
||||||
|
const Keys & keys,
|
||||||
|
SourceId source_id,
|
||||||
|
bool is_mutable)
|
||||||
{
|
{
|
||||||
const auto collection_prefix = getCollectionPrefix(collection_name);
|
auto impl = Impl::create(config, collection_name, collection_path, keys);
|
||||||
std::queue<std::string> enumerate_input;
|
return std::unique_ptr<NamedCollection>(
|
||||||
std::set<std::string> enumerate_result;
|
new NamedCollection(std::move(impl), collection_name, source_id, is_mutable));
|
||||||
|
|
||||||
enumerate_input.push(collection_prefix);
|
|
||||||
collectKeys(config, std::move(enumerate_input), enumerate_result);
|
|
||||||
|
|
||||||
/// Collection does not have any keys.
|
|
||||||
/// (`enumerate_result` == <collection_path>).
|
|
||||||
const bool collection_is_empty = enumerate_result.size() == 1;
|
|
||||||
std::set<std::string> keys;
|
|
||||||
if (!collection_is_empty)
|
|
||||||
{
|
|
||||||
/// Skip collection prefix and add +1 to avoid '.' in the beginning.
|
|
||||||
for (const auto & path : enumerate_result)
|
|
||||||
keys.emplace(path.substr(collection_prefix.size() + 1));
|
|
||||||
}
|
|
||||||
return std::make_unique<NamedCollection>(config, collection_name, keys);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> T NamedCollection::get(const Key & key) const
|
template <typename T> T NamedCollection::get(const Key & key) const
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
return pimpl->get<T>(key);
|
return pimpl->get<T>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> T NamedCollection::getOrDefault(const Key & key, const T & default_value) const
|
template <typename T> T NamedCollection::getOrDefault(const Key & key, const T & default_value) const
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
return pimpl->getOrDefault<T>(key, default_value);
|
return pimpl->getOrDefault<T>(key, default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void NamedCollection::set(const Key & key, const T & value, bool update_if_exists)
|
template <typename T, bool Locked> void NamedCollection::set(const Key & key, const T & value)
|
||||||
{
|
{
|
||||||
pimpl->set<T>(key, value, update_if_exists);
|
assertMutable();
|
||||||
|
std::unique_lock lock(mutex, std::defer_lock);
|
||||||
|
if constexpr (!Locked)
|
||||||
|
lock.lock();
|
||||||
|
pimpl->set<T>(key, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamedCollection::remove(const Key & key)
|
template <typename T, bool Locked> void NamedCollection::setOrUpdate(const Key & key, const T & value)
|
||||||
{
|
{
|
||||||
|
assertMutable();
|
||||||
|
std::unique_lock lock(mutex, std::defer_lock);
|
||||||
|
if constexpr (!Locked)
|
||||||
|
lock.lock();
|
||||||
|
pimpl->set<T>(key, value, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool Locked> void NamedCollection::remove(const Key & key)
|
||||||
|
{
|
||||||
|
assertMutable();
|
||||||
|
std::unique_lock lock(mutex, std::defer_lock);
|
||||||
|
if constexpr (!Locked)
|
||||||
|
lock.lock();
|
||||||
pimpl->remove(key);
|
pimpl->remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<NamedCollection> NamedCollection::duplicate() const
|
void NamedCollection::assertMutable() const
|
||||||
{
|
{
|
||||||
return std::make_shared<NamedCollection>(pimpl->copy());
|
if (!is_mutable)
|
||||||
|
{
|
||||||
|
throw Exception(
|
||||||
|
ErrorCodes::NAMED_COLLECTION_IS_IMMUTABLE,
|
||||||
|
"Cannot change named collection because it is immutable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MutableNamedCollectionPtr NamedCollection::duplicate() const
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
auto impl = pimpl->createCopy(collection_name);
|
||||||
|
return std::unique_ptr<NamedCollection>(
|
||||||
|
new NamedCollection(
|
||||||
|
std::move(impl), collection_name, NamedCollectionUtils::SourceId::NONE, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
NamedCollection::Keys NamedCollection::getKeys() const
|
NamedCollection::Keys NamedCollection::getKeys() const
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
return pimpl->getKeys();
|
return pimpl->getKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NamedCollection::dumpStructure() const
|
std::string NamedCollection::dumpStructure() const
|
||||||
{
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
return pimpl->dumpStructure();
|
return pimpl->dumpStructure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> NamedCollection::lock()
|
||||||
|
{
|
||||||
|
return std::unique_lock(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
template String NamedCollection::get<String>(const NamedCollection::Key & key) const;
|
template String NamedCollection::get<String>(const NamedCollection::Key & key) const;
|
||||||
template UInt64 NamedCollection::get<UInt64>(const NamedCollection::Key & key) const;
|
template UInt64 NamedCollection::get<UInt64>(const NamedCollection::Key & key) const;
|
||||||
template Int64 NamedCollection::get<Int64>(const NamedCollection::Key & key) const;
|
template Int64 NamedCollection::get<Int64>(const NamedCollection::Key & key) const;
|
||||||
@ -537,9 +396,25 @@ template UInt64 NamedCollection::getOrDefault<UInt64>(const NamedCollection::Key
|
|||||||
template Int64 NamedCollection::getOrDefault<Int64>(const NamedCollection::Key & key, const Int64 & default_value) const;
|
template Int64 NamedCollection::getOrDefault<Int64>(const NamedCollection::Key & key, const Int64 & default_value) const;
|
||||||
template Float64 NamedCollection::getOrDefault<Float64>(const NamedCollection::Key & key, const Float64 & default_value) const;
|
template Float64 NamedCollection::getOrDefault<Float64>(const NamedCollection::Key & key, const Float64 & default_value) const;
|
||||||
|
|
||||||
template void NamedCollection::set<String>(const NamedCollection::Key & key, const String & value, bool update_if_exists);
|
template void NamedCollection::set<String, true>(const NamedCollection::Key & key, const String & value);
|
||||||
template void NamedCollection::set<UInt64>(const NamedCollection::Key & key, const UInt64 & value, bool update_if_exists);
|
template void NamedCollection::set<String, false>(const NamedCollection::Key & key, const String & value);
|
||||||
template void NamedCollection::set<Int64>(const NamedCollection::Key & key, const Int64 & value, bool update_if_exists);
|
template void NamedCollection::set<UInt64, true>(const NamedCollection::Key & key, const UInt64 & value);
|
||||||
template void NamedCollection::set<Float64>(const NamedCollection::Key & key, const Float64 & value, bool update_if_exists);
|
template void NamedCollection::set<UInt64, false>(const NamedCollection::Key & key, const UInt64 & value);
|
||||||
|
template void NamedCollection::set<Int64, true>(const NamedCollection::Key & key, const Int64 & value);
|
||||||
|
template void NamedCollection::set<Int64, false>(const NamedCollection::Key & key, const Int64 & value);
|
||||||
|
template void NamedCollection::set<Float64, true>(const NamedCollection::Key & key, const Float64 & value);
|
||||||
|
template void NamedCollection::set<Float64, false>(const NamedCollection::Key & key, const Float64 & value);
|
||||||
|
|
||||||
|
template void NamedCollection::setOrUpdate<String, true>(const NamedCollection::Key & key, const String & value);
|
||||||
|
template void NamedCollection::setOrUpdate<String, false>(const NamedCollection::Key & key, const String & value);
|
||||||
|
template void NamedCollection::setOrUpdate<UInt64, true>(const NamedCollection::Key & key, const UInt64 & value);
|
||||||
|
template void NamedCollection::setOrUpdate<UInt64, false>(const NamedCollection::Key & key, const UInt64 & value);
|
||||||
|
template void NamedCollection::setOrUpdate<Int64, true>(const NamedCollection::Key & key, const Int64 & value);
|
||||||
|
template void NamedCollection::setOrUpdate<Int64, false>(const NamedCollection::Key & key, const Int64 & value);
|
||||||
|
template void NamedCollection::setOrUpdate<Float64, true>(const NamedCollection::Key & key, const Float64 & value);
|
||||||
|
template void NamedCollection::setOrUpdate<Float64, false>(const NamedCollection::Key & key, const Float64 & value);
|
||||||
|
|
||||||
|
template void NamedCollection::remove<true>(const Key & key);
|
||||||
|
template void NamedCollection::remove<false>(const Key & key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Interpreters/Context.h>
|
#include <Interpreters/Context.h>
|
||||||
#include <Poco/Util/AbstractConfiguration.h>
|
#include <Storages/NamedCollections_fwd.h>
|
||||||
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
|
|
||||||
|
namespace Poco { namespace Util { class AbstractConfiguration; } }
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
class NamedCollection;
|
|
||||||
using NamedCollectionPtr = std::shared_ptr<const NamedCollection>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to represent arbitrary-structured named collection object.
|
* Class to represent arbitrary-structured named collection object.
|
||||||
* It can be defined via config or via SQL command.
|
* It can be defined via config or via SQL command.
|
||||||
@ -22,40 +20,58 @@ using NamedCollectionPtr = std::shared_ptr<const NamedCollection>;
|
|||||||
*/
|
*/
|
||||||
class NamedCollection
|
class NamedCollection
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
class Impl;
|
|
||||||
using ImplPtr = std::unique_ptr<Impl>;
|
|
||||||
|
|
||||||
ImplPtr pimpl;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Key = std::string;
|
using Key = std::string;
|
||||||
using Keys = std::set<Key>;
|
using Keys = std::set<Key>;
|
||||||
|
using SourceId = NamedCollectionUtils::SourceId;
|
||||||
|
|
||||||
static NamedCollectionPtr create(
|
static MutableNamedCollectionPtr create(
|
||||||
const Poco::Util::AbstractConfiguration & config,
|
|
||||||
const std::string & collection_name);
|
|
||||||
|
|
||||||
NamedCollection(
|
|
||||||
const Poco::Util::AbstractConfiguration & config,
|
const Poco::Util::AbstractConfiguration & config,
|
||||||
|
const std::string & collection_name,
|
||||||
const std::string & collection_path,
|
const std::string & collection_path,
|
||||||
const Keys & keys);
|
const Keys & keys,
|
||||||
|
SourceId source_id_,
|
||||||
explicit NamedCollection(ImplPtr pimpl_);
|
bool is_mutable_);
|
||||||
|
|
||||||
template <typename T> T get(const Key & key) const;
|
template <typename T> T get(const Key & key) const;
|
||||||
|
|
||||||
template <typename T> T getOrDefault(const Key & key, const T & default_value) const;
|
template <typename T> T getOrDefault(const Key & key, const T & default_value) const;
|
||||||
|
|
||||||
template <typename T> void set(const Key & key, const T & value, bool update_if_exists = false);
|
std::unique_lock<std::mutex> lock();
|
||||||
|
|
||||||
void remove(const Key & key);
|
template <typename T, bool locked = false> void set(const Key & key, const T & value);
|
||||||
|
|
||||||
std::shared_ptr<NamedCollection> duplicate() const;
|
template <typename T, bool locked = false> void setOrUpdate(const Key & key, const T & value);
|
||||||
|
|
||||||
|
template <bool locked = false> void remove(const Key & key);
|
||||||
|
|
||||||
|
MutableNamedCollectionPtr duplicate() const;
|
||||||
|
|
||||||
Keys getKeys() const;
|
Keys getKeys() const;
|
||||||
|
|
||||||
std::string dumpStructure() const;
|
std::string dumpStructure() const;
|
||||||
|
|
||||||
|
bool isMutable() const { return is_mutable; }
|
||||||
|
|
||||||
|
SourceId getSourceId() const { return source_id; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Impl;
|
||||||
|
using ImplPtr = std::unique_ptr<Impl>;
|
||||||
|
|
||||||
|
NamedCollection(
|
||||||
|
ImplPtr pimpl_,
|
||||||
|
const std::string & collection_name,
|
||||||
|
SourceId source_id,
|
||||||
|
bool is_mutable);
|
||||||
|
|
||||||
|
void assertMutable() const;
|
||||||
|
|
||||||
|
ImplPtr pimpl;
|
||||||
|
const std::string collection_name;
|
||||||
|
const SourceId source_id;
|
||||||
|
const bool is_mutable;
|
||||||
|
mutable std::mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,42 +82,51 @@ class NamedCollectionFactory : boost::noncopyable
|
|||||||
public:
|
public:
|
||||||
static NamedCollectionFactory & instance();
|
static NamedCollectionFactory & instance();
|
||||||
|
|
||||||
void initialize(const Poco::Util::AbstractConfiguration & config_);
|
|
||||||
|
|
||||||
void reload(const Poco::Util::AbstractConfiguration & config_);
|
|
||||||
|
|
||||||
bool exists(const std::string & collection_name) const;
|
bool exists(const std::string & collection_name) const;
|
||||||
|
|
||||||
NamedCollectionPtr get(const std::string & collection_name) const;
|
NamedCollectionPtr get(const std::string & collection_name) const;
|
||||||
|
|
||||||
NamedCollectionPtr tryGet(const std::string & collection_name) const;
|
NamedCollectionPtr tryGet(const std::string & collection_name) const;
|
||||||
|
|
||||||
void add(
|
MutableNamedCollectionPtr getMutable(const std::string & collection_name) const;
|
||||||
const std::string & collection_name,
|
|
||||||
NamedCollectionPtr collection);
|
void add(const std::string & collection_name, MutableNamedCollectionPtr collection);
|
||||||
|
|
||||||
|
void add(NamedCollectionsMap collections);
|
||||||
|
|
||||||
|
void update(NamedCollectionsMap collections);
|
||||||
|
|
||||||
void remove(const std::string & collection_name);
|
void remove(const std::string & collection_name);
|
||||||
|
|
||||||
using NamedCollections = std::unordered_map<std::string, NamedCollectionPtr>;
|
void removeIfExists(const std::string & collection_name);
|
||||||
NamedCollections getAll() const;
|
|
||||||
|
void removeById(NamedCollectionUtils::SourceId id);
|
||||||
|
|
||||||
|
NamedCollectionsMap getAll() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void assertInitialized(std::lock_guard<std::mutex> & lock) const;
|
|
||||||
|
|
||||||
NamedCollectionPtr getImpl(
|
|
||||||
const std::string & collection_name,
|
|
||||||
std::lock_guard<std::mutex> & lock) const;
|
|
||||||
|
|
||||||
bool existsUnlocked(
|
bool existsUnlocked(
|
||||||
const std::string & collection_name,
|
const std::string & collection_name,
|
||||||
std::lock_guard<std::mutex> & lock) const;
|
std::lock_guard<std::mutex> & lock) const;
|
||||||
|
|
||||||
mutable NamedCollections loaded_named_collections;
|
MutableNamedCollectionPtr tryGetUnlocked(
|
||||||
|
const std::string & collection_name,
|
||||||
|
std::lock_guard<std::mutex> & lock) const;
|
||||||
|
|
||||||
const Poco::Util::AbstractConfiguration * config;
|
void addUnlocked(
|
||||||
|
const std::string & collection_name,
|
||||||
|
MutableNamedCollectionPtr collection,
|
||||||
|
std::lock_guard<std::mutex> & lock);
|
||||||
|
|
||||||
|
bool removeIfExistsUnlocked(
|
||||||
|
const std::string & collection_name,
|
||||||
|
std::lock_guard<std::mutex> & lock);
|
||||||
|
|
||||||
|
mutable NamedCollectionsMap loaded_named_collections;
|
||||||
|
|
||||||
bool is_initialized = false;
|
|
||||||
mutable std::mutex mutex;
|
mutable std::mutex mutex;
|
||||||
|
bool is_initialized = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
12
src/Storages/NamedCollections_fwd.h
Normal file
12
src/Storages/NamedCollections_fwd.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class NamedCollection;
|
||||||
|
using NamedCollectionPtr = std::shared_ptr<const NamedCollection>;
|
||||||
|
using MutableNamedCollectionPtr = std::shared_ptr<NamedCollection>;
|
||||||
|
using NamedCollectionsMap = std::map<std::string, MutableNamedCollectionPtr>;
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
#include <Common/tests/gtest_global_context.h>
|
#include <Common/tests/gtest_global_context.h>
|
||||||
#include <Storages/NamedCollections.h>
|
#include <Storages/NamedCollections.h>
|
||||||
|
#include <Storages/NamedCollectionUtils.h>
|
||||||
#include <Poco/Util/XMLConfiguration.h>
|
#include <Poco/Util/XMLConfiguration.h>
|
||||||
#include <Poco/DOM/DOMParser.h>
|
#include <Poco/DOM/DOMParser.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
@ -28,7 +29,7 @@ TEST(NamedCollections, SimpleConfig)
|
|||||||
Poco::AutoPtr<Poco::XML::Document> document = dom_parser.parseString(xml);
|
Poco::AutoPtr<Poco::XML::Document> document = dom_parser.parseString(xml);
|
||||||
Poco::AutoPtr<Poco::Util::XMLConfiguration> config = new Poco::Util::XMLConfiguration(document);
|
Poco::AutoPtr<Poco::Util::XMLConfiguration> config = new Poco::Util::XMLConfiguration(document);
|
||||||
|
|
||||||
NamedCollectionFactory::instance().initialize(*config);
|
NamedCollectionUtils::loadFromConfig(*config);
|
||||||
|
|
||||||
ASSERT_TRUE(NamedCollectionFactory::instance().exists("collection1"));
|
ASSERT_TRUE(NamedCollectionFactory::instance().exists("collection1"));
|
||||||
ASSERT_TRUE(NamedCollectionFactory::instance().exists("collection2"));
|
ASSERT_TRUE(NamedCollectionFactory::instance().exists("collection2"));
|
||||||
@ -76,16 +77,16 @@ key5: 5
|
|||||||
key6: 6.6
|
key6: 6.6
|
||||||
)CONFIG");
|
)CONFIG");
|
||||||
|
|
||||||
collection2_copy->set<String>("key4", "value44", true);
|
collection2_copy->setOrUpdate<String>("key4", "value44");
|
||||||
ASSERT_TRUE(collection2_copy->get<String>("key4") == "value44");
|
ASSERT_EQ(collection2_copy->get<String>("key4"), "value44");
|
||||||
ASSERT_TRUE(collection2->get<String>("key4") == "value4");
|
ASSERT_EQ(collection2->get<String>("key4"), "value4");
|
||||||
|
|
||||||
collection2_copy->remove("key4");
|
collection2_copy->remove("key4");
|
||||||
ASSERT_TRUE(collection2_copy->getOrDefault<String>("key4", "N") == "N");
|
ASSERT_EQ(collection2_copy->getOrDefault<String>("key4", "N"), "N");
|
||||||
ASSERT_TRUE(collection2->getOrDefault<String>("key4", "N") == "value4");
|
ASSERT_EQ(collection2->getOrDefault<String>("key4", "N"), "value4");
|
||||||
|
|
||||||
collection2_copy->set<String>("key4", "value45");
|
collection2_copy->setOrUpdate<String>("key4", "value45");
|
||||||
ASSERT_TRUE(collection2_copy->getOrDefault<String>("key4", "N") == "value45");
|
ASSERT_EQ(collection2_copy->getOrDefault<String>("key4", "N"), "value45");
|
||||||
|
|
||||||
NamedCollectionFactory::instance().remove("collection2_copy");
|
NamedCollectionFactory::instance().remove("collection2_copy");
|
||||||
ASSERT_FALSE(NamedCollectionFactory::instance().exists("collection2_copy"));
|
ASSERT_FALSE(NamedCollectionFactory::instance().exists("collection2_copy"));
|
||||||
@ -97,7 +98,7 @@ TEST(NamedCollections, NestedConfig)
|
|||||||
{
|
{
|
||||||
std::string xml(R"CONFIG(<clickhouse>
|
std::string xml(R"CONFIG(<clickhouse>
|
||||||
<named_collections>
|
<named_collections>
|
||||||
<collection1>
|
<collection3>
|
||||||
<key1>
|
<key1>
|
||||||
<key1_1>value1</key1_1>
|
<key1_1>value1</key1_1>
|
||||||
</key1>
|
</key1>
|
||||||
@ -110,21 +111,22 @@ TEST(NamedCollections, NestedConfig)
|
|||||||
</key2_3>
|
</key2_3>
|
||||||
</key2_2>
|
</key2_2>
|
||||||
</key2>
|
</key2>
|
||||||
</collection1>
|
</collection3>
|
||||||
</named_collections>
|
</named_collections>
|
||||||
</clickhouse>)CONFIG");
|
</clickhouse>)CONFIG");
|
||||||
|
|
||||||
Poco::XML::DOMParser dom_parser;
|
Poco::XML::DOMParser dom_parser;
|
||||||
Poco::AutoPtr<Poco::XML::Document> document = dom_parser.parseString(xml);
|
Poco::AutoPtr<Poco::XML::Document> document = dom_parser.parseString(xml);
|
||||||
Poco::AutoPtr<Poco::Util::XMLConfiguration> config = new Poco::Util::XMLConfiguration(document);
|
Poco::AutoPtr<Poco::Util::XMLConfiguration> config = new Poco::Util::XMLConfiguration(document);
|
||||||
NamedCollectionFactory::instance().reload(*config);
|
|
||||||
|
|
||||||
ASSERT_TRUE(NamedCollectionFactory::instance().exists("collection1"));
|
NamedCollectionUtils::loadFromConfig(*config);
|
||||||
|
|
||||||
auto collection1 = NamedCollectionFactory::instance().get("collection1");
|
ASSERT_TRUE(NamedCollectionFactory::instance().exists("collection3"));
|
||||||
ASSERT_TRUE(collection1 != nullptr);
|
|
||||||
|
|
||||||
ASSERT_EQ(collection1->dumpStructure(),
|
auto collection = NamedCollectionFactory::instance().get("collection3");
|
||||||
|
ASSERT_TRUE(collection != nullptr);
|
||||||
|
|
||||||
|
ASSERT_EQ(collection->dumpStructure(),
|
||||||
R"CONFIG(key1:
|
R"CONFIG(key1:
|
||||||
key1_1: value1
|
key1_1: value1
|
||||||
key2:
|
key2:
|
||||||
@ -135,9 +137,9 @@ key2:
|
|||||||
key2_5: 5
|
key2_5: 5
|
||||||
)CONFIG");
|
)CONFIG");
|
||||||
|
|
||||||
ASSERT_EQ(collection1->get<String>("key1.key1_1"), "value1");
|
ASSERT_EQ(collection->get<String>("key1.key1_1"), "value1");
|
||||||
ASSERT_EQ(collection1->get<String>("key2.key2_1"), "value2_1");
|
ASSERT_EQ(collection->get<String>("key2.key2_1"), "value2_1");
|
||||||
ASSERT_EQ(collection1->get<Int64>("key2.key2_2.key2_3.key2_4"), 4);
|
ASSERT_EQ(collection->get<Int64>("key2.key2_2.key2_3.key2_4"), 4);
|
||||||
ASSERT_EQ(collection1->get<Int64>("key2.key2_2.key2_3.key2_5"), 5);
|
ASSERT_EQ(collection->get<Int64>("key2.key2_2.key2_3.key2_5"), 5);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
<clickhouse>
|
||||||
|
<named_collections>
|
||||||
|
<collection1>
|
||||||
|
<key1>value1</key1>
|
||||||
|
</collection1>
|
||||||
|
</named_collections>
|
||||||
|
</clickhouse>
|
@ -0,0 +1,13 @@
|
|||||||
|
<clickhouse>
|
||||||
|
<users>
|
||||||
|
<default>
|
||||||
|
<password></password>
|
||||||
|
<networks>
|
||||||
|
<ip>::/0</ip>
|
||||||
|
</networks>
|
||||||
|
<profile>default</profile>
|
||||||
|
<quota>default</quota>
|
||||||
|
<show_named_collections>1</show_named_collections>
|
||||||
|
</default>
|
||||||
|
</users>
|
||||||
|
</clickhouse>
|
200
tests/integration/test_named_collections/test.py
Normal file
200
tests/integration/test_named_collections/test.py
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import logging
|
||||||
|
import pytest
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
from helpers.cluster import ClickHouseCluster
|
||||||
|
|
||||||
|
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
NAMED_COLLECTIONS_CONFIG = os.path.join(
|
||||||
|
SCRIPT_DIR, "./configs/config.d/named_collections.xml"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="module")
|
||||||
|
def cluster():
|
||||||
|
try:
|
||||||
|
cluster = ClickHouseCluster(__file__)
|
||||||
|
cluster.add_instance(
|
||||||
|
"node",
|
||||||
|
main_configs=[
|
||||||
|
"configs/config.d/named_collections.xml",
|
||||||
|
],
|
||||||
|
user_configs=[
|
||||||
|
"configs/users.d/users.xml",
|
||||||
|
],
|
||||||
|
stay_alive=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
logging.info("Starting cluster...")
|
||||||
|
cluster.start()
|
||||||
|
logging.info("Cluster started")
|
||||||
|
|
||||||
|
yield cluster
|
||||||
|
finally:
|
||||||
|
cluster.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
def replace_config(node, old, new):
|
||||||
|
node.replace_in_config(
|
||||||
|
"/etc/clickhouse-server/config.d/named_collections.xml",
|
||||||
|
old,
|
||||||
|
new,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_reload(cluster):
|
||||||
|
node = cluster.instances["node"]
|
||||||
|
assert (
|
||||||
|
"collection1" == node.query("select name from system.named_collections").strip()
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
"['key1']"
|
||||||
|
== node.query(
|
||||||
|
"select mapKeys(collection) from system.named_collections where name = 'collection1'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
"value1"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key1'] from system.named_collections where name = 'collection1'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
replace_config(node, "value1", "value2")
|
||||||
|
node.query("SYSTEM RELOAD CONFIG")
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"['key1']"
|
||||||
|
== node.query(
|
||||||
|
"select mapKeys(collection) from system.named_collections where name = 'collection1'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
"value2"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key1'] from system.named_collections where name = 'collection1'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_sql_commands(cluster):
|
||||||
|
node = cluster.instances["node"]
|
||||||
|
assert "1" == node.query("select count() from system.named_collections").strip()
|
||||||
|
|
||||||
|
node.query("CREATE NAMED COLLECTION collection2 AS key1=1, key2='value2'")
|
||||||
|
|
||||||
|
def check_created():
|
||||||
|
assert (
|
||||||
|
"collection1\ncollection2"
|
||||||
|
== node.query("select name from system.named_collections").strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"['key1','key2']"
|
||||||
|
== node.query(
|
||||||
|
"select mapKeys(collection) from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"1"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key1'] from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"value2"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key2'] from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
check_created()
|
||||||
|
node.restart_clickhouse()
|
||||||
|
check_created()
|
||||||
|
|
||||||
|
node.query("ALTER NAMED COLLECTION collection2 SET key1=4, key3='value3'")
|
||||||
|
|
||||||
|
def check_altered():
|
||||||
|
assert (
|
||||||
|
"['key1','key2','key3']"
|
||||||
|
== node.query(
|
||||||
|
"select mapKeys(collection) from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"4"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key1'] from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"value3"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key3'] from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
check_altered()
|
||||||
|
node.restart_clickhouse()
|
||||||
|
check_altered()
|
||||||
|
|
||||||
|
node.query("ALTER NAMED COLLECTION collection2 DELETE key2")
|
||||||
|
|
||||||
|
def check_deleted():
|
||||||
|
assert (
|
||||||
|
"['key1','key3']"
|
||||||
|
== node.query(
|
||||||
|
"select mapKeys(collection) from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
check_deleted()
|
||||||
|
node.restart_clickhouse()
|
||||||
|
check_deleted()
|
||||||
|
|
||||||
|
node.query(
|
||||||
|
"ALTER NAMED COLLECTION collection2 SET key3=3, key4='value4' DELETE key1"
|
||||||
|
)
|
||||||
|
|
||||||
|
def check_altered_and_deleted():
|
||||||
|
assert (
|
||||||
|
"['key3','key4']"
|
||||||
|
== node.query(
|
||||||
|
"select mapKeys(collection) from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"3"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key3'] from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
"value4"
|
||||||
|
== node.query(
|
||||||
|
"select collection['key4'] from system.named_collections where name = 'collection2'"
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
check_altered_and_deleted()
|
||||||
|
node.restart_clickhouse()
|
||||||
|
check_altered_and_deleted()
|
||||||
|
|
||||||
|
node.query("DROP NAMED COLLECTION collection2")
|
||||||
|
|
||||||
|
def check_dropped():
|
||||||
|
assert "1" == node.query("select count() from system.named_collections").strip()
|
||||||
|
assert (
|
||||||
|
"collection1"
|
||||||
|
== node.query("select name from system.named_collections").strip()
|
||||||
|
)
|
||||||
|
|
||||||
|
check_dropped()
|
||||||
|
node.restart_clickhouse()
|
||||||
|
check_dropped()
|
@ -39,6 +39,7 @@ ALTER MOVE PARTITION ['ALTER MOVE PART','MOVE PARTITION','MOVE PART'] TABLE ALTE
|
|||||||
ALTER FETCH PARTITION ['ALTER FETCH PART','FETCH PARTITION'] TABLE ALTER TABLE
|
ALTER FETCH PARTITION ['ALTER FETCH PART','FETCH PARTITION'] TABLE ALTER TABLE
|
||||||
ALTER FREEZE PARTITION ['FREEZE PARTITION','UNFREEZE'] TABLE ALTER TABLE
|
ALTER FREEZE PARTITION ['FREEZE PARTITION','UNFREEZE'] TABLE ALTER TABLE
|
||||||
ALTER DATABASE SETTINGS ['ALTER DATABASE SETTING','ALTER MODIFY DATABASE SETTING','MODIFY DATABASE SETTING'] DATABASE ALTER DATABASE
|
ALTER DATABASE SETTINGS ['ALTER DATABASE SETTING','ALTER MODIFY DATABASE SETTING','MODIFY DATABASE SETTING'] DATABASE ALTER DATABASE
|
||||||
|
ALTER NAMED COLLECTION [] \N ALTER
|
||||||
ALTER TABLE [] \N ALTER
|
ALTER TABLE [] \N ALTER
|
||||||
ALTER DATABASE [] \N ALTER
|
ALTER DATABASE [] \N ALTER
|
||||||
ALTER VIEW REFRESH ['ALTER LIVE VIEW REFRESH','REFRESH VIEW'] VIEW ALTER VIEW
|
ALTER VIEW REFRESH ['ALTER LIVE VIEW REFRESH','REFRESH VIEW'] VIEW ALTER VIEW
|
||||||
@ -51,12 +52,14 @@ CREATE VIEW [] VIEW CREATE
|
|||||||
CREATE DICTIONARY [] DICTIONARY CREATE
|
CREATE DICTIONARY [] DICTIONARY CREATE
|
||||||
CREATE TEMPORARY TABLE [] GLOBAL CREATE
|
CREATE TEMPORARY TABLE [] GLOBAL CREATE
|
||||||
CREATE FUNCTION [] GLOBAL CREATE
|
CREATE FUNCTION [] GLOBAL CREATE
|
||||||
|
CREATE NAMED COLLECTION [] GLOBAL CREATE
|
||||||
CREATE [] \N ALL
|
CREATE [] \N ALL
|
||||||
DROP DATABASE [] DATABASE DROP
|
DROP DATABASE [] DATABASE DROP
|
||||||
DROP TABLE [] TABLE DROP
|
DROP TABLE [] TABLE DROP
|
||||||
DROP VIEW [] VIEW DROP
|
DROP VIEW [] VIEW DROP
|
||||||
DROP DICTIONARY [] DICTIONARY DROP
|
DROP DICTIONARY [] DICTIONARY DROP
|
||||||
DROP FUNCTION [] GLOBAL DROP
|
DROP FUNCTION [] GLOBAL DROP
|
||||||
|
DROP NAMED COLLECTION [] GLOBAL DROP
|
||||||
DROP [] \N ALL
|
DROP [] \N ALL
|
||||||
TRUNCATE ['TRUNCATE TABLE'] TABLE ALL
|
TRUNCATE ['TRUNCATE TABLE'] TABLE ALL
|
||||||
OPTIMIZE ['OPTIMIZE TABLE'] TABLE ALL
|
OPTIMIZE ['OPTIMIZE TABLE'] TABLE ALL
|
||||||
|
@ -284,7 +284,7 @@ CREATE TABLE system.grants
|
|||||||
(
|
(
|
||||||
`user_name` Nullable(String),
|
`user_name` Nullable(String),
|
||||||
`role_name` Nullable(String),
|
`role_name` Nullable(String),
|
||||||
`access_type` Enum16('SHOW DATABASES' = 0, 'SHOW TABLES' = 1, 'SHOW COLUMNS' = 2, 'SHOW DICTIONARIES' = 3, 'SHOW' = 4, 'SHOW FILESYSTEM CACHES' = 5, 'SELECT' = 6, 'INSERT' = 7, 'ALTER UPDATE' = 8, 'ALTER DELETE' = 9, 'ALTER ADD COLUMN' = 10, 'ALTER MODIFY COLUMN' = 11, 'ALTER DROP COLUMN' = 12, 'ALTER COMMENT COLUMN' = 13, 'ALTER CLEAR COLUMN' = 14, 'ALTER RENAME COLUMN' = 15, 'ALTER MATERIALIZE COLUMN' = 16, 'ALTER COLUMN' = 17, 'ALTER MODIFY COMMENT' = 18, 'ALTER ORDER BY' = 19, 'ALTER SAMPLE BY' = 20, 'ALTER ADD INDEX' = 21, 'ALTER DROP INDEX' = 22, 'ALTER MATERIALIZE INDEX' = 23, 'ALTER CLEAR INDEX' = 24, 'ALTER INDEX' = 25, 'ALTER ADD PROJECTION' = 26, 'ALTER DROP PROJECTION' = 27, 'ALTER MATERIALIZE PROJECTION' = 28, 'ALTER CLEAR PROJECTION' = 29, 'ALTER PROJECTION' = 30, 'ALTER ADD CONSTRAINT' = 31, 'ALTER DROP CONSTRAINT' = 32, 'ALTER CONSTRAINT' = 33, 'ALTER TTL' = 34, 'ALTER MATERIALIZE TTL' = 35, 'ALTER SETTINGS' = 36, 'ALTER MOVE PARTITION' = 37, 'ALTER FETCH PARTITION' = 38, 'ALTER FREEZE PARTITION' = 39, 'ALTER DATABASE SETTINGS' = 40, 'ALTER TABLE' = 41, 'ALTER DATABASE' = 42, 'ALTER VIEW REFRESH' = 43, 'ALTER VIEW MODIFY QUERY' = 44, 'ALTER VIEW' = 45, 'ALTER' = 46, 'CREATE DATABASE' = 47, 'CREATE TABLE' = 48, 'CREATE VIEW' = 49, 'CREATE DICTIONARY' = 50, 'CREATE TEMPORARY TABLE' = 51, 'CREATE FUNCTION' = 52, 'CREATE' = 53, 'DROP DATABASE' = 54, 'DROP TABLE' = 55, 'DROP VIEW' = 56, 'DROP DICTIONARY' = 57, 'DROP FUNCTION' = 58, 'DROP' = 59, 'TRUNCATE' = 60, 'OPTIMIZE' = 61, 'BACKUP' = 62, 'KILL QUERY' = 63, 'KILL TRANSACTION' = 64, 'MOVE PARTITION BETWEEN SHARDS' = 65, 'CREATE USER' = 66, 'ALTER USER' = 67, 'DROP USER' = 68, 'CREATE ROLE' = 69, 'ALTER ROLE' = 70, 'DROP ROLE' = 71, 'ROLE ADMIN' = 72, 'CREATE ROW POLICY' = 73, 'ALTER ROW POLICY' = 74, 'DROP ROW POLICY' = 75, 'CREATE QUOTA' = 76, 'ALTER QUOTA' = 77, 'DROP QUOTA' = 78, 'CREATE SETTINGS PROFILE' = 79, 'ALTER SETTINGS PROFILE' = 80, 'DROP SETTINGS PROFILE' = 81, 'SHOW USERS' = 82, 'SHOW ROLES' = 83, 'SHOW ROW POLICIES' = 84, 'SHOW QUOTAS' = 85, 'SHOW SETTINGS PROFILES' = 86, 'SHOW ACCESS' = 87, 'SHOW NAMED COLLECTIONS' = 88, 'ACCESS MANAGEMENT' = 89, 'SYSTEM SHUTDOWN' = 90, 'SYSTEM DROP DNS CACHE' = 91, 'SYSTEM DROP MARK CACHE' = 92, 'SYSTEM DROP UNCOMPRESSED CACHE' = 93, 'SYSTEM DROP MMAP CACHE' = 94, 'SYSTEM DROP COMPILED EXPRESSION CACHE' = 95, 'SYSTEM DROP FILESYSTEM CACHE' = 96, 'SYSTEM DROP SCHEMA CACHE' = 97, 'SYSTEM DROP CACHE' = 98, 'SYSTEM RELOAD CONFIG' = 99, 'SYSTEM RELOAD USERS' = 100, 'SYSTEM RELOAD SYMBOLS' = 101, 'SYSTEM RELOAD DICTIONARY' = 102, 'SYSTEM RELOAD MODEL' = 103, 'SYSTEM RELOAD FUNCTION' = 104, 'SYSTEM RELOAD EMBEDDED DICTIONARIES' = 105, 'SYSTEM RELOAD' = 106, 'SYSTEM RESTART DISK' = 107, 'SYSTEM MERGES' = 108, 'SYSTEM TTL MERGES' = 109, 'SYSTEM FETCHES' = 110, 'SYSTEM MOVES' = 111, 'SYSTEM DISTRIBUTED SENDS' = 112, 'SYSTEM REPLICATED SENDS' = 113, 'SYSTEM SENDS' = 114, 'SYSTEM REPLICATION QUEUES' = 115, 'SYSTEM DROP REPLICA' = 116, 'SYSTEM SYNC REPLICA' = 117, 'SYSTEM RESTART REPLICA' = 118, 'SYSTEM RESTORE REPLICA' = 119, 'SYSTEM SYNC DATABASE REPLICA' = 120, 'SYSTEM SYNC TRANSACTION LOG' = 121, 'SYSTEM FLUSH DISTRIBUTED' = 122, 'SYSTEM FLUSH LOGS' = 123, 'SYSTEM FLUSH' = 124, 'SYSTEM THREAD FUZZER' = 125, 'SYSTEM UNFREEZE' = 126, 'SYSTEM' = 127, 'dictGet' = 128, 'addressToLine' = 129, 'addressToLineWithInlines' = 130, 'addressToSymbol' = 131, 'demangle' = 132, 'INTROSPECTION' = 133, 'FILE' = 134, 'URL' = 135, 'REMOTE' = 136, 'MONGO' = 137, 'MEILISEARCH' = 138, 'MYSQL' = 139, 'POSTGRES' = 140, 'SQLITE' = 141, 'ODBC' = 142, 'JDBC' = 143, 'HDFS' = 144, 'S3' = 145, 'HIVE' = 146, 'SOURCES' = 147, 'CLUSTER' = 148, 'ALL' = 149, 'NONE' = 150),
|
`access_type` Enum16('SHOW DATABASES' = 0, 'SHOW TABLES' = 1, 'SHOW COLUMNS' = 2, 'SHOW DICTIONARIES' = 3, 'SHOW' = 4, 'SHOW FILESYSTEM CACHES' = 5, 'SELECT' = 6, 'INSERT' = 7, 'ALTER UPDATE' = 8, 'ALTER DELETE' = 9, 'ALTER ADD COLUMN' = 10, 'ALTER MODIFY COLUMN' = 11, 'ALTER DROP COLUMN' = 12, 'ALTER COMMENT COLUMN' = 13, 'ALTER CLEAR COLUMN' = 14, 'ALTER RENAME COLUMN' = 15, 'ALTER MATERIALIZE COLUMN' = 16, 'ALTER COLUMN' = 17, 'ALTER MODIFY COMMENT' = 18, 'ALTER ORDER BY' = 19, 'ALTER SAMPLE BY' = 20, 'ALTER ADD INDEX' = 21, 'ALTER DROP INDEX' = 22, 'ALTER MATERIALIZE INDEX' = 23, 'ALTER CLEAR INDEX' = 24, 'ALTER INDEX' = 25, 'ALTER ADD PROJECTION' = 26, 'ALTER DROP PROJECTION' = 27, 'ALTER MATERIALIZE PROJECTION' = 28, 'ALTER CLEAR PROJECTION' = 29, 'ALTER PROJECTION' = 30, 'ALTER ADD CONSTRAINT' = 31, 'ALTER DROP CONSTRAINT' = 32, 'ALTER CONSTRAINT' = 33, 'ALTER TTL' = 34, 'ALTER MATERIALIZE TTL' = 35, 'ALTER SETTINGS' = 36, 'ALTER MOVE PARTITION' = 37, 'ALTER FETCH PARTITION' = 38, 'ALTER FREEZE PARTITION' = 39, 'ALTER DATABASE SETTINGS' = 40, 'ALTER NAMED COLLECTION' = 41, 'ALTER TABLE' = 42, 'ALTER DATABASE' = 43, 'ALTER VIEW REFRESH' = 44, 'ALTER VIEW MODIFY QUERY' = 45, 'ALTER VIEW' = 46, 'ALTER' = 47, 'CREATE DATABASE' = 48, 'CREATE TABLE' = 49, 'CREATE VIEW' = 50, 'CREATE DICTIONARY' = 51, 'CREATE TEMPORARY TABLE' = 52, 'CREATE FUNCTION' = 53, 'CREATE NAMED COLLECTION' = 54, 'CREATE' = 55, 'DROP DATABASE' = 56, 'DROP TABLE' = 57, 'DROP VIEW' = 58, 'DROP DICTIONARY' = 59, 'DROP FUNCTION' = 60, 'DROP NAMED COLLECTION' = 61, 'DROP' = 62, 'TRUNCATE' = 63, 'OPTIMIZE' = 64, 'BACKUP' = 65, 'KILL QUERY' = 66, 'KILL TRANSACTION' = 67, 'MOVE PARTITION BETWEEN SHARDS' = 68, 'CREATE USER' = 69, 'ALTER USER' = 70, 'DROP USER' = 71, 'CREATE ROLE' = 72, 'ALTER ROLE' = 73, 'DROP ROLE' = 74, 'ROLE ADMIN' = 75, 'CREATE ROW POLICY' = 76, 'ALTER ROW POLICY' = 77, 'DROP ROW POLICY' = 78, 'CREATE QUOTA' = 79, 'ALTER QUOTA' = 80, 'DROP QUOTA' = 81, 'CREATE SETTINGS PROFILE' = 82, 'ALTER SETTINGS PROFILE' = 83, 'DROP SETTINGS PROFILE' = 84, 'SHOW USERS' = 85, 'SHOW ROLES' = 86, 'SHOW ROW POLICIES' = 87, 'SHOW QUOTAS' = 88, 'SHOW SETTINGS PROFILES' = 89, 'SHOW ACCESS' = 90, 'SHOW NAMED COLLECTIONS' = 91, 'ACCESS MANAGEMENT' = 92, 'SYSTEM SHUTDOWN' = 93, 'SYSTEM DROP DNS CACHE' = 94, 'SYSTEM DROP MARK CACHE' = 95, 'SYSTEM DROP UNCOMPRESSED CACHE' = 96, 'SYSTEM DROP MMAP CACHE' = 97, 'SYSTEM DROP COMPILED EXPRESSION CACHE' = 98, 'SYSTEM DROP FILESYSTEM CACHE' = 99, 'SYSTEM DROP SCHEMA CACHE' = 100, 'SYSTEM DROP CACHE' = 101, 'SYSTEM RELOAD CONFIG' = 102, 'SYSTEM RELOAD USERS' = 103, 'SYSTEM RELOAD SYMBOLS' = 104, 'SYSTEM RELOAD DICTIONARY' = 105, 'SYSTEM RELOAD MODEL' = 106, 'SYSTEM RELOAD FUNCTION' = 107, 'SYSTEM RELOAD EMBEDDED DICTIONARIES' = 108, 'SYSTEM RELOAD' = 109, 'SYSTEM RESTART DISK' = 110, 'SYSTEM MERGES' = 111, 'SYSTEM TTL MERGES' = 112, 'SYSTEM FETCHES' = 113, 'SYSTEM MOVES' = 114, 'SYSTEM DISTRIBUTED SENDS' = 115, 'SYSTEM REPLICATED SENDS' = 116, 'SYSTEM SENDS' = 117, 'SYSTEM REPLICATION QUEUES' = 118, 'SYSTEM DROP REPLICA' = 119, 'SYSTEM SYNC REPLICA' = 120, 'SYSTEM RESTART REPLICA' = 121, 'SYSTEM RESTORE REPLICA' = 122, 'SYSTEM SYNC DATABASE REPLICA' = 123, 'SYSTEM SYNC TRANSACTION LOG' = 124, 'SYSTEM FLUSH DISTRIBUTED' = 125, 'SYSTEM FLUSH LOGS' = 126, 'SYSTEM FLUSH' = 127, 'SYSTEM THREAD FUZZER' = 128, 'SYSTEM UNFREEZE' = 129, 'SYSTEM' = 130, 'dictGet' = 131, 'addressToLine' = 132, 'addressToLineWithInlines' = 133, 'addressToSymbol' = 134, 'demangle' = 135, 'INTROSPECTION' = 136, 'FILE' = 137, 'URL' = 138, 'REMOTE' = 139, 'MONGO' = 140, 'MEILISEARCH' = 141, 'MYSQL' = 142, 'POSTGRES' = 143, 'SQLITE' = 144, 'ODBC' = 145, 'JDBC' = 146, 'HDFS' = 147, 'S3' = 148, 'HIVE' = 149, 'SOURCES' = 150, 'CLUSTER' = 151, 'ALL' = 152, 'NONE' = 153),
|
||||||
`database` Nullable(String),
|
`database` Nullable(String),
|
||||||
`table` Nullable(String),
|
`table` Nullable(String),
|
||||||
`column` Nullable(String),
|
`column` Nullable(String),
|
||||||
@ -560,10 +560,10 @@ ENGINE = SystemPartsColumns
|
|||||||
COMMENT 'SYSTEM TABLE is built on the fly.'
|
COMMENT 'SYSTEM TABLE is built on the fly.'
|
||||||
CREATE TABLE system.privileges
|
CREATE TABLE system.privileges
|
||||||
(
|
(
|
||||||
`privilege` Enum16('SHOW DATABASES' = 0, 'SHOW TABLES' = 1, 'SHOW COLUMNS' = 2, 'SHOW DICTIONARIES' = 3, 'SHOW' = 4, 'SHOW FILESYSTEM CACHES' = 5, 'SELECT' = 6, 'INSERT' = 7, 'ALTER UPDATE' = 8, 'ALTER DELETE' = 9, 'ALTER ADD COLUMN' = 10, 'ALTER MODIFY COLUMN' = 11, 'ALTER DROP COLUMN' = 12, 'ALTER COMMENT COLUMN' = 13, 'ALTER CLEAR COLUMN' = 14, 'ALTER RENAME COLUMN' = 15, 'ALTER MATERIALIZE COLUMN' = 16, 'ALTER COLUMN' = 17, 'ALTER MODIFY COMMENT' = 18, 'ALTER ORDER BY' = 19, 'ALTER SAMPLE BY' = 20, 'ALTER ADD INDEX' = 21, 'ALTER DROP INDEX' = 22, 'ALTER MATERIALIZE INDEX' = 23, 'ALTER CLEAR INDEX' = 24, 'ALTER INDEX' = 25, 'ALTER ADD PROJECTION' = 26, 'ALTER DROP PROJECTION' = 27, 'ALTER MATERIALIZE PROJECTION' = 28, 'ALTER CLEAR PROJECTION' = 29, 'ALTER PROJECTION' = 30, 'ALTER ADD CONSTRAINT' = 31, 'ALTER DROP CONSTRAINT' = 32, 'ALTER CONSTRAINT' = 33, 'ALTER TTL' = 34, 'ALTER MATERIALIZE TTL' = 35, 'ALTER SETTINGS' = 36, 'ALTER MOVE PARTITION' = 37, 'ALTER FETCH PARTITION' = 38, 'ALTER FREEZE PARTITION' = 39, 'ALTER DATABASE SETTINGS' = 40, 'ALTER TABLE' = 41, 'ALTER DATABASE' = 42, 'ALTER VIEW REFRESH' = 43, 'ALTER VIEW MODIFY QUERY' = 44, 'ALTER VIEW' = 45, 'ALTER' = 46, 'CREATE DATABASE' = 47, 'CREATE TABLE' = 48, 'CREATE VIEW' = 49, 'CREATE DICTIONARY' = 50, 'CREATE TEMPORARY TABLE' = 51, 'CREATE FUNCTION' = 52, 'CREATE' = 53, 'DROP DATABASE' = 54, 'DROP TABLE' = 55, 'DROP VIEW' = 56, 'DROP DICTIONARY' = 57, 'DROP FUNCTION' = 58, 'DROP' = 59, 'TRUNCATE' = 60, 'OPTIMIZE' = 61, 'BACKUP' = 62, 'KILL QUERY' = 63, 'KILL TRANSACTION' = 64, 'MOVE PARTITION BETWEEN SHARDS' = 65, 'CREATE USER' = 66, 'ALTER USER' = 67, 'DROP USER' = 68, 'CREATE ROLE' = 69, 'ALTER ROLE' = 70, 'DROP ROLE' = 71, 'ROLE ADMIN' = 72, 'CREATE ROW POLICY' = 73, 'ALTER ROW POLICY' = 74, 'DROP ROW POLICY' = 75, 'CREATE QUOTA' = 76, 'ALTER QUOTA' = 77, 'DROP QUOTA' = 78, 'CREATE SETTINGS PROFILE' = 79, 'ALTER SETTINGS PROFILE' = 80, 'DROP SETTINGS PROFILE' = 81, 'SHOW USERS' = 82, 'SHOW ROLES' = 83, 'SHOW ROW POLICIES' = 84, 'SHOW QUOTAS' = 85, 'SHOW SETTINGS PROFILES' = 86, 'SHOW ACCESS' = 87, 'SHOW NAMED COLLECTIONS' = 88, 'ACCESS MANAGEMENT' = 89, 'SYSTEM SHUTDOWN' = 90, 'SYSTEM DROP DNS CACHE' = 91, 'SYSTEM DROP MARK CACHE' = 92, 'SYSTEM DROP UNCOMPRESSED CACHE' = 93, 'SYSTEM DROP MMAP CACHE' = 94, 'SYSTEM DROP COMPILED EXPRESSION CACHE' = 95, 'SYSTEM DROP FILESYSTEM CACHE' = 96, 'SYSTEM DROP SCHEMA CACHE' = 97, 'SYSTEM DROP CACHE' = 98, 'SYSTEM RELOAD CONFIG' = 99, 'SYSTEM RELOAD USERS' = 100, 'SYSTEM RELOAD SYMBOLS' = 101, 'SYSTEM RELOAD DICTIONARY' = 102, 'SYSTEM RELOAD MODEL' = 103, 'SYSTEM RELOAD FUNCTION' = 104, 'SYSTEM RELOAD EMBEDDED DICTIONARIES' = 105, 'SYSTEM RELOAD' = 106, 'SYSTEM RESTART DISK' = 107, 'SYSTEM MERGES' = 108, 'SYSTEM TTL MERGES' = 109, 'SYSTEM FETCHES' = 110, 'SYSTEM MOVES' = 111, 'SYSTEM DISTRIBUTED SENDS' = 112, 'SYSTEM REPLICATED SENDS' = 113, 'SYSTEM SENDS' = 114, 'SYSTEM REPLICATION QUEUES' = 115, 'SYSTEM DROP REPLICA' = 116, 'SYSTEM SYNC REPLICA' = 117, 'SYSTEM RESTART REPLICA' = 118, 'SYSTEM RESTORE REPLICA' = 119, 'SYSTEM SYNC DATABASE REPLICA' = 120, 'SYSTEM SYNC TRANSACTION LOG' = 121, 'SYSTEM FLUSH DISTRIBUTED' = 122, 'SYSTEM FLUSH LOGS' = 123, 'SYSTEM FLUSH' = 124, 'SYSTEM THREAD FUZZER' = 125, 'SYSTEM UNFREEZE' = 126, 'SYSTEM' = 127, 'dictGet' = 128, 'addressToLine' = 129, 'addressToLineWithInlines' = 130, 'addressToSymbol' = 131, 'demangle' = 132, 'INTROSPECTION' = 133, 'FILE' = 134, 'URL' = 135, 'REMOTE' = 136, 'MONGO' = 137, 'MEILISEARCH' = 138, 'MYSQL' = 139, 'POSTGRES' = 140, 'SQLITE' = 141, 'ODBC' = 142, 'JDBC' = 143, 'HDFS' = 144, 'S3' = 145, 'HIVE' = 146, 'SOURCES' = 147, 'CLUSTER' = 148, 'ALL' = 149, 'NONE' = 150),
|
`privilege` Enum16('SHOW DATABASES' = 0, 'SHOW TABLES' = 1, 'SHOW COLUMNS' = 2, 'SHOW DICTIONARIES' = 3, 'SHOW' = 4, 'SHOW FILESYSTEM CACHES' = 5, 'SELECT' = 6, 'INSERT' = 7, 'ALTER UPDATE' = 8, 'ALTER DELETE' = 9, 'ALTER ADD COLUMN' = 10, 'ALTER MODIFY COLUMN' = 11, 'ALTER DROP COLUMN' = 12, 'ALTER COMMENT COLUMN' = 13, 'ALTER CLEAR COLUMN' = 14, 'ALTER RENAME COLUMN' = 15, 'ALTER MATERIALIZE COLUMN' = 16, 'ALTER COLUMN' = 17, 'ALTER MODIFY COMMENT' = 18, 'ALTER ORDER BY' = 19, 'ALTER SAMPLE BY' = 20, 'ALTER ADD INDEX' = 21, 'ALTER DROP INDEX' = 22, 'ALTER MATERIALIZE INDEX' = 23, 'ALTER CLEAR INDEX' = 24, 'ALTER INDEX' = 25, 'ALTER ADD PROJECTION' = 26, 'ALTER DROP PROJECTION' = 27, 'ALTER MATERIALIZE PROJECTION' = 28, 'ALTER CLEAR PROJECTION' = 29, 'ALTER PROJECTION' = 30, 'ALTER ADD CONSTRAINT' = 31, 'ALTER DROP CONSTRAINT' = 32, 'ALTER CONSTRAINT' = 33, 'ALTER TTL' = 34, 'ALTER MATERIALIZE TTL' = 35, 'ALTER SETTINGS' = 36, 'ALTER MOVE PARTITION' = 37, 'ALTER FETCH PARTITION' = 38, 'ALTER FREEZE PARTITION' = 39, 'ALTER DATABASE SETTINGS' = 40, 'ALTER NAMED COLLECTION' = 41, 'ALTER TABLE' = 42, 'ALTER DATABASE' = 43, 'ALTER VIEW REFRESH' = 44, 'ALTER VIEW MODIFY QUERY' = 45, 'ALTER VIEW' = 46, 'ALTER' = 47, 'CREATE DATABASE' = 48, 'CREATE TABLE' = 49, 'CREATE VIEW' = 50, 'CREATE DICTIONARY' = 51, 'CREATE TEMPORARY TABLE' = 52, 'CREATE FUNCTION' = 53, 'CREATE NAMED COLLECTION' = 54, 'CREATE' = 55, 'DROP DATABASE' = 56, 'DROP TABLE' = 57, 'DROP VIEW' = 58, 'DROP DICTIONARY' = 59, 'DROP FUNCTION' = 60, 'DROP NAMED COLLECTION' = 61, 'DROP' = 62, 'TRUNCATE' = 63, 'OPTIMIZE' = 64, 'BACKUP' = 65, 'KILL QUERY' = 66, 'KILL TRANSACTION' = 67, 'MOVE PARTITION BETWEEN SHARDS' = 68, 'CREATE USER' = 69, 'ALTER USER' = 70, 'DROP USER' = 71, 'CREATE ROLE' = 72, 'ALTER ROLE' = 73, 'DROP ROLE' = 74, 'ROLE ADMIN' = 75, 'CREATE ROW POLICY' = 76, 'ALTER ROW POLICY' = 77, 'DROP ROW POLICY' = 78, 'CREATE QUOTA' = 79, 'ALTER QUOTA' = 80, 'DROP QUOTA' = 81, 'CREATE SETTINGS PROFILE' = 82, 'ALTER SETTINGS PROFILE' = 83, 'DROP SETTINGS PROFILE' = 84, 'SHOW USERS' = 85, 'SHOW ROLES' = 86, 'SHOW ROW POLICIES' = 87, 'SHOW QUOTAS' = 88, 'SHOW SETTINGS PROFILES' = 89, 'SHOW ACCESS' = 90, 'SHOW NAMED COLLECTIONS' = 91, 'ACCESS MANAGEMENT' = 92, 'SYSTEM SHUTDOWN' = 93, 'SYSTEM DROP DNS CACHE' = 94, 'SYSTEM DROP MARK CACHE' = 95, 'SYSTEM DROP UNCOMPRESSED CACHE' = 96, 'SYSTEM DROP MMAP CACHE' = 97, 'SYSTEM DROP COMPILED EXPRESSION CACHE' = 98, 'SYSTEM DROP FILESYSTEM CACHE' = 99, 'SYSTEM DROP SCHEMA CACHE' = 100, 'SYSTEM DROP CACHE' = 101, 'SYSTEM RELOAD CONFIG' = 102, 'SYSTEM RELOAD USERS' = 103, 'SYSTEM RELOAD SYMBOLS' = 104, 'SYSTEM RELOAD DICTIONARY' = 105, 'SYSTEM RELOAD MODEL' = 106, 'SYSTEM RELOAD FUNCTION' = 107, 'SYSTEM RELOAD EMBEDDED DICTIONARIES' = 108, 'SYSTEM RELOAD' = 109, 'SYSTEM RESTART DISK' = 110, 'SYSTEM MERGES' = 111, 'SYSTEM TTL MERGES' = 112, 'SYSTEM FETCHES' = 113, 'SYSTEM MOVES' = 114, 'SYSTEM DISTRIBUTED SENDS' = 115, 'SYSTEM REPLICATED SENDS' = 116, 'SYSTEM SENDS' = 117, 'SYSTEM REPLICATION QUEUES' = 118, 'SYSTEM DROP REPLICA' = 119, 'SYSTEM SYNC REPLICA' = 120, 'SYSTEM RESTART REPLICA' = 121, 'SYSTEM RESTORE REPLICA' = 122, 'SYSTEM SYNC DATABASE REPLICA' = 123, 'SYSTEM SYNC TRANSACTION LOG' = 124, 'SYSTEM FLUSH DISTRIBUTED' = 125, 'SYSTEM FLUSH LOGS' = 126, 'SYSTEM FLUSH' = 127, 'SYSTEM THREAD FUZZER' = 128, 'SYSTEM UNFREEZE' = 129, 'SYSTEM' = 130, 'dictGet' = 131, 'addressToLine' = 132, 'addressToLineWithInlines' = 133, 'addressToSymbol' = 134, 'demangle' = 135, 'INTROSPECTION' = 136, 'FILE' = 137, 'URL' = 138, 'REMOTE' = 139, 'MONGO' = 140, 'MEILISEARCH' = 141, 'MYSQL' = 142, 'POSTGRES' = 143, 'SQLITE' = 144, 'ODBC' = 145, 'JDBC' = 146, 'HDFS' = 147, 'S3' = 148, 'HIVE' = 149, 'SOURCES' = 150, 'CLUSTER' = 151, 'ALL' = 152, 'NONE' = 153),
|
||||||
`aliases` Array(String),
|
`aliases` Array(String),
|
||||||
`level` Nullable(Enum8('GLOBAL' = 0, 'DATABASE' = 1, 'TABLE' = 2, 'DICTIONARY' = 3, 'VIEW' = 4, 'COLUMN' = 5)),
|
`level` Nullable(Enum8('GLOBAL' = 0, 'DATABASE' = 1, 'TABLE' = 2, 'DICTIONARY' = 3, 'VIEW' = 4, 'COLUMN' = 5)),
|
||||||
`parent_group` Nullable(Enum16('SHOW DATABASES' = 0, 'SHOW TABLES' = 1, 'SHOW COLUMNS' = 2, 'SHOW DICTIONARIES' = 3, 'SHOW' = 4, 'SHOW FILESYSTEM CACHES' = 5, 'SELECT' = 6, 'INSERT' = 7, 'ALTER UPDATE' = 8, 'ALTER DELETE' = 9, 'ALTER ADD COLUMN' = 10, 'ALTER MODIFY COLUMN' = 11, 'ALTER DROP COLUMN' = 12, 'ALTER COMMENT COLUMN' = 13, 'ALTER CLEAR COLUMN' = 14, 'ALTER RENAME COLUMN' = 15, 'ALTER MATERIALIZE COLUMN' = 16, 'ALTER COLUMN' = 17, 'ALTER MODIFY COMMENT' = 18, 'ALTER ORDER BY' = 19, 'ALTER SAMPLE BY' = 20, 'ALTER ADD INDEX' = 21, 'ALTER DROP INDEX' = 22, 'ALTER MATERIALIZE INDEX' = 23, 'ALTER CLEAR INDEX' = 24, 'ALTER INDEX' = 25, 'ALTER ADD PROJECTION' = 26, 'ALTER DROP PROJECTION' = 27, 'ALTER MATERIALIZE PROJECTION' = 28, 'ALTER CLEAR PROJECTION' = 29, 'ALTER PROJECTION' = 30, 'ALTER ADD CONSTRAINT' = 31, 'ALTER DROP CONSTRAINT' = 32, 'ALTER CONSTRAINT' = 33, 'ALTER TTL' = 34, 'ALTER MATERIALIZE TTL' = 35, 'ALTER SETTINGS' = 36, 'ALTER MOVE PARTITION' = 37, 'ALTER FETCH PARTITION' = 38, 'ALTER FREEZE PARTITION' = 39, 'ALTER DATABASE SETTINGS' = 40, 'ALTER TABLE' = 41, 'ALTER DATABASE' = 42, 'ALTER VIEW REFRESH' = 43, 'ALTER VIEW MODIFY QUERY' = 44, 'ALTER VIEW' = 45, 'ALTER' = 46, 'CREATE DATABASE' = 47, 'CREATE TABLE' = 48, 'CREATE VIEW' = 49, 'CREATE DICTIONARY' = 50, 'CREATE TEMPORARY TABLE' = 51, 'CREATE FUNCTION' = 52, 'CREATE' = 53, 'DROP DATABASE' = 54, 'DROP TABLE' = 55, 'DROP VIEW' = 56, 'DROP DICTIONARY' = 57, 'DROP FUNCTION' = 58, 'DROP' = 59, 'TRUNCATE' = 60, 'OPTIMIZE' = 61, 'BACKUP' = 62, 'KILL QUERY' = 63, 'KILL TRANSACTION' = 64, 'MOVE PARTITION BETWEEN SHARDS' = 65, 'CREATE USER' = 66, 'ALTER USER' = 67, 'DROP USER' = 68, 'CREATE ROLE' = 69, 'ALTER ROLE' = 70, 'DROP ROLE' = 71, 'ROLE ADMIN' = 72, 'CREATE ROW POLICY' = 73, 'ALTER ROW POLICY' = 74, 'DROP ROW POLICY' = 75, 'CREATE QUOTA' = 76, 'ALTER QUOTA' = 77, 'DROP QUOTA' = 78, 'CREATE SETTINGS PROFILE' = 79, 'ALTER SETTINGS PROFILE' = 80, 'DROP SETTINGS PROFILE' = 81, 'SHOW USERS' = 82, 'SHOW ROLES' = 83, 'SHOW ROW POLICIES' = 84, 'SHOW QUOTAS' = 85, 'SHOW SETTINGS PROFILES' = 86, 'SHOW ACCESS' = 87, 'SHOW NAMED COLLECTIONS' = 88, 'ACCESS MANAGEMENT' = 89, 'SYSTEM SHUTDOWN' = 90, 'SYSTEM DROP DNS CACHE' = 91, 'SYSTEM DROP MARK CACHE' = 92, 'SYSTEM DROP UNCOMPRESSED CACHE' = 93, 'SYSTEM DROP MMAP CACHE' = 94, 'SYSTEM DROP COMPILED EXPRESSION CACHE' = 95, 'SYSTEM DROP FILESYSTEM CACHE' = 96, 'SYSTEM DROP SCHEMA CACHE' = 97, 'SYSTEM DROP CACHE' = 98, 'SYSTEM RELOAD CONFIG' = 99, 'SYSTEM RELOAD USERS' = 100, 'SYSTEM RELOAD SYMBOLS' = 101, 'SYSTEM RELOAD DICTIONARY' = 102, 'SYSTEM RELOAD MODEL' = 103, 'SYSTEM RELOAD FUNCTION' = 104, 'SYSTEM RELOAD EMBEDDED DICTIONARIES' = 105, 'SYSTEM RELOAD' = 106, 'SYSTEM RESTART DISK' = 107, 'SYSTEM MERGES' = 108, 'SYSTEM TTL MERGES' = 109, 'SYSTEM FETCHES' = 110, 'SYSTEM MOVES' = 111, 'SYSTEM DISTRIBUTED SENDS' = 112, 'SYSTEM REPLICATED SENDS' = 113, 'SYSTEM SENDS' = 114, 'SYSTEM REPLICATION QUEUES' = 115, 'SYSTEM DROP REPLICA' = 116, 'SYSTEM SYNC REPLICA' = 117, 'SYSTEM RESTART REPLICA' = 118, 'SYSTEM RESTORE REPLICA' = 119, 'SYSTEM SYNC DATABASE REPLICA' = 120, 'SYSTEM SYNC TRANSACTION LOG' = 121, 'SYSTEM FLUSH DISTRIBUTED' = 122, 'SYSTEM FLUSH LOGS' = 123, 'SYSTEM FLUSH' = 124, 'SYSTEM THREAD FUZZER' = 125, 'SYSTEM UNFREEZE' = 126, 'SYSTEM' = 127, 'dictGet' = 128, 'addressToLine' = 129, 'addressToLineWithInlines' = 130, 'addressToSymbol' = 131, 'demangle' = 132, 'INTROSPECTION' = 133, 'FILE' = 134, 'URL' = 135, 'REMOTE' = 136, 'MONGO' = 137, 'MEILISEARCH' = 138, 'MYSQL' = 139, 'POSTGRES' = 140, 'SQLITE' = 141, 'ODBC' = 142, 'JDBC' = 143, 'HDFS' = 144, 'S3' = 145, 'HIVE' = 146, 'SOURCES' = 147, 'CLUSTER' = 148, 'ALL' = 149, 'NONE' = 150))
|
`parent_group` Nullable(Enum16('SHOW DATABASES' = 0, 'SHOW TABLES' = 1, 'SHOW COLUMNS' = 2, 'SHOW DICTIONARIES' = 3, 'SHOW' = 4, 'SHOW FILESYSTEM CACHES' = 5, 'SELECT' = 6, 'INSERT' = 7, 'ALTER UPDATE' = 8, 'ALTER DELETE' = 9, 'ALTER ADD COLUMN' = 10, 'ALTER MODIFY COLUMN' = 11, 'ALTER DROP COLUMN' = 12, 'ALTER COMMENT COLUMN' = 13, 'ALTER CLEAR COLUMN' = 14, 'ALTER RENAME COLUMN' = 15, 'ALTER MATERIALIZE COLUMN' = 16, 'ALTER COLUMN' = 17, 'ALTER MODIFY COMMENT' = 18, 'ALTER ORDER BY' = 19, 'ALTER SAMPLE BY' = 20, 'ALTER ADD INDEX' = 21, 'ALTER DROP INDEX' = 22, 'ALTER MATERIALIZE INDEX' = 23, 'ALTER CLEAR INDEX' = 24, 'ALTER INDEX' = 25, 'ALTER ADD PROJECTION' = 26, 'ALTER DROP PROJECTION' = 27, 'ALTER MATERIALIZE PROJECTION' = 28, 'ALTER CLEAR PROJECTION' = 29, 'ALTER PROJECTION' = 30, 'ALTER ADD CONSTRAINT' = 31, 'ALTER DROP CONSTRAINT' = 32, 'ALTER CONSTRAINT' = 33, 'ALTER TTL' = 34, 'ALTER MATERIALIZE TTL' = 35, 'ALTER SETTINGS' = 36, 'ALTER MOVE PARTITION' = 37, 'ALTER FETCH PARTITION' = 38, 'ALTER FREEZE PARTITION' = 39, 'ALTER DATABASE SETTINGS' = 40, 'ALTER NAMED COLLECTION' = 41, 'ALTER TABLE' = 42, 'ALTER DATABASE' = 43, 'ALTER VIEW REFRESH' = 44, 'ALTER VIEW MODIFY QUERY' = 45, 'ALTER VIEW' = 46, 'ALTER' = 47, 'CREATE DATABASE' = 48, 'CREATE TABLE' = 49, 'CREATE VIEW' = 50, 'CREATE DICTIONARY' = 51, 'CREATE TEMPORARY TABLE' = 52, 'CREATE FUNCTION' = 53, 'CREATE NAMED COLLECTION' = 54, 'CREATE' = 55, 'DROP DATABASE' = 56, 'DROP TABLE' = 57, 'DROP VIEW' = 58, 'DROP DICTIONARY' = 59, 'DROP FUNCTION' = 60, 'DROP NAMED COLLECTION' = 61, 'DROP' = 62, 'TRUNCATE' = 63, 'OPTIMIZE' = 64, 'BACKUP' = 65, 'KILL QUERY' = 66, 'KILL TRANSACTION' = 67, 'MOVE PARTITION BETWEEN SHARDS' = 68, 'CREATE USER' = 69, 'ALTER USER' = 70, 'DROP USER' = 71, 'CREATE ROLE' = 72, 'ALTER ROLE' = 73, 'DROP ROLE' = 74, 'ROLE ADMIN' = 75, 'CREATE ROW POLICY' = 76, 'ALTER ROW POLICY' = 77, 'DROP ROW POLICY' = 78, 'CREATE QUOTA' = 79, 'ALTER QUOTA' = 80, 'DROP QUOTA' = 81, 'CREATE SETTINGS PROFILE' = 82, 'ALTER SETTINGS PROFILE' = 83, 'DROP SETTINGS PROFILE' = 84, 'SHOW USERS' = 85, 'SHOW ROLES' = 86, 'SHOW ROW POLICIES' = 87, 'SHOW QUOTAS' = 88, 'SHOW SETTINGS PROFILES' = 89, 'SHOW ACCESS' = 90, 'SHOW NAMED COLLECTIONS' = 91, 'ACCESS MANAGEMENT' = 92, 'SYSTEM SHUTDOWN' = 93, 'SYSTEM DROP DNS CACHE' = 94, 'SYSTEM DROP MARK CACHE' = 95, 'SYSTEM DROP UNCOMPRESSED CACHE' = 96, 'SYSTEM DROP MMAP CACHE' = 97, 'SYSTEM DROP COMPILED EXPRESSION CACHE' = 98, 'SYSTEM DROP FILESYSTEM CACHE' = 99, 'SYSTEM DROP SCHEMA CACHE' = 100, 'SYSTEM DROP CACHE' = 101, 'SYSTEM RELOAD CONFIG' = 102, 'SYSTEM RELOAD USERS' = 103, 'SYSTEM RELOAD SYMBOLS' = 104, 'SYSTEM RELOAD DICTIONARY' = 105, 'SYSTEM RELOAD MODEL' = 106, 'SYSTEM RELOAD FUNCTION' = 107, 'SYSTEM RELOAD EMBEDDED DICTIONARIES' = 108, 'SYSTEM RELOAD' = 109, 'SYSTEM RESTART DISK' = 110, 'SYSTEM MERGES' = 111, 'SYSTEM TTL MERGES' = 112, 'SYSTEM FETCHES' = 113, 'SYSTEM MOVES' = 114, 'SYSTEM DISTRIBUTED SENDS' = 115, 'SYSTEM REPLICATED SENDS' = 116, 'SYSTEM SENDS' = 117, 'SYSTEM REPLICATION QUEUES' = 118, 'SYSTEM DROP REPLICA' = 119, 'SYSTEM SYNC REPLICA' = 120, 'SYSTEM RESTART REPLICA' = 121, 'SYSTEM RESTORE REPLICA' = 122, 'SYSTEM SYNC DATABASE REPLICA' = 123, 'SYSTEM SYNC TRANSACTION LOG' = 124, 'SYSTEM FLUSH DISTRIBUTED' = 125, 'SYSTEM FLUSH LOGS' = 126, 'SYSTEM FLUSH' = 127, 'SYSTEM THREAD FUZZER' = 128, 'SYSTEM UNFREEZE' = 129, 'SYSTEM' = 130, 'dictGet' = 131, 'addressToLine' = 132, 'addressToLineWithInlines' = 133, 'addressToSymbol' = 134, 'demangle' = 135, 'INTROSPECTION' = 136, 'FILE' = 137, 'URL' = 138, 'REMOTE' = 139, 'MONGO' = 140, 'MEILISEARCH' = 141, 'MYSQL' = 142, 'POSTGRES' = 143, 'SQLITE' = 144, 'ODBC' = 145, 'JDBC' = 146, 'HDFS' = 147, 'S3' = 148, 'HIVE' = 149, 'SOURCES' = 150, 'CLUSTER' = 151, 'ALL' = 152, 'NONE' = 153))
|
||||||
)
|
)
|
||||||
ENGINE = SystemPrivileges
|
ENGINE = SystemPrivileges
|
||||||
COMMENT 'SYSTEM TABLE is built on the fly.'
|
COMMENT 'SYSTEM TABLE is built on the fly.'
|
||||||
|
Loading…
Reference in New Issue
Block a user