ClickHouse/dbms/include/DB/Interpreters/Limits.h

195 lines
8.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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
}
};
}