2012-03-05 00:09:41 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
2012-07-26 20:16:57 +00:00
|
|
|
|
#include <Poco/Timespan.h>
|
2014-02-13 07:17:22 +00:00
|
|
|
|
#include <Poco/Util/AbstractConfiguration.h>
|
2012-03-05 00:09:41 +00:00
|
|
|
|
#include <DB/Core/Defines.h>
|
2012-08-02 19:03:32 +00:00
|
|
|
|
#include <DB/Core/Field.h>
|
2012-03-05 00:09:41 +00:00
|
|
|
|
|
2012-12-24 19:50:22 +00:00
|
|
|
|
#include <DB/Interpreters/Limits.h>
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#include <DB/Interpreters/SettingsCommon.h>
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2012-03-05 00:09:41 +00:00
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/** Настройки выполнения запроса.
|
|
|
|
|
*/
|
|
|
|
|
struct Settings
|
|
|
|
|
{
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/** Перечисление настроек: тип, имя, значение по-умолчанию.
|
|
|
|
|
*
|
|
|
|
|
* Это сделано несколько неудобно, чтобы не перечислять настройки во многих разных местах.
|
|
|
|
|
* Замечание: можно было бы сделать полностью динамические настройки вида map: String -> Field,
|
|
|
|
|
* но пока рано, так как в коде они используются как статический struct.
|
2013-09-07 02:03:13 +00:00
|
|
|
|
*/
|
2013-12-10 17:07:06 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#define APPLY_FOR_SETTINGS(M) \
|
|
|
|
|
/** Максимальный размер блока для чтения */ \
|
|
|
|
|
M(SettingUInt64, max_block_size, DEFAULT_BLOCK_SIZE) \
|
|
|
|
|
/** Максимальное количество потоков выполнения запроса */ \
|
|
|
|
|
M(SettingUInt64, max_threads, DEFAULT_MAX_THREADS) \
|
|
|
|
|
/** Максимальное количество соединений при распределённой обработке одного запроса (должно быть больше, чем max_threads). */ \
|
|
|
|
|
M(SettingUInt64, max_distributed_connections, DEFAULT_MAX_DISTRIBUTED_CONNECTIONS) \
|
|
|
|
|
/** Какую часть запроса можно прочитать в оперативку для парсинга (оставшиеся данные для INSERT, если есть, считываются позже) */ \
|
|
|
|
|
M(SettingUInt64, max_query_size, DEFAULT_MAX_QUERY_SIZE) \
|
|
|
|
|
/** Выполнять разные стадии конвейера выполнения запроса параллельно. */ \
|
|
|
|
|
M(SettingBool, asynchronous, false) \
|
|
|
|
|
/** Интервал в микросекундах для проверки, не запрошена ли остановка выполнения запроса, и отправки прогресса. */ \
|
|
|
|
|
M(SettingUInt64, interactive_delay, DEFAULT_INTERACTIVE_DELAY) \
|
|
|
|
|
M(SettingSeconds, connect_timeout, DBMS_DEFAULT_CONNECT_TIMEOUT_SEC) \
|
|
|
|
|
/** Если следует выбрать одну из рабочих реплик. */ \
|
|
|
|
|
M(SettingMilliseconds, connect_timeout_with_failover_ms, DBMS_DEFAULT_CONNECT_TIMEOUT_WITH_FAILOVER_MS) \
|
|
|
|
|
M(SettingSeconds, receive_timeout, DBMS_DEFAULT_RECEIVE_TIMEOUT_SEC) \
|
|
|
|
|
M(SettingSeconds, send_timeout, DBMS_DEFAULT_SEND_TIMEOUT_SEC) \
|
|
|
|
|
/** Время ожидания в очереди запросов, если количество одновременно выполняющихся запросов превышает максимальное. */ \
|
|
|
|
|
M(SettingMilliseconds, queue_max_wait_ms, DEFAULT_QUERIES_QUEUE_WAIT_TIME_MS) \
|
|
|
|
|
/** Блокироваться в цикле ожидания запроса в сервере на указанное количество секунд. */ \
|
|
|
|
|
M(SettingUInt64, poll_interval, DBMS_DEFAULT_POLL_INTERVAL) \
|
|
|
|
|
/** Максимальное количество соединений с одним удалённым сервером в пуле. */ \
|
|
|
|
|
M(SettingUInt64, distributed_connections_pool_size, DBMS_DEFAULT_DISTRIBUTED_CONNECTIONS_POOL_SIZE) \
|
|
|
|
|
/** Максимальное количество попыток соединения с репликами. */ \
|
|
|
|
|
M(SettingUInt64, connections_with_failover_max_tries, DBMS_CONNECTION_POOL_WITH_FAILOVER_DEFAULT_MAX_TRIES) \
|
|
|
|
|
/** Переписывать запросы SELECT из CollapsingMergeTree с агрегатными функциями для автоматического учета поля Sign. */ \
|
|
|
|
|
M(SettingBool, sign_rewrite, false) \
|
|
|
|
|
/** Считать минимумы и максимумы столбцов результата. Они могут выводиться в JSON-форматах. */ \
|
|
|
|
|
M(SettingBool, extremes, false) \
|
|
|
|
|
/** Использовать ли кэш разжатых блоков. */ \
|
|
|
|
|
M(SettingBool, use_uncompressed_cache, true) \
|
|
|
|
|
/** Использовать ли SplittingAggregator вместо обычного. Он быстрее для запросов с большим состоянием агрегации. */ \
|
|
|
|
|
M(SettingBool, use_splitting_aggregator, false) \
|
|
|
|
|
/** Следует ли отменять выполняющийся запрос с таким же id, как новый. */ \
|
|
|
|
|
M(SettingBool, replace_running_query, false) \
|
|
|
|
|
\
|
|
|
|
|
M(SettingLoadBalancing, load_balancing, LoadBalancing::RANDOM) \
|
2014-02-27 13:12:56 +00:00
|
|
|
|
\
|
2014-02-18 09:02:35 +00:00
|
|
|
|
M(SettingTotalsMode, totals_mode, TotalsMode::BEFORE_HAVING) \
|
2014-02-27 13:12:56 +00:00
|
|
|
|
M(SettingFloat, totals_auto_threshold, 0.5) \
|
2014-02-17 23:56:45 +00:00
|
|
|
|
\
|
|
|
|
|
/** Сэмплирование по умолчанию. Если равно 1, то отключено. */ \
|
|
|
|
|
M(SettingFloat, default_sample, 1.0) \
|
2014-01-28 19:26:37 +00:00
|
|
|
|
|
2012-12-24 19:50:22 +00:00
|
|
|
|
/// Всевозможные ограничения на выполнение запроса.
|
|
|
|
|
Limits limits;
|
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#define DECLARE(TYPE, NAME, DEFAULT) \
|
|
|
|
|
TYPE NAME {DEFAULT};
|
|
|
|
|
|
|
|
|
|
APPLY_FOR_SETTINGS(DECLARE)
|
|
|
|
|
|
|
|
|
|
#undef DECLARE
|
|
|
|
|
|
2012-08-02 19:03:32 +00:00
|
|
|
|
/// Установить настройку по имени.
|
2014-02-17 23:56:45 +00:00
|
|
|
|
void set(const String & name, const Field & value)
|
|
|
|
|
{
|
|
|
|
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|
|
|
|
else if (name == #NAME) NAME.set(value);
|
|
|
|
|
|
|
|
|
|
if (false) {}
|
|
|
|
|
APPLY_FOR_SETTINGS(TRY_SET)
|
|
|
|
|
else if (!limits.trySet(name, value))
|
|
|
|
|
throw Exception("Unknown setting " + name, ErrorCodes::UNKNOWN_SETTING);
|
|
|
|
|
|
|
|
|
|
#undef TRY_SET
|
|
|
|
|
}
|
2013-02-01 19:02:04 +00:00
|
|
|
|
|
2013-02-17 19:54:32 +00:00
|
|
|
|
/// Установить настройку по имени. Прочитать сериализованное в бинарном виде значение из буфера (для межсерверного взаимодействия).
|
2014-02-17 23:56:45 +00:00
|
|
|
|
void set(const String & name, ReadBuffer & buf)
|
|
|
|
|
{
|
|
|
|
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|
|
|
|
else if (name == #NAME) NAME.set(buf);
|
|
|
|
|
|
|
|
|
|
if (false) {}
|
|
|
|
|
APPLY_FOR_SETTINGS(TRY_SET)
|
|
|
|
|
else if (!limits.trySet(name, buf))
|
|
|
|
|
throw Exception("Unknown setting " + name, ErrorCodes::UNKNOWN_SETTING);
|
|
|
|
|
|
|
|
|
|
#undef TRY_SET
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Установить настройку по имени. Прочитать значение в текстовом виде из строки (например, из конфига, или из параметра URL).
|
|
|
|
|
*/
|
|
|
|
|
void set(const String & name, const String & value)
|
|
|
|
|
{
|
|
|
|
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|
|
|
|
else if (name == #NAME) NAME.set(value);
|
2013-02-01 19:02:04 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
if (false) {}
|
|
|
|
|
APPLY_FOR_SETTINGS(TRY_SET)
|
|
|
|
|
else if (!limits.trySet(name, value))
|
|
|
|
|
throw Exception("Unknown setting " + name, ErrorCodes::UNKNOWN_SETTING);
|
|
|
|
|
|
|
|
|
|
#undef TRY_SET
|
|
|
|
|
}
|
2013-02-17 19:54:32 +00:00
|
|
|
|
|
|
|
|
|
/** Установить настройки из профиля (в конфиге сервера, в одном профиле может быть перечислено много настроек).
|
|
|
|
|
* Профиль также может быть установлен с помощью функций set, как настройка profile.
|
|
|
|
|
*/
|
2014-02-17 23:56:45 +00:00
|
|
|
|
void setProfile(const String & profile_name, Poco::Util::AbstractConfiguration & config)
|
|
|
|
|
{
|
|
|
|
|
String elem = "profiles." + profile_name;
|
|
|
|
|
|
|
|
|
|
if (!config.has(elem))
|
|
|
|
|
throw Exception("There is no profile '" + profile_name + "' in configuration file.", ErrorCodes::THERE_IS_NO_PROFILE);
|
|
|
|
|
|
|
|
|
|
Poco::Util::AbstractConfiguration::Keys config_keys;
|
|
|
|
|
config.keys(elem, config_keys);
|
|
|
|
|
|
|
|
|
|
for (Poco::Util::AbstractConfiguration::Keys::const_iterator it = config_keys.begin(); it != config_keys.end(); ++it)
|
|
|
|
|
set(*it, config.getString(elem + "." + *it));
|
|
|
|
|
}
|
2013-02-17 19:54:32 +00:00
|
|
|
|
|
2013-02-01 19:02:04 +00:00
|
|
|
|
/// Прочитать настройки из буфера. Они записаны как набор name-value пар, идущих подряд, заканчивающихся пустым name.
|
2014-02-17 23:56:45 +00:00
|
|
|
|
void deserialize(ReadBuffer & buf)
|
|
|
|
|
{
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
String name;
|
|
|
|
|
readBinary(name, buf);
|
2013-02-01 19:02:04 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/// Пустая строка - это маркер конца настроек.
|
|
|
|
|
if (name.empty())
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
set(name, buf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Записать изменённые настройки в буфер. (Например, для отправки на удалённый сервер.)
|
|
|
|
|
void serialize(WriteBuffer & buf) const
|
|
|
|
|
{
|
|
|
|
|
#define WRITE(TYPE, NAME, DEFAULT) \
|
|
|
|
|
if (NAME.changed) \
|
|
|
|
|
{ \
|
|
|
|
|
writeStringBinary(#NAME, buf); \
|
|
|
|
|
NAME.write(buf); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APPLY_FOR_SETTINGS(WRITE)
|
|
|
|
|
|
|
|
|
|
limits.serialize(buf);
|
|
|
|
|
|
|
|
|
|
/// Пустая строка - это маркер конца настроек.
|
|
|
|
|
writeStringBinary("", buf);
|
|
|
|
|
|
|
|
|
|
#undef WRITE
|
|
|
|
|
}
|
2013-12-11 11:51:08 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#undef APPLY_FOR_SETTINGS
|
2012-03-05 00:09:41 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|