2015-04-16 06:12:35 +00:00
|
|
|
|
#include <map>
|
|
|
|
|
#include <set>
|
2015-05-07 10:31:50 +00:00
|
|
|
|
#include <chrono>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
#include <Poco/Mutex.h>
|
2012-08-17 19:53:11 +00:00
|
|
|
|
#include <Poco/File.h>
|
2015-07-25 09:49:09 +00:00
|
|
|
|
#include <Poco/UUIDGenerator.h>
|
2012-08-17 19:53:11 +00:00
|
|
|
|
|
2015-09-29 19:19:54 +00:00
|
|
|
|
#include <common/logger_useful.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
#include <DB/Common/Macros.h>
|
2012-08-17 19:53:11 +00:00
|
|
|
|
#include <DB/Common/escapeForFileName.h>
|
2016-04-09 07:47:08 +00:00
|
|
|
|
#include <DB/Common/Stopwatch.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
#include <DB/DataStreams/FormatFactory.h>
|
|
|
|
|
#include <DB/AggregateFunctions/AggregateFunctionFactory.h>
|
|
|
|
|
#include <DB/TableFunctions/TableFunctionFactory.h>
|
|
|
|
|
#include <DB/Storages/IStorage.h>
|
|
|
|
|
#include <DB/Storages/MarkCache.h>
|
|
|
|
|
#include <DB/Storages/MergeTree/BackgroundProcessingPool.h>
|
2016-01-28 01:00:27 +00:00
|
|
|
|
#include <DB/Storages/MergeTree/ReshardingWorker.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
#include <DB/Storages/MergeTree/MergeList.h>
|
2015-07-16 21:32:51 +00:00
|
|
|
|
#include <DB/Storages/MergeTree/MergeTreeSettings.h>
|
2015-04-17 05:35:53 +00:00
|
|
|
|
#include <DB/Storages/CompressionMethodSelector.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
#include <DB/Interpreters/Settings.h>
|
|
|
|
|
#include <DB/Interpreters/Users.h>
|
|
|
|
|
#include <DB/Interpreters/Quota.h>
|
|
|
|
|
#include <DB/Interpreters/Dictionaries.h>
|
|
|
|
|
#include <DB/Interpreters/ExternalDictionaries.h>
|
|
|
|
|
#include <DB/Interpreters/ProcessList.h>
|
|
|
|
|
#include <DB/Interpreters/Cluster.h>
|
|
|
|
|
#include <DB/Interpreters/InterserverIOHandler.h>
|
|
|
|
|
#include <DB/Interpreters/Compiler.h>
|
2015-06-26 20:48:10 +00:00
|
|
|
|
#include <DB/Interpreters/QueryLog.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
#include <DB/Interpreters/Context.h>
|
2012-08-17 19:53:11 +00:00
|
|
|
|
#include <DB/IO/ReadBufferFromFile.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
#include <DB/IO/UncompressedCache.h>
|
2012-08-17 19:53:11 +00:00
|
|
|
|
#include <DB/Parsers/ASTCreateQuery.h>
|
|
|
|
|
#include <DB/Parsers/ParserCreateQuery.h>
|
2015-04-11 03:10:23 +00:00
|
|
|
|
#include <DB/Parsers/parseQuery.h>
|
2016-03-19 01:18:49 +00:00
|
|
|
|
#include <DB/Databases/IDatabase.h>
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2015-10-05 01:26:43 +00:00
|
|
|
|
#include <DB/Common/ConfigProcessor.h>
|
2015-04-16 06:12:35 +00:00
|
|
|
|
#include <zkutil/ZooKeeper.h>
|
|
|
|
|
|
2014-08-22 01:01:28 +00:00
|
|
|
|
|
2016-12-07 22:49:42 +00:00
|
|
|
|
namespace ProfileEvents
|
|
|
|
|
{
|
|
|
|
|
extern const Event ContextLock;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace CurrentMetrics
|
|
|
|
|
{
|
|
|
|
|
extern const Metric ContextLockWait;
|
2016-12-23 20:23:46 +00:00
|
|
|
|
extern const Metric MemoryTrackingForMerges;
|
2016-12-07 22:49:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
|
namespace ErrorCodes
|
|
|
|
|
{
|
|
|
|
|
extern const int DATABASE_ACCESS_DENIED;
|
|
|
|
|
extern const int UNKNOWN_DATABASE;
|
|
|
|
|
extern const int UNKNOWN_TABLE;
|
|
|
|
|
extern const int TABLE_ALREADY_EXISTS;
|
|
|
|
|
extern const int DATABASE_ALREADY_EXISTS;
|
|
|
|
|
extern const int TABLE_METADATA_DOESNT_EXIST;
|
|
|
|
|
extern const int THERE_IS_NO_SESSION;
|
|
|
|
|
extern const int NO_ELEMENTS_IN_CONFIG;
|
2016-03-21 12:57:12 +00:00
|
|
|
|
extern const int DDL_GUARD_IS_ACTIVE;
|
2016-01-11 21:46:36 +00:00
|
|
|
|
}
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
class TableFunctionFactory;
|
|
|
|
|
|
|
|
|
|
|
2016-11-23 20:41:39 +00:00
|
|
|
|
/** Set of known objects (environment), that could be used in query.
|
|
|
|
|
* Shared (global) part. Order of members (especially, order of destruction) is very important.
|
2015-04-16 06:12:35 +00:00
|
|
|
|
*/
|
|
|
|
|
struct ContextShared
|
|
|
|
|
{
|
2016-11-23 20:41:39 +00:00
|
|
|
|
Logger * log = &Logger::get("Context");
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
2016-11-23 20:41:39 +00:00
|
|
|
|
/// For access of most of shared objects. Recursive mutex.
|
2016-01-17 07:53:58 +00:00
|
|
|
|
mutable Poco::Mutex mutex;
|
2016-11-23 20:41:39 +00:00
|
|
|
|
/// Separate mutex for access of external dictionaries. Separate mutex to avoid locks when server doing request to itself.
|
2016-01-17 07:53:58 +00:00
|
|
|
|
mutable std::mutex external_dictionaries_mutex;
|
2016-11-23 20:41:39 +00:00
|
|
|
|
/// Separate mutex for re-initialization of zookeer session. This operation could take a long time and must not interfere with another operations.
|
2016-01-17 07:53:58 +00:00
|
|
|
|
mutable std::mutex zookeeper_mutex;
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
mutable zkutil::ZooKeeperPtr zookeeper; /// Клиент для ZooKeeper.
|
|
|
|
|
|
|
|
|
|
String interserver_io_host; /// Имя хоста по которым это сервер доступен для других серверов.
|
|
|
|
|
int interserver_io_port; /// и порт,
|
|
|
|
|
|
|
|
|
|
String path; /// Путь к директории с данными, со слешем на конце.
|
|
|
|
|
String tmp_path; /// Путь ко временным файлам, возникающим при обработке запроса.
|
2016-10-24 14:01:24 +00:00
|
|
|
|
String flags_path; ///
|
2015-04-16 06:12:35 +00:00
|
|
|
|
Databases databases; /// Список БД и таблиц в них.
|
|
|
|
|
TableFunctionFactory table_function_factory; /// Табличные функции.
|
|
|
|
|
AggregateFunctionFactory aggregate_function_factory; /// Агрегатные функции.
|
|
|
|
|
FormatFactory format_factory; /// Форматы.
|
2016-05-28 14:14:18 +00:00
|
|
|
|
mutable std::shared_ptr<Dictionaries> dictionaries; /// Словари Метрики. Инициализируются лениво.
|
|
|
|
|
mutable std::shared_ptr<ExternalDictionaries> external_dictionaries;
|
2015-04-16 06:12:35 +00:00
|
|
|
|
Users users; /// Известные пользователи.
|
|
|
|
|
Quotas quotas; /// Известные квоты на использование ресурсов.
|
|
|
|
|
mutable UncompressedCachePtr uncompressed_cache; /// Кэш разжатых блоков.
|
|
|
|
|
mutable MarkCachePtr mark_cache; /// Кэш засечек в сжатых файлах.
|
|
|
|
|
ProcessList process_list; /// Исполняющиеся в данный момент запросы.
|
|
|
|
|
MergeList merge_list; /// Список выполняемых мерджей (для (Replicated)?MergeTree)
|
|
|
|
|
ViewDependencies view_dependencies; /// Текущие зависимости
|
|
|
|
|
ConfigurationPtr users_config; /// Конфиг с секциями users, profiles и quotas.
|
|
|
|
|
InterserverIOHandler interserver_io_handler; /// Обработчик для межсерверной передачи данных.
|
|
|
|
|
BackgroundProcessingPoolPtr background_pool; /// Пул потоков для фоновой работы, выполняемой таблицами.
|
2016-01-28 01:00:27 +00:00
|
|
|
|
ReshardingWorkerPtr resharding_worker;
|
2015-04-16 06:12:35 +00:00
|
|
|
|
Macros macros; /// Подстановки из конфига.
|
|
|
|
|
std::unique_ptr<Compiler> compiler; /// Для динамической компиляции частей запроса, при необходимости.
|
2015-06-26 20:48:10 +00:00
|
|
|
|
std::unique_ptr<QueryLog> query_log; /// Для логгирования запросов.
|
2016-03-21 12:57:12 +00:00
|
|
|
|
/// Правила для выбора метода сжатия в зависимости от размера куска.
|
|
|
|
|
mutable std::unique_ptr<CompressionMethodSelector> compression_method_selector;
|
2015-07-16 21:32:51 +00:00
|
|
|
|
std::unique_ptr<MergeTreeSettings> merge_tree_settings; /// Настройки для движка MergeTree.
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
/// Clusters for distributed tables
|
2016-10-14 15:06:46 +00:00
|
|
|
|
/// Initialized on demand (on distributed storages initialization) since Settings should be initialized
|
2016-10-10 08:44:52 +00:00
|
|
|
|
std::unique_ptr<Clusters> clusters;
|
|
|
|
|
ConfigurationPtr clusters_config; /// Soteres updated configs
|
|
|
|
|
mutable std::mutex clusters_mutex; /// Guards clusters and clusters_config
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
2015-07-25 09:49:09 +00:00
|
|
|
|
Poco::UUIDGenerator uuid_generator;
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
bool shutdown_called = false;
|
|
|
|
|
|
2016-03-21 12:57:12 +00:00
|
|
|
|
/// Позволяют запретить одновременное выполнение DDL запросов над одной и той же таблицей.
|
|
|
|
|
/// database -> table -> exception_message
|
|
|
|
|
/// На время выполнения операции, сюда помещается элемент, и возвращается объект, который в деструкторе удаляет элемент.
|
|
|
|
|
/// В случае, если элемент уже есть - кидается исключение. См. class DDLGuard ниже.
|
|
|
|
|
using DDLGuards = std::unordered_map<String, std::unordered_map<String, String>>;
|
|
|
|
|
DDLGuards ddl_guards;
|
2016-04-01 17:41:13 +00:00
|
|
|
|
/// Если вы захватываете mutex и ddl_guards_mutex, то захватывать их нужно строго в этом порядке.
|
2016-03-21 12:57:12 +00:00
|
|
|
|
mutable std::mutex ddl_guards_mutex;
|
|
|
|
|
|
2016-04-09 07:47:08 +00:00
|
|
|
|
Stopwatch uptime_watch;
|
|
|
|
|
|
2016-11-11 17:01:02 +00:00
|
|
|
|
Context::ApplicationType application_type = Context::ApplicationType::SERVER;
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
~ContextShared()
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
shutdown();
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
tryLogCurrentException(__PRETTY_FUNCTION__);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Выполнить сложную работу по уничтожению объектов заранее.
|
|
|
|
|
*/
|
|
|
|
|
void shutdown()
|
|
|
|
|
{
|
|
|
|
|
if (shutdown_called)
|
|
|
|
|
return;
|
|
|
|
|
shutdown_called = true;
|
|
|
|
|
|
2016-03-22 02:05:21 +00:00
|
|
|
|
query_log.reset();
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
/** В этот момент, некоторые таблицы могут иметь потоки, которые блокируют наш mutex.
|
2015-04-16 06:12:35 +00:00
|
|
|
|
* Чтобы корректно их завершить, скопируем текущий список таблиц,
|
|
|
|
|
* и попросим их всех закончить свою работу.
|
|
|
|
|
* Потом удалим все объекты с таблицами.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
Databases current_databases;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Poco::ScopedLock<Poco::Mutex> lock(mutex);
|
|
|
|
|
current_databases = databases;
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
for (auto & database : current_databases)
|
|
|
|
|
database.second->shutdown();
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Poco::ScopedLock<Poco::Mutex> lock(mutex);
|
|
|
|
|
databases.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Context::Context()
|
|
|
|
|
: shared(new ContextShared),
|
|
|
|
|
quota(new QuotaForIntervals)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-04 20:52:00 +00:00
|
|
|
|
Context::~Context() = default;
|
2015-04-16 06:12:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const TableFunctionFactory & Context::getTableFunctionFactory() const { return shared->table_function_factory; }
|
|
|
|
|
const AggregateFunctionFactory & Context::getAggregateFunctionFactory() const { return shared->aggregate_function_factory; }
|
|
|
|
|
InterserverIOHandler & Context::getInterserverIOHandler() { return shared->interserver_io_handler; }
|
2016-12-07 22:49:42 +00:00
|
|
|
|
|
|
|
|
|
std::unique_lock<Poco::Mutex> Context::getLock() const
|
|
|
|
|
{
|
|
|
|
|
ProfileEvents::increment(ProfileEvents::ContextLock);
|
|
|
|
|
CurrentMetrics::Increment increment{CurrentMetrics::ContextLockWait};
|
|
|
|
|
return std::unique_lock<Poco::Mutex>(shared->mutex);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
ProcessList & Context::getProcessList() { return shared->process_list; }
|
|
|
|
|
const ProcessList & Context::getProcessList() const { return shared->process_list; }
|
|
|
|
|
MergeList & Context::getMergeList() { return shared->merge_list; }
|
|
|
|
|
const MergeList & Context::getMergeList() const { return shared->merge_list; }
|
|
|
|
|
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
const Databases Context::getDatabases() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2016-03-19 01:18:49 +00:00
|
|
|
|
return shared->databases;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Databases Context::getDatabases()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2016-03-19 01:18:49 +00:00
|
|
|
|
return shared->databases;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
|
|
|
|
|
static String resolveDatabase(const String & database_name, const String & current_database)
|
|
|
|
|
{
|
|
|
|
|
String res = database_name.empty() ? current_database : database_name;
|
|
|
|
|
if (res.empty())
|
|
|
|
|
throw Exception("Default database is not selected", ErrorCodes::UNKNOWN_DATABASE);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
const DatabasePtr Context::getDatabase(const String & database_name) const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2016-03-19 01:18:49 +00:00
|
|
|
|
assertDatabaseExists(db);
|
|
|
|
|
return shared->databases[db];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DatabasePtr Context::getDatabase(const String & database_name)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2016-03-19 01:18:49 +00:00
|
|
|
|
assertDatabaseExists(db);
|
|
|
|
|
return shared->databases[db];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const DatabasePtr Context::tryGetDatabase(const String & database_name) const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2016-03-19 01:18:49 +00:00
|
|
|
|
auto it = shared->databases.find(db);
|
|
|
|
|
if (it == shared->databases.end())
|
|
|
|
|
return {};
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DatabasePtr Context::tryGetDatabase(const String & database_name)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2016-03-19 01:18:49 +00:00
|
|
|
|
auto it = shared->databases.find(db);
|
|
|
|
|
if (it == shared->databases.end())
|
|
|
|
|
return {};
|
|
|
|
|
return it->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
String Context::getPath() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
return shared->path;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-07 17:19:23 +00:00
|
|
|
|
String Context::getTemporaryPath() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-01-07 17:19:23 +00:00
|
|
|
|
return shared->tmp_path;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-24 14:01:24 +00:00
|
|
|
|
String Context::getFlagsPath() const
|
|
|
|
|
{
|
|
|
|
|
auto lock = getLock();
|
2016-12-07 19:25:16 +00:00
|
|
|
|
if (!shared->flags_path.empty())
|
|
|
|
|
return shared->flags_path;
|
|
|
|
|
|
|
|
|
|
shared->flags_path = shared->path + "flags/";
|
|
|
|
|
Poco::File(shared->flags_path).createDirectories();
|
2016-10-24 14:01:24 +00:00
|
|
|
|
return shared->flags_path;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
|
|
|
|
void Context::setPath(const String & path)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
shared->path = path;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-07 17:19:23 +00:00
|
|
|
|
void Context::setTemporaryPath(const String & path)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-01-07 17:19:23 +00:00
|
|
|
|
shared->tmp_path = path;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-24 14:01:24 +00:00
|
|
|
|
void Context::setFlagsPath(const String & path)
|
|
|
|
|
{
|
|
|
|
|
auto lock = getLock();
|
|
|
|
|
shared->flags_path = path;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2016-10-14 15:06:46 +00:00
|
|
|
|
void Context::setUsersConfig(const ConfigurationPtr & config)
|
2013-08-10 07:46:45 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-02-13 07:17:22 +00:00
|
|
|
|
shared->users_config = config;
|
|
|
|
|
shared->users.loadFromConfig(*shared->users_config);
|
|
|
|
|
shared->quotas.loadFromConfig(*shared->users_config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ConfigurationPtr Context::getUsersConfig()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-02-13 07:17:22 +00:00
|
|
|
|
return shared->users_config;
|
2013-08-10 07:46:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-10-24 21:40:39 +00:00
|
|
|
|
void Context::setUser(const String & name, const String & password, const Poco::Net::SocketAddress & address, const String & quota_key)
|
2013-08-10 07:46:45 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2013-08-10 07:46:45 +00:00
|
|
|
|
|
2016-10-24 21:40:39 +00:00
|
|
|
|
const User & user_props = shared->users.get(name, password, address.host());
|
2013-08-10 07:46:45 +00:00
|
|
|
|
setSetting("profile", user_props.profile);
|
2016-10-24 21:40:39 +00:00
|
|
|
|
setQuota(user_props.quota, quota_key, name, address.host());
|
2013-08-10 07:46:45 +00:00
|
|
|
|
|
2016-10-24 21:40:39 +00:00
|
|
|
|
client_info.current_user = name;
|
|
|
|
|
client_info.current_address = address;
|
2016-11-16 05:09:41 +00:00
|
|
|
|
|
|
|
|
|
if (!quota_key.empty())
|
|
|
|
|
client_info.quota_key = quota_key;
|
2013-08-10 07:46:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-11-03 00:24:46 +00:00
|
|
|
|
void Context::setQuota(const String & name, const String & quota_key, const String & user_name, const Poco::Net::IPAddress & address)
|
2013-08-12 00:36:18 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-02-13 07:17:22 +00:00
|
|
|
|
quota = shared->quotas.get(name, quota_key, user_name, address);
|
2013-08-12 00:36:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QuotaForIntervals & Context::getQuota()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2013-08-12 00:36:18 +00:00
|
|
|
|
return *quota;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-01 15:10:41 +00:00
|
|
|
|
void Context::checkDatabaseAccessRights(const std::string & database_name) const
|
|
|
|
|
{
|
2016-10-24 21:40:39 +00:00
|
|
|
|
if (client_info.current_user.empty() || (database_name == "system"))
|
2015-10-01 15:10:41 +00:00
|
|
|
|
{
|
2015-10-01 15:14:39 +00:00
|
|
|
|
/// Безымянный пользователь, т.е. сервер, имеет доступ ко всем БД.
|
2015-10-01 15:10:41 +00:00
|
|
|
|
/// Все пользователи имеют доступ к БД system.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-10-24 21:40:39 +00:00
|
|
|
|
if (!shared->users.isAllowedDatabase(client_info.current_user, database_name))
|
2015-10-01 15:10:41 +00:00
|
|
|
|
throw Exception("Access denied to database " + database_name, ErrorCodes::DATABASE_ACCESS_DENIED);
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-13 14:39:48 +00:00
|
|
|
|
void Context::addDependency(const DatabaseAndTableName & from, const DatabaseAndTableName & where)
|
2013-11-08 17:43:03 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(from.first);
|
|
|
|
|
checkDatabaseAccessRights(where.first);
|
2013-11-08 17:43:03 +00:00
|
|
|
|
shared->view_dependencies[from].insert(where);
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-13 14:39:48 +00:00
|
|
|
|
void Context::removeDependency(const DatabaseAndTableName & from, const DatabaseAndTableName & where)
|
2013-11-08 17:43:03 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(from.first);
|
|
|
|
|
checkDatabaseAccessRights(where.first);
|
2013-11-08 17:43:03 +00:00
|
|
|
|
shared->view_dependencies[from].erase(where);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-23 20:32:00 +00:00
|
|
|
|
Dependencies Context::getDependencies(const String & database_name, const String & table_name) const
|
2013-11-08 17:43:03 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-12-23 20:32:00 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(db);
|
2014-12-23 20:32:00 +00:00
|
|
|
|
|
|
|
|
|
ViewDependencies::const_iterator iter = shared->view_dependencies.find(DatabaseAndTableName(db, table_name));
|
2013-11-08 17:43:03 +00:00
|
|
|
|
if (iter == shared->view_dependencies.end())
|
2014-12-23 20:32:00 +00:00
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
return Dependencies(iter->second.begin(), iter->second.end());
|
2013-11-08 17:43:03 +00:00
|
|
|
|
}
|
2013-08-12 00:36:18 +00:00
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
bool Context::isTableExist(const String & database_name, const String & table_name) const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(db);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
Databases::const_iterator it = shared->databases.find(db);
|
|
|
|
|
return shared->databases.end() != it
|
|
|
|
|
&& it->second->isTableExist(table_name);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Context::isDatabaseExist(const String & database_name) const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(db);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
return shared->databases.end() != shared->databases.find(db);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Context::assertTableExists(const String & database_name, const String & table_name) const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(db);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2015-01-28 02:37:05 +00:00
|
|
|
|
Databases::const_iterator it = shared->databases.find(db);
|
|
|
|
|
if (shared->databases.end() == it)
|
2012-08-02 17:33:31 +00:00
|
|
|
|
throw Exception("Database " + db + " doesn't exist", ErrorCodes::UNKNOWN_DATABASE);
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
if (!it->second->isTableExist(table_name))
|
2012-08-02 17:33:31 +00:00
|
|
|
|
throw Exception("Table " + db + "." + table_name + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-10-01 15:10:41 +00:00
|
|
|
|
void Context::assertTableDoesntExist(const String & database_name, const String & table_name, bool check_database_access_rights) const
|
2012-08-02 17:33:31 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
if (check_database_access_rights)
|
|
|
|
|
checkDatabaseAccessRights(db);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
Databases::const_iterator it = shared->databases.find(db);
|
|
|
|
|
if (shared->databases.end() != it && it->second->isTableExist(table_name))
|
2012-08-02 17:33:31 +00:00
|
|
|
|
throw Exception("Table " + db + "." + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-10-01 15:10:41 +00:00
|
|
|
|
void Context::assertDatabaseExists(const String & database_name, bool check_database_access_rights) const
|
2012-08-02 17:33:31 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
if (check_database_access_rights)
|
|
|
|
|
checkDatabaseAccessRights(db);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
|
|
|
|
if (shared->databases.end() == shared->databases.find(db))
|
|
|
|
|
throw Exception("Database " + db + " doesn't exist", ErrorCodes::UNKNOWN_DATABASE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Context::assertDatabaseDoesntExist(const String & database_name) const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(db);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
|
|
|
|
if (shared->databases.end() != shared->databases.find(db))
|
|
|
|
|
throw Exception("Database " + db + " already exists.", ErrorCodes::DATABASE_ALREADY_EXISTS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-03-13 15:00:06 +00:00
|
|
|
|
Tables Context::getExternalTables() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-03-14 15:42:30 +00:00
|
|
|
|
|
2014-03-13 15:00:06 +00:00
|
|
|
|
Tables res = external_tables;
|
|
|
|
|
if (session_context && session_context != this)
|
|
|
|
|
{
|
|
|
|
|
Tables buf = session_context->getExternalTables();
|
|
|
|
|
res.insert(buf.begin(), buf.end());
|
|
|
|
|
}
|
|
|
|
|
else if (global_context && global_context != this)
|
|
|
|
|
{
|
|
|
|
|
Tables buf = global_context->getExternalTables();
|
|
|
|
|
res.insert(buf.begin(), buf.end());
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StoragePtr Context::tryGetExternalTable(const String & table_name) const
|
2014-03-04 15:31:56 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-03-04 15:31:56 +00:00
|
|
|
|
|
2015-01-28 02:37:05 +00:00
|
|
|
|
Tables::const_iterator jt = external_tables.find(table_name);
|
|
|
|
|
if (external_tables.end() == jt)
|
2014-03-04 15:31:56 +00:00
|
|
|
|
return StoragePtr();
|
|
|
|
|
|
|
|
|
|
return jt->second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
StoragePtr Context::getTable(const String & database_name, const String & table_name) const
|
2015-08-19 21:15:27 +00:00
|
|
|
|
{
|
|
|
|
|
Exception exc;
|
|
|
|
|
auto res = getTableImpl(database_name, table_name, &exc);
|
|
|
|
|
if (!res)
|
|
|
|
|
throw exc;
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StoragePtr Context::tryGetTable(const String & database_name, const String & table_name) const
|
|
|
|
|
{
|
|
|
|
|
return getTableImpl(database_name, table_name, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StoragePtr Context::getTableImpl(const String & database_name, const String & table_name, Exception * exception) const
|
2012-08-02 17:33:31 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2015-08-19 21:15:27 +00:00
|
|
|
|
/** Возможность обратиться к временным таблицам другого запроса в виде _query_QUERY_ID.table
|
|
|
|
|
* NOTE В дальнейшем может потребоваться подумать об изоляции.
|
|
|
|
|
*/
|
2016-07-14 05:22:09 +00:00
|
|
|
|
if (startsWith(database_name, "_query_"))
|
2014-03-04 15:31:56 +00:00
|
|
|
|
{
|
2015-08-19 21:15:27 +00:00
|
|
|
|
String requested_query_id = database_name.substr(strlen("_query_"));
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2015-09-04 20:52:00 +00:00
|
|
|
|
auto res = shared->process_list.tryGetTemporaryTable(requested_query_id, table_name);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2015-09-04 20:52:00 +00:00
|
|
|
|
if (!res && exception)
|
|
|
|
|
*exception = Exception(
|
|
|
|
|
"Cannot find temporary table with name " + table_name + " for query with id " + requested_query_id, ErrorCodes::UNKNOWN_TABLE);
|
2014-03-04 15:31:56 +00:00
|
|
|
|
|
2015-09-04 20:52:00 +00:00
|
|
|
|
return res;
|
2015-08-19 21:15:27 +00:00
|
|
|
|
}
|
2014-03-12 13:14:16 +00:00
|
|
|
|
|
2014-03-06 14:02:20 +00:00
|
|
|
|
if (database_name.empty())
|
|
|
|
|
{
|
2015-08-19 21:15:27 +00:00
|
|
|
|
StoragePtr res = tryGetExternalTable(table_name);
|
|
|
|
|
if (res)
|
2014-03-06 14:02:20 +00:00
|
|
|
|
return res;
|
|
|
|
|
}
|
2015-08-19 21:15:27 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2015-10-01 15:10:41 +00:00
|
|
|
|
checkDatabaseAccessRights(db);
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2015-01-28 02:37:05 +00:00
|
|
|
|
Databases::const_iterator it = shared->databases.find(db);
|
|
|
|
|
if (shared->databases.end() == it)
|
2015-08-19 21:15:27 +00:00
|
|
|
|
{
|
|
|
|
|
if (exception)
|
|
|
|
|
*exception = Exception("Database " + db + " doesn't exist", ErrorCodes::UNKNOWN_DATABASE);
|
|
|
|
|
return {};
|
|
|
|
|
}
|
2014-06-26 00:58:14 +00:00
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
auto table = it->second->tryGetTable(table_name);
|
|
|
|
|
if (!table)
|
2015-08-19 21:15:27 +00:00
|
|
|
|
{
|
|
|
|
|
if (exception)
|
|
|
|
|
*exception = Exception("Table " + db + "." + table_name + " doesn't exist.", ErrorCodes::UNKNOWN_TABLE);
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
return table;
|
2013-05-06 10:31:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2014-03-13 15:00:06 +00:00
|
|
|
|
void Context::addExternalTable(const String & table_name, StoragePtr storage)
|
2014-03-04 15:31:56 +00:00
|
|
|
|
{
|
2014-03-13 15:00:06 +00:00
|
|
|
|
if (external_tables.end() != external_tables.find(table_name))
|
2014-03-04 15:31:56 +00:00
|
|
|
|
throw Exception("Temporary table " + table_name + " already exists.", ErrorCodes::TABLE_ALREADY_EXISTS);
|
2015-08-19 21:15:27 +00:00
|
|
|
|
|
2014-03-13 15:00:06 +00:00
|
|
|
|
external_tables[table_name] = storage;
|
2015-08-19 21:15:27 +00:00
|
|
|
|
|
2015-09-04 20:52:00 +00:00
|
|
|
|
if (process_list_elem)
|
2015-08-19 21:15:27 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-09-04 20:52:00 +00:00
|
|
|
|
shared->process_list.addTemporaryTable(*process_list_elem, table_name, storage);
|
2015-08-19 21:15:27 +00:00
|
|
|
|
}
|
2014-03-04 15:31:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-03-21 12:57:12 +00:00
|
|
|
|
DDLGuard::DDLGuard(Map & map_, std::mutex & mutex_, std::unique_lock<std::mutex> && lock, const String & elem, const String & message)
|
|
|
|
|
: map(map_), mutex(mutex_)
|
|
|
|
|
{
|
|
|
|
|
bool inserted;
|
|
|
|
|
std::tie(it, inserted) = map.emplace(elem, message);
|
|
|
|
|
if (!inserted)
|
|
|
|
|
throw Exception(it->second, ErrorCodes::DDL_GUARD_IS_ACTIVE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DDLGuard::~DDLGuard()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
map.erase(it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<DDLGuard> Context::getDDLGuard(const String & database, const String & table, const String & message) const
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(shared->ddl_guards_mutex);
|
|
|
|
|
return std::make_unique<DDLGuard>(shared->ddl_guards[database], shared->ddl_guards_mutex, std::move(lock), table, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-04-01 17:41:13 +00:00
|
|
|
|
std::unique_ptr<DDLGuard> Context::getDDLGuardIfTableDoesntExist(const String & database, const String & table, const String & message) const
|
|
|
|
|
{
|
|
|
|
|
auto lock = getLock();
|
|
|
|
|
|
|
|
|
|
Databases::const_iterator it = shared->databases.find(database);
|
|
|
|
|
if (shared->databases.end() != it && it->second->isTableExist(table))
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
return getDDLGuard(database, table, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
void Context::addDatabase(const String & database_name, const DatabasePtr & database)
|
2012-08-02 17:33:31 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
assertDatabaseDoesntExist(database_name);
|
|
|
|
|
shared->databases[database_name] = database;
|
2012-08-02 17:33:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-03-21 12:57:12 +00:00
|
|
|
|
DatabasePtr Context::detachDatabase(const String & database_name)
|
2012-08-02 17:33:31 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2016-03-21 12:57:12 +00:00
|
|
|
|
auto res = getDatabase(database_name);
|
2016-03-19 01:18:49 +00:00
|
|
|
|
shared->databases.erase(database_name);
|
2016-03-21 12:57:12 +00:00
|
|
|
|
return res;
|
2012-08-02 17:33:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
ASTPtr Context::getCreateQuery(const String & database_name, const String & table_name) const
|
2012-08-02 17:33:31 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
2017-01-05 16:34:05 +00:00
|
|
|
|
String db = resolveDatabase(database_name, current_database);
|
2012-08-02 17:33:31 +00:00
|
|
|
|
assertDatabaseExists(db);
|
2012-08-17 19:53:11 +00:00
|
|
|
|
|
2016-03-19 01:18:49 +00:00
|
|
|
|
return shared->databases[db]->getCreateQuery(table_name);
|
2012-08-17 19:53:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
Settings Context::getSettings() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
return settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-05-05 20:07:11 +00:00
|
|
|
|
Limits Context::getLimits() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2013-05-05 20:07:11 +00:00
|
|
|
|
return settings.limits;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
void Context::setSettings(const Settings & settings_)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
settings = settings_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 19:03:32 +00:00
|
|
|
|
void Context::setSetting(const String & name, const Field & value)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-02-13 07:17:22 +00:00
|
|
|
|
if (name == "profile")
|
|
|
|
|
settings.setProfile(value.safeGet<String>(), *shared->users_config);
|
|
|
|
|
else
|
|
|
|
|
settings.set(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Context::setSetting(const String & name, const std::string & value)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-02-13 07:17:22 +00:00
|
|
|
|
if (name == "profile")
|
|
|
|
|
settings.setProfile(value, *shared->users_config);
|
|
|
|
|
else
|
|
|
|
|
settings.set(name, value);
|
2012-08-02 19:03:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
String Context::getCurrentDatabase() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
return current_database;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-02-12 17:31:02 +00:00
|
|
|
|
String Context::getCurrentQueryId() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2016-10-24 21:40:39 +00:00
|
|
|
|
return client_info.current_query_id;
|
2014-02-12 17:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
void Context::setCurrentDatabase(const String & name)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2012-08-02 17:33:31 +00:00
|
|
|
|
assertDatabaseExists(name);
|
|
|
|
|
current_database = name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-02-12 17:31:02 +00:00
|
|
|
|
void Context::setCurrentQueryId(const String & query_id)
|
|
|
|
|
{
|
2016-10-24 21:40:39 +00:00
|
|
|
|
if (!client_info.current_query_id.empty())
|
2015-08-19 21:15:27 +00:00
|
|
|
|
throw Exception("Logical error: attempt to set query_id twice", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
2015-07-25 09:49:09 +00:00
|
|
|
|
String query_id_to_set = query_id;
|
|
|
|
|
if (query_id_to_set.empty()) /// Если пользователь не передал свой query_id, то генерируем его самостоятельно.
|
|
|
|
|
query_id_to_set = shared->uuid_generator.createRandom().toString();
|
|
|
|
|
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2016-10-24 21:40:39 +00:00
|
|
|
|
client_info.current_query_id = query_id_to_set;
|
2014-02-12 17:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-06-29 18:03:57 +00:00
|
|
|
|
String Context::getDefaultFormat() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2013-06-29 18:03:57 +00:00
|
|
|
|
return default_format.empty() ? "TabSeparated" : default_format;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Context::setDefaultFormat(const String & name)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2013-06-29 18:03:57 +00:00
|
|
|
|
default_format = name;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-11 15:59:01 +00:00
|
|
|
|
const Macros& Context::getMacros() const
|
|
|
|
|
{
|
|
|
|
|
return shared->macros;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Context::setMacros(Macros && macros)
|
|
|
|
|
{
|
|
|
|
|
/// Полагаемся, что это присваивание происходит один раз при старте сервера. Если это не так, нужно использовать мьютекс.
|
|
|
|
|
shared->macros = macros;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-16 11:29:51 +00:00
|
|
|
|
const Context & Context::getSessionContext() const
|
|
|
|
|
{
|
|
|
|
|
if (!session_context)
|
|
|
|
|
throw Exception("There is no session", ErrorCodes::THERE_IS_NO_SESSION);
|
|
|
|
|
return *session_context;
|
|
|
|
|
}
|
2013-06-29 18:03:57 +00:00
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
Context & Context::getSessionContext()
|
|
|
|
|
{
|
|
|
|
|
if (!session_context)
|
|
|
|
|
throw Exception("There is no session", ErrorCodes::THERE_IS_NO_SESSION);
|
|
|
|
|
return *session_context;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-15 10:57:11 +00:00
|
|
|
|
const Context & Context::getGlobalContext() const
|
|
|
|
|
{
|
|
|
|
|
if (!global_context)
|
|
|
|
|
throw Exception("Logical error: there is no global context", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
return *global_context;
|
|
|
|
|
}
|
2012-08-02 17:33:31 +00:00
|
|
|
|
|
|
|
|
|
Context & Context::getGlobalContext()
|
|
|
|
|
{
|
|
|
|
|
if (!global_context)
|
|
|
|
|
throw Exception("Logical error: there is no global context", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
return *global_context;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-19 20:15:15 +00:00
|
|
|
|
|
2012-12-21 19:48:47 +00:00
|
|
|
|
const Dictionaries & Context::getDictionaries() const
|
2012-12-19 20:15:15 +00:00
|
|
|
|
{
|
2015-04-02 16:30:18 +00:00
|
|
|
|
return getDictionariesImpl(false);
|
2015-02-10 17:40:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ExternalDictionaries & Context::getExternalDictionaries() const
|
|
|
|
|
{
|
2015-04-02 16:30:18 +00:00
|
|
|
|
return getExternalDictionariesImpl(false);
|
2015-03-27 13:11:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-02 16:30:18 +00:00
|
|
|
|
|
|
|
|
|
const Dictionaries & Context::getDictionariesImpl(const bool throw_on_error) const
|
2015-03-27 13:11:22 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-04-02 16:30:18 +00:00
|
|
|
|
|
2015-03-27 13:11:22 +00:00
|
|
|
|
if (!shared->dictionaries)
|
2016-05-28 14:14:18 +00:00
|
|
|
|
shared->dictionaries = std::make_shared<Dictionaries>(throw_on_error);
|
2015-04-02 16:30:18 +00:00
|
|
|
|
|
|
|
|
|
return *shared->dictionaries;
|
2015-03-27 13:11:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-02 16:30:18 +00:00
|
|
|
|
|
|
|
|
|
const ExternalDictionaries & Context::getExternalDictionariesImpl(const bool throw_on_error) const
|
2015-03-27 13:11:22 +00:00
|
|
|
|
{
|
2016-01-17 07:53:58 +00:00
|
|
|
|
std::lock_guard<std::mutex> lock(shared->external_dictionaries_mutex);
|
2015-04-02 16:30:18 +00:00
|
|
|
|
|
2015-02-10 17:40:40 +00:00
|
|
|
|
if (!shared->external_dictionaries)
|
2015-02-03 17:14:12 +00:00
|
|
|
|
{
|
|
|
|
|
if (!this->global_context)
|
|
|
|
|
throw Exception("Logical error: there is no global context", ErrorCodes::LOGICAL_ERROR);
|
2016-05-28 14:14:18 +00:00
|
|
|
|
shared->external_dictionaries = std::make_shared<ExternalDictionaries>(*this->global_context, throw_on_error);
|
2015-02-03 17:14:12 +00:00
|
|
|
|
}
|
2015-04-02 16:30:18 +00:00
|
|
|
|
|
|
|
|
|
return *shared->external_dictionaries;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Context::tryCreateDictionaries() const
|
|
|
|
|
{
|
|
|
|
|
static_cast<void>(getDictionariesImpl(true));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Context::tryCreateExternalDictionaries() const
|
|
|
|
|
{
|
|
|
|
|
static_cast<void>(getExternalDictionariesImpl(true));
|
2012-12-19 20:15:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-02-16 14:55:14 +00:00
|
|
|
|
|
|
|
|
|
void Context::setProgressCallback(ProgressCallback callback)
|
|
|
|
|
{
|
|
|
|
|
/// Колбек устанавливается на сессию или на запрос. В сессии одновременно обрабатывается только один запрос. Поэтому блокировка не нужна.
|
|
|
|
|
progress_callback = callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProgressCallback Context::getProgressCallback() const
|
|
|
|
|
{
|
|
|
|
|
return progress_callback;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-03 20:21:28 +00:00
|
|
|
|
|
2013-11-03 05:32:42 +00:00
|
|
|
|
void Context::setProcessListElement(ProcessList::Element * elem)
|
|
|
|
|
{
|
|
|
|
|
/// Устанавливается на сессию или на запрос. В сессии одновременно обрабатывается только один запрос. Поэтому блокировка не нужна.
|
|
|
|
|
process_list_elem = elem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProcessList::Element * Context::getProcessListElement()
|
|
|
|
|
{
|
|
|
|
|
return process_list_elem;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-03-28 14:36:24 +00:00
|
|
|
|
void Context::setUncompressedCache(size_t max_size_in_bytes)
|
2013-09-08 05:53:10 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2013-09-08 05:53:10 +00:00
|
|
|
|
|
|
|
|
|
if (shared->uncompressed_cache)
|
|
|
|
|
throw Exception("Uncompressed cache has been already created.", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
2016-09-23 20:33:06 +00:00
|
|
|
|
shared->uncompressed_cache = std::make_shared<UncompressedCache>(max_size_in_bytes);
|
2013-09-08 05:53:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UncompressedCachePtr Context::getUncompressedCache() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2013-09-08 05:53:10 +00:00
|
|
|
|
return shared->uncompressed_cache;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-11 13:30:42 +00:00
|
|
|
|
void Context::setMarkCache(size_t cache_size_in_bytes)
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-02-11 13:30:42 +00:00
|
|
|
|
|
|
|
|
|
if (shared->mark_cache)
|
|
|
|
|
throw Exception("Uncompressed cache has been already created.", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
2016-09-23 20:33:06 +00:00
|
|
|
|
shared->mark_cache = std::make_shared<MarkCache>(cache_size_in_bytes, std::chrono::seconds(settings.mark_cache_min_lifetime));
|
2014-02-11 13:30:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MarkCachePtr Context::getMarkCache() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-02-11 13:30:42 +00:00
|
|
|
|
return shared->mark_cache;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-02 12:30:38 +00:00
|
|
|
|
BackgroundProcessingPool & Context::getBackgroundPool()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-07-02 12:30:38 +00:00
|
|
|
|
if (!shared->background_pool)
|
2016-05-28 10:15:36 +00:00
|
|
|
|
shared->background_pool = std::make_shared<BackgroundProcessingPool>(settings.background_pool_size);
|
2014-07-02 12:30:38 +00:00
|
|
|
|
return *shared->background_pool;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-28 01:00:42 +00:00
|
|
|
|
void Context::setReshardingWorker(std::shared_ptr<ReshardingWorker> resharding_worker)
|
2016-01-28 01:00:27 +00:00
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2016-01-28 01:00:42 +00:00
|
|
|
|
if (shared->resharding_worker)
|
2016-01-28 16:06:57 +00:00
|
|
|
|
throw Exception("Resharding background thread has already been initialized.", ErrorCodes::LOGICAL_ERROR);
|
2016-01-28 01:00:42 +00:00
|
|
|
|
shared->resharding_worker = resharding_worker;
|
|
|
|
|
}
|
2016-01-28 01:00:27 +00:00
|
|
|
|
|
2016-01-28 01:00:42 +00:00
|
|
|
|
ReshardingWorker & Context::getReshardingWorker()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2016-01-28 01:00:27 +00:00
|
|
|
|
if (!shared->resharding_worker)
|
2016-01-28 16:06:57 +00:00
|
|
|
|
throw Exception("Resharding background thread not initialized: resharding missing in configuration file.",
|
|
|
|
|
ErrorCodes::LOGICAL_ERROR);
|
2016-01-28 01:00:27 +00:00
|
|
|
|
return *shared->resharding_worker;
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-05 19:54:00 +00:00
|
|
|
|
void Context::resetCaches() const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2014-04-05 19:54:00 +00:00
|
|
|
|
|
|
|
|
|
if (shared->uncompressed_cache)
|
|
|
|
|
shared->uncompressed_cache->reset();
|
|
|
|
|
|
|
|
|
|
if (shared->mark_cache)
|
|
|
|
|
shared->mark_cache->reset();
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-13 10:10:26 +00:00
|
|
|
|
void Context::setZooKeeper(zkutil::ZooKeeperPtr zookeeper)
|
2014-03-21 19:17:59 +00:00
|
|
|
|
{
|
2016-01-17 07:53:58 +00:00
|
|
|
|
std::lock_guard<std::mutex> lock(shared->zookeeper_mutex);
|
2014-03-21 19:17:59 +00:00
|
|
|
|
|
|
|
|
|
if (shared->zookeeper)
|
|
|
|
|
throw Exception("ZooKeeper client has already been set.", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
|
|
shared->zookeeper = zookeeper;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-13 10:10:26 +00:00
|
|
|
|
zkutil::ZooKeeperPtr Context::getZooKeeper() const
|
2014-03-21 19:17:59 +00:00
|
|
|
|
{
|
2016-01-17 07:53:58 +00:00
|
|
|
|
std::lock_guard<std::mutex> lock(shared->zookeeper_mutex);
|
2014-04-25 13:55:15 +00:00
|
|
|
|
|
2014-05-13 11:24:04 +00:00
|
|
|
|
if (shared->zookeeper && shared->zookeeper->expired())
|
2014-04-25 13:55:15 +00:00
|
|
|
|
shared->zookeeper = shared->zookeeper->startNewSession();
|
|
|
|
|
|
|
|
|
|
return shared->zookeeper;
|
2014-03-21 19:17:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-11-19 20:40:51 +00:00
|
|
|
|
void Context::setInterserverIOAddress(const String & host, UInt16 port)
|
2014-03-21 19:49:27 +00:00
|
|
|
|
{
|
|
|
|
|
shared->interserver_io_host = host;
|
|
|
|
|
shared->interserver_io_port = port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-11-19 20:40:51 +00:00
|
|
|
|
std::pair<String, UInt16> Context::getInterserverIOAddress() const
|
2014-03-21 19:49:27 +00:00
|
|
|
|
{
|
2014-11-19 20:40:51 +00:00
|
|
|
|
if (shared->interserver_io_host.empty() || shared->interserver_io_port == 0)
|
|
|
|
|
throw Exception("Parameter 'interserver_http_port' required for replication is not specified in configuration file.",
|
|
|
|
|
ErrorCodes::NO_ELEMENTS_IN_CONFIG);
|
|
|
|
|
|
|
|
|
|
return { shared->interserver_io_host, shared->interserver_io_port };
|
2014-03-21 19:49:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-24 04:50:53 +00:00
|
|
|
|
UInt16 Context::getTCPPort() const
|
|
|
|
|
{
|
|
|
|
|
return Poco::Util::Application::instance().config().getInt("tcp_port");
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-21 19:49:27 +00:00
|
|
|
|
|
2016-10-14 15:06:46 +00:00
|
|
|
|
std::shared_ptr<Cluster> Context::getCluster(const std::string & cluster_name) const
|
2013-12-07 16:51:29 +00:00
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
auto res = getClusters().getCluster(cluster_name);
|
2013-12-10 17:06:57 +00:00
|
|
|
|
|
2016-10-14 15:06:46 +00:00
|
|
|
|
if (!res)
|
2016-10-10 08:44:52 +00:00
|
|
|
|
throw Exception("Requested cluster '" + cluster_name + "' not found", ErrorCodes::BAD_GET);
|
|
|
|
|
|
|
|
|
|
return res;
|
2013-12-07 16:51:29 +00:00
|
|
|
|
}
|
2015-01-10 02:30:03 +00:00
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
|
2016-10-14 15:06:46 +00:00
|
|
|
|
std::shared_ptr<Cluster> Context::tryGetCluster(const std::string & cluster_name) const
|
|
|
|
|
{
|
|
|
|
|
return getClusters().getCluster(cluster_name);
|
2013-12-07 16:51:29 +00:00
|
|
|
|
}
|
2015-01-10 02:30:03 +00:00
|
|
|
|
|
2016-10-14 15:06:46 +00:00
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
Clusters & Context::getClusters() const
|
2015-04-30 12:43:16 +00:00
|
|
|
|
{
|
2016-03-10 03:08:09 +00:00
|
|
|
|
{
|
2016-10-10 08:44:52 +00:00
|
|
|
|
std::lock_guard<std::mutex> lock(shared->clusters_mutex);
|
2016-03-10 03:08:09 +00:00
|
|
|
|
if (!shared->clusters)
|
2016-10-10 08:44:52 +00:00
|
|
|
|
{
|
|
|
|
|
auto & config = shared->clusters_config ? *shared->clusters_config : Poco::Util::Application::instance().config();
|
|
|
|
|
shared->clusters = std::make_unique<Clusters>(config, settings);
|
|
|
|
|
}
|
2016-03-10 03:08:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
return *shared->clusters;
|
2015-04-30 12:43:16 +00:00
|
|
|
|
}
|
2015-01-10 02:30:03 +00:00
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
|
2016-10-14 15:06:46 +00:00
|
|
|
|
/// On repeating calls updates existing clusters and adds new clusters, doesn't delete old clusters
|
|
|
|
|
void Context::setClustersConfig(const ConfigurationPtr & config)
|
2016-10-10 08:44:52 +00:00
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(shared->clusters_mutex);
|
|
|
|
|
|
|
|
|
|
shared->clusters_config = config;
|
|
|
|
|
if (shared->clusters)
|
|
|
|
|
shared->clusters->updateClusters(*shared->clusters_config, settings);
|
2015-04-30 12:43:16 +00:00
|
|
|
|
}
|
2015-01-10 02:30:03 +00:00
|
|
|
|
|
2016-10-10 08:44:52 +00:00
|
|
|
|
|
2015-01-10 02:30:03 +00:00
|
|
|
|
Compiler & Context::getCompiler()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-01-11 00:35:30 +00:00
|
|
|
|
|
|
|
|
|
if (!shared->compiler)
|
2016-05-28 14:14:18 +00:00
|
|
|
|
shared->compiler = std::make_unique<Compiler>(shared->path + "build/", 1);
|
2015-01-11 00:35:30 +00:00
|
|
|
|
|
|
|
|
|
return *shared->compiler;
|
2015-01-10 02:30:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-06-26 20:48:10 +00:00
|
|
|
|
QueryLog & Context::getQueryLog()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-06-26 20:48:10 +00:00
|
|
|
|
|
|
|
|
|
if (!shared->query_log)
|
|
|
|
|
{
|
2016-03-22 19:35:23 +00:00
|
|
|
|
if (shared->shutdown_called)
|
|
|
|
|
throw Exception("Will not get query_log because shutdown was called", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
|
|
|
|
if (!global_context)
|
|
|
|
|
throw Exception("Logical error: no global context for query log", ErrorCodes::LOGICAL_ERROR);
|
|
|
|
|
|
2015-06-26 20:48:10 +00:00
|
|
|
|
auto & config = Poco::Util::Application::instance().config();
|
|
|
|
|
|
|
|
|
|
String database = config.getString("query_log.database", "system");
|
|
|
|
|
String table = config.getString("query_log.table", "query_log");
|
|
|
|
|
size_t flush_interval_milliseconds = parse<size_t>(
|
|
|
|
|
config.getString("query_log.flush_interval_milliseconds", DEFAULT_QUERY_LOG_FLUSH_INTERVAL_MILLISECONDS_STR));
|
|
|
|
|
|
2016-10-27 17:48:12 +00:00
|
|
|
|
shared->query_log = std::make_unique<QueryLog>(
|
|
|
|
|
*global_context, database, table, "MergeTree(event_date, event_time, 1024)", flush_interval_milliseconds);
|
2015-06-26 20:48:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return *shared->query_log;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-17 05:35:53 +00:00
|
|
|
|
CompressionMethod Context::chooseCompressionMethod(size_t part_size, double part_size_ratio) const
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-04-17 05:35:53 +00:00
|
|
|
|
|
|
|
|
|
if (!shared->compression_method_selector)
|
|
|
|
|
{
|
|
|
|
|
constexpr auto config_name = "compression";
|
|
|
|
|
auto & config = Poco::Util::Application::instance().config();
|
|
|
|
|
|
|
|
|
|
if (config.has(config_name))
|
2016-09-23 20:33:06 +00:00
|
|
|
|
shared->compression_method_selector = std::make_unique<CompressionMethodSelector>(config, "compression");
|
2015-04-17 05:35:53 +00:00
|
|
|
|
else
|
2016-09-23 20:33:06 +00:00
|
|
|
|
shared->compression_method_selector = std::make_unique<CompressionMethodSelector>();
|
2015-04-17 05:35:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return shared->compression_method_selector->choose(part_size, part_size_ratio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-07-16 21:32:51 +00:00
|
|
|
|
const MergeTreeSettings & Context::getMergeTreeSettings()
|
|
|
|
|
{
|
2016-03-22 01:50:19 +00:00
|
|
|
|
auto lock = getLock();
|
2015-07-16 21:32:51 +00:00
|
|
|
|
|
|
|
|
|
if (!shared->merge_tree_settings)
|
|
|
|
|
{
|
|
|
|
|
auto & config = Poco::Util::Application::instance().config();
|
2016-09-23 20:33:06 +00:00
|
|
|
|
shared->merge_tree_settings = std::make_unique<MergeTreeSettings>();
|
2015-07-16 21:32:51 +00:00
|
|
|
|
shared->merge_tree_settings->loadFromConfig("merge_tree", config);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return *shared->merge_tree_settings;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-02-13 06:37:19 +00:00
|
|
|
|
BlockInputStreamPtr Context::getInputFormat(const String & name, ReadBuffer & buf, const Block & sample, size_t max_block_size) const
|
|
|
|
|
{
|
|
|
|
|
return shared->format_factory.getInput(name, buf, sample, *this, max_block_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BlockOutputStreamPtr Context::getOutputFormat(const String & name, WriteBuffer & buf, const Block & sample) const
|
|
|
|
|
{
|
|
|
|
|
return shared->format_factory.getOutput(name, buf, sample, *this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-04-09 07:47:08 +00:00
|
|
|
|
time_t Context::getUptimeSeconds() const
|
|
|
|
|
{
|
|
|
|
|
auto lock = getLock();
|
|
|
|
|
return shared->uptime_watch.elapsedSeconds();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2015-04-16 06:12:35 +00:00
|
|
|
|
void Context::shutdown()
|
|
|
|
|
{
|
|
|
|
|
shared->shutdown();
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-11 17:01:02 +00:00
|
|
|
|
|
|
|
|
|
Context::ApplicationType Context::getApplicationType() const
|
|
|
|
|
{
|
|
|
|
|
return shared->application_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Context::setApplicationType(ApplicationType type)
|
|
|
|
|
{
|
|
|
|
|
/// Lock isn't required, you should set it at start
|
|
|
|
|
shared->application_type = type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-02 17:33:31 +00:00
|
|
|
|
}
|