提交 854a2f4c 编写于 作者: A Alexey Milovidov

dbms: added optional section SETTINGS to SELECT query [#METR-16354].

上级 cac3ce7e
...@@ -130,6 +130,18 @@ private: ...@@ -130,6 +130,18 @@ private:
void ignoreWithTotals(); void ignoreWithTotals();
/** Если в запросе SELECT есть секция SETTINGS, то применить настройки из неё и удалить секцию SETTINGS.
* Затем достать настройки из context и поместить их в settings.
*
* Секция SETTINGS - настройки для конкретного запроса.
* Обычно настройки могут быть переданы другими способами, не внутри запроса.
* Но использование такой секции оправдано, если нужно задать настройки для одного подзапроса.
*
* При распределённой обработке запроса, секция SETTINGS не будет передана внутри запроса,
* а настройки будут переданы отдельно, при отправке запроса.
*/
void initSettings();
ASTPtr query_ptr; ASTPtr query_ptr;
ASTSelectQuery & query; ASTSelectQuery & query;
Context context; Context context;
......
...@@ -8,7 +8,7 @@ namespace DB ...@@ -8,7 +8,7 @@ namespace DB
{ {
/** Установить один или несколько параметров, для сессии или глобально. /** Установить один или несколько параметров, для сессии или глобально... или для текущего запроса.
*/ */
class InterpreterSetQuery class InterpreterSetQuery
{ {
...@@ -16,17 +16,36 @@ public: ...@@ -16,17 +16,36 @@ public:
InterpreterSetQuery(ASTPtr query_ptr_, Context & context_) InterpreterSetQuery(ASTPtr query_ptr_, Context & context_)
: query_ptr(query_ptr_), context(context_) {} : query_ptr(query_ptr_), context(context_) {}
/** Обычный запрос SET. Задать настройку на сессию или глобальную (если указано GLOBAL).
*/
void execute() void execute()
{ {
ASTSetQuery & ast = typeid_cast<ASTSetQuery &>(*query_ptr); ASTSetQuery & ast = typeid_cast<ASTSetQuery &>(*query_ptr);
Context & target = ast.global ? context.getGlobalContext() : context.getSessionContext(); Context & target = ast.global ? context.getGlobalContext() : context.getSessionContext();
executeImpl(ast, target);
}
/** Задать настроку для текущего контекста (контекста запроса).
* Используется для интерпретации секции SETTINGS в запросе SELECT.
*/
void executeForCurrentContext()
{
ASTSetQuery & ast = typeid_cast<ASTSetQuery &>(*query_ptr);
executeImpl(ast, context);
}
private:
ASTPtr query_ptr;
Context & context;
void executeImpl(ASTSetQuery & ast, Context & target)
{
/** Значение readonly понимается следующим образом: /** Значение readonly понимается следующим образом:
* 0 - можно всё. * 0 - можно всё.
* 1 - можно делать только запросы на чтение; в том числе, нельзя менять настройки. * 1 - можно делать только запросы на чтение; в том числе, нельзя менять настройки.
* 2 - можно делать только запросы на чтение и можно менять настройки, кроме настройки readonly. * 2 - можно делать только запросы на чтение и можно менять настройки, кроме настройки readonly.
*/ */
if (context.getSettingsRef().limits.readonly == 1) if (context.getSettingsRef().limits.readonly == 1)
throw Exception("Cannot execute SET query in readonly mode", ErrorCodes::READONLY); throw Exception("Cannot execute SET query in readonly mode", ErrorCodes::READONLY);
...@@ -39,10 +58,6 @@ public: ...@@ -39,10 +58,6 @@ public:
for (ASTSetQuery::Changes::const_iterator it = ast.changes.begin(); it != ast.changes.end(); ++it) for (ASTSetQuery::Changes::const_iterator it = ast.changes.begin(); it != ast.changes.end(); ++it)
target.setSetting(it->name, it->value); target.setSetting(it->name, it->value);
} }
private:
ASTPtr query_ptr;
Context & context;
}; };
......
...@@ -51,6 +51,7 @@ public: ...@@ -51,6 +51,7 @@ public:
ASTPtr order_expression_list; ASTPtr order_expression_list;
ASTPtr limit_offset; ASTPtr limit_offset;
ASTPtr limit_length; ASTPtr limit_length;
ASTPtr settings;
ASTPtr next_union_all; /// Следующий запрос SELECT в цепочке UNION ALL, если такой есть ASTPtr next_union_all; /// Следующий запрос SELECT в цепочке UNION ALL, если такой есть
}; };
......
...@@ -12,9 +12,15 @@ namespace DB ...@@ -12,9 +12,15 @@ namespace DB
*/ */
class ParserSetQuery : public IParserBase class ParserSetQuery : public IParserBase
{ {
public:
ParserSetQuery(bool parse_only_internals_ = false) : parse_only_internals(parse_only_internals_) {}
protected: protected:
const char * getName() const { return "SET query"; } const char * getName() const { return "SET query"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected); bool parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_parsed_pos, Expected & expected);
/// Парсить список name = value пар, без SET [GLOBAL].
bool parse_only_internals;
}; };
} }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <DB/Parsers/ASTOrderByElement.h> #include <DB/Parsers/ASTOrderByElement.h>
#include <DB/Interpreters/InterpreterSelectQuery.h> #include <DB/Interpreters/InterpreterSelectQuery.h>
#include <DB/Interpreters/InterpreterSetQuery.h>
#include <DB/Interpreters/ExpressionAnalyzer.h> #include <DB/Interpreters/ExpressionAnalyzer.h>
#include <DB/Storages/StorageView.h> #include <DB/Storages/StorageView.h>
#include <DB/TableFunctions/ITableFunction.h> #include <DB/TableFunctions/ITableFunction.h>
...@@ -39,10 +40,12 @@ InterpreterSelectQuery::~InterpreterSelectQuery() = default; ...@@ -39,10 +40,12 @@ InterpreterSelectQuery::~InterpreterSelectQuery() = default;
void InterpreterSelectQuery::init(BlockInputStreamPtr input, const Names & required_column_names, const NamesAndTypesList & table_column_names) void InterpreterSelectQuery::init(BlockInputStreamPtr input, const Names & required_column_names, const NamesAndTypesList & table_column_names)
{ {
original_max_threads = settings.max_threads;
ProfileEvents::increment(ProfileEvents::SelectQuery); ProfileEvents::increment(ProfileEvents::SelectQuery);
initSettings();
original_max_threads = settings.max_threads;
if (settings.limits.max_subquery_depth && subquery_depth > settings.limits.max_subquery_depth) if (settings.limits.max_subquery_depth && subquery_depth > settings.limits.max_subquery_depth)
throw Exception("Too deep subqueries. Maximum: " + toString(settings.limits.max_subquery_depth), throw Exception("Too deep subqueries. Maximum: " + toString(settings.limits.max_subquery_depth),
ErrorCodes::TOO_DEEP_SUBQUERIES); ErrorCodes::TOO_DEEP_SUBQUERIES);
...@@ -174,7 +177,7 @@ void InterpreterSelectQuery::initQueryAnalyzer() ...@@ -174,7 +177,7 @@ void InterpreterSelectQuery::initQueryAnalyzer()
InterpreterSelectQuery::InterpreterSelectQuery(ASTPtr query_ptr_, const Context & context_, QueryProcessingStage::Enum to_stage_, InterpreterSelectQuery::InterpreterSelectQuery(ASTPtr query_ptr_, const Context & context_, QueryProcessingStage::Enum to_stage_,
size_t subquery_depth_, BlockInputStreamPtr input_, bool is_union_all_head_) size_t subquery_depth_, BlockInputStreamPtr input_, bool is_union_all_head_)
: query_ptr(query_ptr_), query(typeid_cast<ASTSelectQuery &>(*query_ptr)), : query_ptr(query_ptr_), query(typeid_cast<ASTSelectQuery &>(*query_ptr)),
context(context_), settings(context.getSettings()), to_stage(to_stage_), subquery_depth(subquery_depth_), context(context_), to_stage(to_stage_), subquery_depth(subquery_depth_),
is_first_select_inside_union_all(is_union_all_head_ && !query.next_union_all.isNull()), is_first_select_inside_union_all(is_union_all_head_ && !query.next_union_all.isNull()),
log(&Logger::get("InterpreterSelectQuery")) log(&Logger::get("InterpreterSelectQuery"))
{ {
...@@ -185,7 +188,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(ASTPtr query_ptr_, const Context ...@@ -185,7 +188,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(ASTPtr query_ptr_, const Context
const Names & required_column_names_, const Names & required_column_names_,
QueryProcessingStage::Enum to_stage_, size_t subquery_depth_, BlockInputStreamPtr input_) QueryProcessingStage::Enum to_stage_, size_t subquery_depth_, BlockInputStreamPtr input_)
: query_ptr(query_ptr_), query(typeid_cast<ASTSelectQuery &>(*query_ptr)), : query_ptr(query_ptr_), query(typeid_cast<ASTSelectQuery &>(*query_ptr)),
context(context_), settings(context.getSettings()), to_stage(to_stage_), subquery_depth(subquery_depth_), context(context_), to_stage(to_stage_), subquery_depth(subquery_depth_),
is_first_select_inside_union_all(!query.next_union_all.isNull()), is_first_select_inside_union_all(!query.next_union_all.isNull()),
log(&Logger::get("InterpreterSelectQuery")) log(&Logger::get("InterpreterSelectQuery"))
{ {
...@@ -196,7 +199,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(ASTPtr query_ptr_, const Context ...@@ -196,7 +199,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(ASTPtr query_ptr_, const Context
const Names & required_column_names_, const Names & required_column_names_,
const NamesAndTypesList & table_column_names, QueryProcessingStage::Enum to_stage_, size_t subquery_depth_, BlockInputStreamPtr input_) const NamesAndTypesList & table_column_names, QueryProcessingStage::Enum to_stage_, size_t subquery_depth_, BlockInputStreamPtr input_)
: query_ptr(query_ptr_), query(typeid_cast<ASTSelectQuery &>(*query_ptr)), : query_ptr(query_ptr_), query(typeid_cast<ASTSelectQuery &>(*query_ptr)),
context(context_), settings(context.getSettings()), to_stage(to_stage_), subquery_depth(subquery_depth_), context(context_), to_stage(to_stage_), subquery_depth(subquery_depth_),
is_first_select_inside_union_all(!query.next_union_all.isNull()), is_first_select_inside_union_all(!query.next_union_all.isNull()),
log(&Logger::get("InterpreterSelectQuery")) log(&Logger::get("InterpreterSelectQuery"))
{ {
...@@ -1028,4 +1031,21 @@ void InterpreterSelectQuery::ignoreWithTotals() ...@@ -1028,4 +1031,21 @@ void InterpreterSelectQuery::ignoreWithTotals()
} }
void InterpreterSelectQuery::initSettings()
{
if (query.settings)
{
InterpreterSetQuery(query.settings, context).executeForCurrentContext();
auto it = std::find(query.children.begin(), query.children.end(), query.settings);
if (query.children.end() == it)
throw Exception("Logical error: cannot find query.settings element in query.children", ErrorCodes::LOGICAL_ERROR);
query.children.erase(it);
query.settings = nullptr;
}
settings = context.getSettings();
}
} }
...@@ -164,6 +164,7 @@ ASTPtr ASTSelectQuery::clone() const ...@@ -164,6 +164,7 @@ ASTPtr ASTSelectQuery::clone() const
CLONE(order_expression_list) CLONE(order_expression_list)
CLONE(limit_offset) CLONE(limit_offset)
CLONE(limit_length) CLONE(limit_length)
CLONE(settings)
CLONE(format) CLONE(format)
CLONE(next_union_all) CLONE(next_union_all)
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <DB/Parsers/ExpressionElementParsers.h> #include <DB/Parsers/ExpressionElementParsers.h>
#include <DB/Parsers/ExpressionListParsers.h> #include <DB/Parsers/ExpressionListParsers.h>
#include <DB/Parsers/ParserJoin.h> #include <DB/Parsers/ParserJoin.h>
#include <DB/Parsers/ParserSetQuery.h>
#include <DB/Parsers/ParserSelectQuery.h> #include <DB/Parsers/ParserSelectQuery.h>
...@@ -37,6 +38,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_p ...@@ -37,6 +38,7 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_p
ParserString s_having("HAVING", true, true); ParserString s_having("HAVING", true, true);
ParserString s_order("ORDER", true, true); ParserString s_order("ORDER", true, true);
ParserString s_limit("LIMIT", true, true); ParserString s_limit("LIMIT", true, true);
ParserString s_settings("SETTINGS", true, true);
ParserString s_format("FORMAT", true, true); ParserString s_format("FORMAT", true, true);
ParserString s_union("UNION", true, true); ParserString s_union("UNION", true, true);
ParserString s_all("ALL", true, true); ParserString s_all("ALL", true, true);
...@@ -281,6 +283,19 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_p ...@@ -281,6 +283,19 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_p
} }
} }
/// SETTINGS key1 = value1, key2 = value2, ...
if (s_settings.ignore(pos, end, max_parsed_pos, expected))
{
ws.ignore(pos, end);
ParserSetQuery parser_settings(true);
if (!parser_settings.parse(pos, end, select_query->settings, max_parsed_pos, expected))
return false;
ws.ignore(pos, end);
}
/// FORMAT format_name /// FORMAT format_name
if (s_format.ignore(pos, end, max_parsed_pos, expected)) if (s_format.ignore(pos, end, max_parsed_pos, expected))
{ {
...@@ -339,6 +354,8 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_p ...@@ -339,6 +354,8 @@ bool ParserSelectQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_p
select_query->children.push_back(select_query->limit_offset); select_query->children.push_back(select_query->limit_offset);
if (select_query->limit_length) if (select_query->limit_length)
select_query->children.push_back(select_query->limit_length); select_query->children.push_back(select_query->limit_length);
if (select_query->settings)
select_query->children.push_back(select_query->settings);
if (select_query->format) if (select_query->format)
select_query->children.push_back(select_query->format); select_query->children.push_back(select_query->format);
if (select_query->next_union_all) if (select_query->next_union_all)
......
...@@ -50,18 +50,24 @@ bool ParserSetQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_pars ...@@ -50,18 +50,24 @@ bool ParserSetQuery::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max_pars
Pos begin = pos; Pos begin = pos;
ParserWhiteSpaceOrComments ws; ParserWhiteSpaceOrComments ws;
ParserString s_set("SET", true, true);
ParserString s_global("GLOBAL", true, true);
ParserString s_comma(","); ParserString s_comma(",");
ws.ignore(pos, end); bool global = false;
if (!s_set.ignore(pos, end, max_parsed_pos, expected)) if (!parse_only_internals)
return false; {
ParserString s_set("SET", true, true);
ParserString s_global("GLOBAL", true, true);
ws.ignore(pos, end); ws.ignore(pos, end);
bool global = s_global.ignore(pos, end, max_parsed_pos, expected); if (!s_set.ignore(pos, end, max_parsed_pos, expected))
return false;
ws.ignore(pos, end);
global = s_global.ignore(pos, end, max_parsed_pos, expected);
}
ASTSetQuery::Changes changes; ASTSetQuery::Changes changes;
......
...@@ -211,6 +211,20 @@ void formatAST(const ASTSelectQuery & ast, std::ostream & s, size_t indent, bo ...@@ -211,6 +211,20 @@ void formatAST(const ASTSelectQuery & ast, std::ostream & s, size_t indent, bo
formatAST(*ast.limit_length, s, indent, hilite, one_line); formatAST(*ast.limit_length, s, indent, hilite, one_line);
} }
if (ast.settings)
{
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "SETTINGS " << (hilite ? hilite_none : "");
const ASTSetQuery & ast_set = typeid_cast<const ASTSetQuery &>(*ast.settings);
for (ASTSetQuery::Changes::const_iterator it = ast_set.changes.begin(); it != ast_set.changes.end(); ++it)
{
if (it != ast_set.changes.begin())
s << ", ";
s << it->name << " = " << apply_visitor(FieldVisitorToString(), it->value);
}
}
if (ast.format) if (ast.format)
{ {
s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "FORMAT " << (hilite ? hilite_none : ""); s << (hilite ? hilite_keyword : "") << nl_or_ws << indent_str << "FORMAT " << (hilite ? hilite_none : "");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册