mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-05 23:31:24 +00:00
195 lines
8.2 KiB
C++
195 lines
8.2 KiB
C++
|
#pragma once
|
|||
|
|
|||
|
#include <Poco/Timespan.h>
|
|||
|
#include <DB/Core/Defines.h>
|
|||
|
#include <DB/Core/Field.h>
|
|||
|
#include <DB/Interpreters/SettingsCommon.h>
|
|||
|
|
|||
|
|
|||
|
namespace DB
|
|||
|
{
|
|||
|
|
|||
|
/** Ограничения при выполнении запроса - часть настроек.
|
|||
|
* Используются, чтобы обеспечить более безопасное исполнение запросов из пользовательского интерфейса.
|
|||
|
* В основном, ограничения проверяются на каждый блок (а не на каждую строку). То есть, ограничения могут быть немного нарушены.
|
|||
|
* Почти все ограничения действуют только на SELECT-ы.
|
|||
|
* Почти все ограничения действуют на каждый поток по отдельности.
|
|||
|
*/
|
|||
|
struct Limits
|
|||
|
{
|
|||
|
/** Перечисление ограничений: тип, имя, значение по-умолчанию.
|
|||
|
* По-умолчанию: всё не ограничено, кроме довольно слабых ограничений на глубину рекурсии и размер выражений.
|
|||
|
*/
|
|||
|
|
|||
|
#define APPLY_FOR_LIMITS(M) \
|
|||
|
/** Ограничения на чтение из самых "глубоких" источников. \
|
|||
|
* То есть, только в самом глубоком подзапросе. \
|
|||
|
* При чтении с удалённого сервера, проверяется только на удалённом сервере. \
|
|||
|
*/ \
|
|||
|
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_bytes_before_external_group_by, 0) \
|
|||
|
\
|
|||
|
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_bytes_before_external_sort, 0) \
|
|||
|
\
|
|||
|
/** Ограничение на размер результата. \
|
|||
|
* Проверяются также для подзапросов и на удалённых серверах. \
|
|||
|
*/ \
|
|||
|
M(SettingUInt64, max_result_rows, 0) \
|
|||
|
M(SettingUInt64, max_result_bytes, 0) \
|
|||
|
M(SettingOverflowMode<false>, result_overflow_mode, OverflowMode::THROW) \
|
|||
|
\
|
|||
|
/* TODO: Проверять также при слиянии и финализации агрегатных функций. */ \
|
|||
|
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, 50000) /** а уже после парсинга запроса. */ \
|
|||
|
\
|
|||
|
/** 0 - можно всё. 1 - только запросы на чтение. 2 - только запросы на чтение, а также изменение настроек, кроме настройки readonly. */ \
|
|||
|
M(SettingUInt64, readonly, 0) \
|
|||
|
\
|
|||
|
/** Ограничения для максимального размера множества, получающегося при выполнении секции IN. */ \
|
|||
|
M(SettingUInt64, max_rows_in_set, 0) \
|
|||
|
M(SettingUInt64, max_bytes_in_set, 0) \
|
|||
|
M(SettingOverflowMode<false>, set_overflow_mode, OverflowMode::THROW) \
|
|||
|
\
|
|||
|
/** Ограничения для максимального размера множества, получающегося при выполнении секции 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. */ \
|
|||
|
M(SettingUInt64, max_rows_to_transfer, 0) \
|
|||
|
M(SettingUInt64, max_bytes_to_transfer, 0) \
|
|||
|
M(SettingOverflowMode<false>, transfer_overflow_mode, OverflowMode::THROW) \
|
|||
|
\
|
|||
|
/** Ограничения для максимального размера запоминаемого состояния при выполнении DISTINCT. */ \
|
|||
|
M(SettingUInt64, max_rows_in_distinct, 0) \
|
|||
|
M(SettingUInt64, max_bytes_in_distinct, 0) \
|
|||
|
M(SettingOverflowMode<false>, distinct_overflow_mode, OverflowMode::THROW) \
|
|||
|
\
|
|||
|
/** Максимальное использование памяти при обработке запроса. 0 - не ограничено. */ \
|
|||
|
M(SettingUInt64, max_memory_usage, 0) /* На один запрос */ \
|
|||
|
/* Суммарно на одновременно выполняющиеся запросы одного пользователя */ \
|
|||
|
M(SettingUInt64, max_memory_usage_for_user, 0) \
|
|||
|
/* Суммарно на все одновременно выполняющиеся запросы */ \
|
|||
|
M(SettingUInt64, max_memory_usage_for_all_queries, 0) \
|
|||
|
\
|
|||
|
/** Максимальная скорость обмена данными по сети в байтах в секунду. 0 - не ограничена. */ \
|
|||
|
M(SettingUInt64, max_network_bandwidth, 0) \
|
|||
|
/** Максимальное количество байт на приём или передачу по сети, в рамках запроса. */ \
|
|||
|
M(SettingUInt64, max_network_bytes, 0) \
|
|||
|
|
|||
|
#define DECLARE(TYPE, NAME, DEFAULT) \
|
|||
|
TYPE NAME {DEFAULT};
|
|||
|
|
|||
|
APPLY_FOR_LIMITS(DECLARE)
|
|||
|
|
|||
|
#undef DECLARE
|
|||
|
|
|||
|
/// Установить настройку по имени.
|
|||
|
bool trySet(const String & name, const Field & value)
|
|||
|
{
|
|||
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|||
|
else if (name == #NAME) NAME.set(value);
|
|||
|
|
|||
|
if (false) {}
|
|||
|
APPLY_FOR_LIMITS(TRY_SET)
|
|||
|
else
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
|
|||
|
#undef TRY_SET
|
|||
|
}
|
|||
|
|
|||
|
/// Установить настройку по имени. Прочитать сериализованное в бинарном виде значение из буфера (для межсерверного взаимодействия).
|
|||
|
bool trySet(const String & name, ReadBuffer & buf)
|
|||
|
{
|
|||
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|||
|
else if (name == #NAME) NAME.set(buf);
|
|||
|
|
|||
|
if (false) {}
|
|||
|
APPLY_FOR_LIMITS(TRY_SET)
|
|||
|
else
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
|
|||
|
#undef TRY_SET
|
|||
|
}
|
|||
|
|
|||
|
/// Пропустить сериализованное в бинарном виде значение из буфера.
|
|||
|
bool tryIgnore(const String & name, ReadBuffer & buf)
|
|||
|
{
|
|||
|
#define TRY_IGNORE(TYPE, NAME, DEFAULT) \
|
|||
|
else if (name == #NAME) decltype(NAME)(DEFAULT).set(buf);
|
|||
|
|
|||
|
if (false) {}
|
|||
|
APPLY_FOR_LIMITS(TRY_IGNORE)
|
|||
|
else
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
|
|||
|
#undef TRY_IGNORE
|
|||
|
}
|
|||
|
|
|||
|
/** Установить настройку по имени. Прочитать значение в текстовом виде из строки (например, из конфига, или из параметра URL).
|
|||
|
*/
|
|||
|
bool trySet(const String & name, const String & value)
|
|||
|
{
|
|||
|
#define TRY_SET(TYPE, NAME, DEFAULT) \
|
|||
|
else if (name == #NAME) NAME.set(value);
|
|||
|
|
|||
|
if (false) {}
|
|||
|
APPLY_FOR_LIMITS(TRY_SET)
|
|||
|
else
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
|
|||
|
#undef TRY_SET
|
|||
|
}
|
|||
|
|
|||
|
private:
|
|||
|
friend struct Settings;
|
|||
|
|
|||
|
/// Записать все настройки в буфер. (В отличие от соответствующего метода в Settings, пустая строка на конце не пишется).
|
|||
|
void serialize(WriteBuffer & buf) const
|
|||
|
{
|
|||
|
#define WRITE(TYPE, NAME, DEFAULT) \
|
|||
|
if (NAME.changed) \
|
|||
|
{ \
|
|||
|
writeStringBinary(#NAME, buf); \
|
|||
|
NAME.write(buf); \
|
|||
|
}
|
|||
|
|
|||
|
APPLY_FOR_LIMITS(WRITE)
|
|||
|
|
|||
|
#undef WRITE
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
}
|