2012-12-24 19:50:22 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <Poco/Timespan.h>
|
|
|
|
|
#include <DB/Core/Defines.h>
|
|
|
|
|
#include <DB/Core/Field.h>
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#include <DB/Interpreters/SettingsCommon.h>
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
/** Ограничения при выполнении запроса - часть настроек.
|
|
|
|
|
* Используются, чтобы обеспечить более безопасное исполнение запросов из пользовательского интерфейса.
|
|
|
|
|
* В основном, ограничения проверяются на каждый блок (а не на каждую строку). То есть, ограничения могут быть немного нарушены.
|
|
|
|
|
* Почти все ограничения действуют только на SELECT-ы.
|
2012-12-25 19:28:59 +00:00
|
|
|
|
* Почти все ограничения действуют на каждый поток по отдельности.
|
2012-12-24 19:50:22 +00:00
|
|
|
|
*/
|
|
|
|
|
struct Limits
|
|
|
|
|
{
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/** Перечисление ограничений: тип, имя, значение по-умолчанию.
|
|
|
|
|
* По-умолчанию: всё не ограничено, кроме довольно слабых ограничений на глубину рекурсии и размер выражений.
|
2012-12-25 20:36:35 +00:00
|
|
|
|
*/
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2014-04-10 17:06:58 +00:00
|
|
|
|
#define APPLY_FOR_LIMITS(M) \
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/** Ограничения на чтение из самых "глубоких" источников. \
|
|
|
|
|
* То есть, только в самом глубоком подзапросе. \
|
|
|
|
|
* При чтении с удалённого сервера, проверяется только на удалённом сервере. \
|
|
|
|
|
*/ \
|
|
|
|
|
M(SettingUInt64, max_rows_to_read, 0) \
|
|
|
|
|
M(SettingUInt64, max_bytes_to_read, 0) \
|
|
|
|
|
M(SettingOverflowMode<false>, read_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
|
|
|
|
M(SettingUInt64, max_rows_to_group_by, 0) \
|
|
|
|
|
M(SettingOverflowMode<true>, group_by_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
|
|
|
|
M(SettingUInt64, max_rows_to_sort, 0) \
|
|
|
|
|
M(SettingUInt64, max_bytes_to_sort, 0) \
|
|
|
|
|
M(SettingOverflowMode<false>, sort_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
|
|
|
|
/** Ограничение на размер результата. \
|
|
|
|
|
* Проверяются также для подзапросов и на удалённых серверах. \
|
|
|
|
|
*/ \
|
|
|
|
|
M(SettingUInt64, max_result_rows, 0) \
|
|
|
|
|
M(SettingUInt64, max_result_bytes, 0) \
|
|
|
|
|
M(SettingOverflowMode<false>, result_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
|
|
|
|
/* TODO: Проверять также при merge стадии сортировки, при слиянии и финализации агрегатных функций. */ \
|
|
|
|
|
M(SettingSeconds, max_execution_time, 0) \
|
|
|
|
|
M(SettingOverflowMode<false>, timeout_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
|
|
|
|
/** В строчках в секунду. */ \
|
|
|
|
|
M(SettingUInt64, min_execution_speed, 0) \
|
|
|
|
|
/** Проверять, что скорость не слишком низкая, после прошествия указанного времени. */ \
|
|
|
|
|
M(SettingSeconds, timeout_before_checking_execution_speed, 0) \
|
|
|
|
|
\
|
|
|
|
|
M(SettingUInt64, max_columns_to_read, 0) \
|
|
|
|
|
M(SettingUInt64, max_temporary_columns, 0) \
|
|
|
|
|
M(SettingUInt64, max_temporary_non_const_columns, 0) \
|
|
|
|
|
\
|
|
|
|
|
M(SettingUInt64, max_subquery_depth, 100) \
|
|
|
|
|
M(SettingUInt64, max_pipeline_depth, 1000) \
|
|
|
|
|
M(SettingUInt64, max_ast_depth, 1000) /** Проверяются не во время парсинга, */ \
|
|
|
|
|
M(SettingUInt64, max_ast_elements, 10000) /** а уже после парсинга запроса. */ \
|
|
|
|
|
\
|
|
|
|
|
M(SettingBool, readonly, false) \
|
|
|
|
|
\
|
|
|
|
|
/** Ограничения для максимального размера множества, получающегося при выполнении секции IN. */ \
|
|
|
|
|
M(SettingUInt64, max_rows_in_set, 0) \
|
|
|
|
|
M(SettingUInt64, max_bytes_in_set, 0) \
|
|
|
|
|
M(SettingOverflowMode<false>, set_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
2014-07-07 18:32:20 +00:00
|
|
|
|
/** Ограничения для максимального размера множества, получающегося при выполнении секции IN. */ \
|
|
|
|
|
M(SettingUInt64, max_rows_in_join, 0) \
|
|
|
|
|
M(SettingUInt64, max_bytes_in_join, 0) \
|
|
|
|
|
M(SettingOverflowMode<false>, join_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
|
|
|
|
/** Ограничения для максимального размера передаваемой внешней таблицы, получающейся при выполнении секции GLOBAL IN/JOIN. */ \
|
2014-05-15 10:24:03 +00:00
|
|
|
|
M(SettingUInt64, max_rows_to_transfer, 0) \
|
|
|
|
|
M(SettingUInt64, max_bytes_to_transfer, 0) \
|
|
|
|
|
M(SettingOverflowMode<false>, transfer_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/** Ограничения для максимального размера запоминаемого состояния при выполнении DISTINCT. */ \
|
|
|
|
|
M(SettingUInt64, max_rows_in_distinct, 0) \
|
|
|
|
|
M(SettingUInt64, max_bytes_in_distinct, 0) \
|
2014-05-03 22:57:43 +00:00
|
|
|
|
M(SettingOverflowMode<false>, distinct_overflow_mode, OverflowMode::THROW) \
|
|
|
|
|
\
|
|
|
|
|
/** Максимальное использование памяти при обработке запроса. 0 - не ограничено. */ \
|
|
|
|
|
M(SettingUInt64, max_memory_usage, 0) \
|
2014-02-17 23:56:45 +00:00
|
|
|
|
|
|
|
|
|
#define DECLARE(TYPE, NAME, DEFAULT) \
|
|
|
|
|
TYPE NAME {DEFAULT};
|
|
|
|
|
|
2014-04-10 17:06:58 +00:00
|
|
|
|
APPLY_FOR_LIMITS(DECLARE)
|
2014-02-17 23:56:45 +00:00
|
|
|
|
|
|
|
|
|
#undef DECLARE
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/// Установить настройку по имени.
|
|
|
|
|
bool trySet(const String & name, const Field & value)
|
|
|
|
|
{
|
|
|
|
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|
|
|
|
else if (name == #NAME) NAME.set(value);
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
if (false) {}
|
2014-04-10 17:06:58 +00:00
|
|
|
|
APPLY_FOR_LIMITS(TRY_SET)
|
2014-02-17 23:56:45 +00:00
|
|
|
|
else
|
|
|
|
|
return false;
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
return true;
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#undef TRY_SET
|
|
|
|
|
}
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/// Установить настройку по имени. Прочитать сериализованное в бинарном виде значение из буфера (для межсерверного взаимодействия).
|
|
|
|
|
bool trySet(const String & name, ReadBuffer & buf)
|
2012-12-24 19:50:22 +00:00
|
|
|
|
{
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|
|
|
|
else if (name == #NAME) NAME.set(buf);
|
|
|
|
|
|
|
|
|
|
if (false) {}
|
2014-04-10 17:06:58 +00:00
|
|
|
|
APPLY_FOR_LIMITS(TRY_SET)
|
2014-02-17 23:56:45 +00:00
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
#undef TRY_SET
|
2012-12-24 19:50:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
/** Установить настройку по имени. Прочитать значение в текстовом виде из строки (например, из конфига, или из параметра URL).
|
|
|
|
|
*/
|
|
|
|
|
bool trySet(const String & name, const String & value)
|
|
|
|
|
{
|
|
|
|
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|
|
|
|
else if (name == #NAME) NAME.set(value);
|
2012-12-24 19:50:22 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
if (false) {}
|
2014-04-10 17:06:58 +00:00
|
|
|
|
APPLY_FOR_LIMITS(TRY_SET)
|
2014-02-17 23:56:45 +00:00
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
return true;
|
2013-02-01 19:02:04 +00:00
|
|
|
|
|
2014-02-17 23:56:45 +00:00
|
|
|
|
#undef TRY_SET
|
|
|
|
|
}
|
2013-02-17 19:54:32 +00:00
|
|
|
|
|
2012-12-24 19:50:22 +00:00
|
|
|
|
private:
|
2014-02-28 01:06:44 +00:00
|
|
|
|
friend struct Settings;
|
2013-02-01 19:02:04 +00:00
|
|
|
|
|
|
|
|
|
/// Записать все настройки в буфер. (В отличие от соответствующего метода в Settings, пустая строка на конце не пишется).
|
2014-02-17 23:56:45 +00:00
|
|
|
|
void serialize(WriteBuffer & buf) const
|
|
|
|
|
{
|
|
|
|
|
#define WRITE(TYPE, NAME, DEFAULT) \
|
|
|
|
|
if (NAME.changed) \
|
|
|
|
|
{ \
|
|
|
|
|
writeStringBinary(#NAME, buf); \
|
|
|
|
|
NAME.write(buf); \
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-10 17:06:58 +00:00
|
|
|
|
APPLY_FOR_LIMITS(WRITE)
|
2014-02-17 23:56:45 +00:00
|
|
|
|
|
|
|
|
|
#undef WRITE
|
|
|
|
|
}
|
2012-12-24 19:50:22 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|