Apply SETTINGS clause earlier

This commit is contained in:
Alexey Milovidov 2020-11-02 22:23:26 +03:00
parent 70982fdc54
commit 878fd466c5
3 changed files with 79 additions and 13 deletions

View File

@ -17,6 +17,7 @@
#include <Parsers/ASTInsertQuery.h> #include <Parsers/ASTInsertQuery.h>
#include <Parsers/ASTSelectQuery.h> #include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTSelectWithUnionQuery.h>
#include <Parsers/ASTShowProcesslistQuery.h> #include <Parsers/ASTShowProcesslistQuery.h>
#include <Parsers/ASTIdentifier.h> #include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTLiteral.h> #include <Parsers/ASTLiteral.h>
@ -337,6 +338,27 @@ static std::tuple<ASTPtr, BlockIO> executeQueryImpl(
/// TODO Parser should fail early when max_query_size limit is reached. /// TODO Parser should fail early when max_query_size limit is reached.
ast = parseQuery(parser, begin, end, "", max_query_size, settings.max_parser_depth); ast = parseQuery(parser, begin, end, "", max_query_size, settings.max_parser_depth);
/// Interpret SETTINGS clauses as early as possible (before invoking the corresponding interpreter),
/// to allow settings to take effect.
if (const auto * select_query = ast->as<ASTSelectQuery>())
{
if (auto new_settings = select_query->settings())
InterpreterSetQuery(new_settings, context).executeForCurrentContext();
}
else if (const auto * select_with_union_query = ast->as<ASTSelectWithUnionQuery>())
{
if (!select_with_union_query->list_of_selects->children.empty())
{
if (auto new_settings = select_with_union_query->list_of_selects->children.back()->as<ASTSelectQuery>()->settings())
InterpreterSetQuery(new_settings, context).executeForCurrentContext();
}
}
else if (const auto * query_with_output = dynamic_cast<const ASTQueryWithOutput *>(ast.get()))
{
if (query_with_output->settings_ast)
InterpreterSetQuery(query_with_output->settings_ast, context).executeForCurrentContext();
}
auto * insert_query = ast->as<ASTInsertQuery>(); auto * insert_query = ast->as<ASTInsertQuery>();
if (insert_query && insert_query->settings_ast) if (insert_query && insert_query->settings_ast)
@ -802,12 +824,12 @@ BlockIO executeQuery(
} }
BlockIO executeQuery( BlockIO executeQuery(
const String & query, const String & query,
Context & context, Context & context,
bool internal, bool internal,
QueryProcessingStage::Enum stage, QueryProcessingStage::Enum stage,
bool may_have_embedded_data, bool may_have_embedded_data,
bool allow_processors) bool allow_processors)
{ {
BlockIO res = executeQuery(query, context, internal, stage, may_have_embedded_data); BlockIO res = executeQuery(query, context, internal, stage, may_have_embedded_data);
@ -876,7 +898,6 @@ void executeQuery(
} }
else if (streams.in) else if (streams.in)
{ {
/// FIXME: try to prettify this cast using `as<>()`
const auto * ast_query_with_output = dynamic_cast<const ASTQueryWithOutput *>(ast.get()); const auto * ast_query_with_output = dynamic_cast<const ASTQueryWithOutput *>(ast.get());
WriteBuffer * out_buf = &ostr; WriteBuffer * out_buf = &ostr;
@ -895,9 +916,6 @@ void executeQuery(
? getIdentifierName(ast_query_with_output->format) ? getIdentifierName(ast_query_with_output->format)
: context.getDefaultFormat(); : context.getDefaultFormat();
if (ast_query_with_output && ast_query_with_output->settings_ast)
InterpreterSetQuery(ast_query_with_output->settings_ast, context).executeForCurrentContext();
BlockOutputStreamPtr out = context.getOutputFormat(format_name, *out_buf, streams.in->getHeader()); BlockOutputStreamPtr out = context.getOutputFormat(format_name, *out_buf, streams.in->getHeader());
/// Save previous progress callback if any. TODO Do it more conveniently. /// Save previous progress callback if any. TODO Do it more conveniently.
@ -936,9 +954,6 @@ void executeQuery(
? getIdentifierName(ast_query_with_output->format) ? getIdentifierName(ast_query_with_output->format)
: context.getDefaultFormat(); : context.getDefaultFormat();
if (ast_query_with_output && ast_query_with_output->settings_ast)
InterpreterSetQuery(ast_query_with_output->settings_ast, context).executeForCurrentContext();
if (!pipeline.isCompleted()) if (!pipeline.isCompleted())
{ {
pipeline.addSimpleTransform([](const Block & header) pipeline.addSimpleTransform([](const Block & header)

View File

@ -0,0 +1,43 @@
number
0
number
1
0
1
2
3
4
5
6
7
8
9
{
"meta":
[
{
"name": "number",
"type": "UInt64"
}
],
"data":
[
["0"],
["1"],
["2"],
["3"],
["4"],
["5"],
["6"],
["7"],
["8"],
["9"]
],
"rows": 10,
"rows_before_limit_at_least": 10
}

View File

@ -0,0 +1,8 @@
select * from numbers(100) settings max_result_rows = 1; -- { serverError 396 }
select * from numbers(100) FORMAT JSON settings max_result_rows = 1; -- { serverError 396 }
SET max_result_rows = 1;
select * from numbers(10); -- { serverError 396 }
select * from numbers(10) SETTINGS result_overflow_mode = 'break', max_block_size = 1 FORMAT PrettySpaceNoEscapes;
select * from numbers(10) settings max_result_rows = 10;
select * from numbers(10) FORMAT JSONCompact settings max_result_rows = 10, output_format_write_statistics = 0;