diff --git a/src/Interpreters/executeQuery.cpp b/src/Interpreters/executeQuery.cpp index 5feff841ca9..7697bbda36b 100644 --- a/src/Interpreters/executeQuery.cpp +++ b/src/Interpreters/executeQuery.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -337,6 +338,27 @@ static std::tuple executeQueryImpl( /// TODO Parser should fail early when max_query_size limit is reached. 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()) + { + if (auto new_settings = select_query->settings()) + InterpreterSetQuery(new_settings, context).executeForCurrentContext(); + } + else if (const auto * select_with_union_query = ast->as()) + { + if (!select_with_union_query->list_of_selects->children.empty()) + { + if (auto new_settings = select_with_union_query->list_of_selects->children.back()->as()->settings()) + InterpreterSetQuery(new_settings, context).executeForCurrentContext(); + } + } + else if (const auto * query_with_output = dynamic_cast(ast.get())) + { + if (query_with_output->settings_ast) + InterpreterSetQuery(query_with_output->settings_ast, context).executeForCurrentContext(); + } + auto * insert_query = ast->as(); if (insert_query && insert_query->settings_ast) @@ -802,12 +824,12 @@ BlockIO executeQuery( } BlockIO executeQuery( - const String & query, - Context & context, - bool internal, - QueryProcessingStage::Enum stage, - bool may_have_embedded_data, - bool allow_processors) + const String & query, + Context & context, + bool internal, + QueryProcessingStage::Enum stage, + bool may_have_embedded_data, + bool allow_processors) { BlockIO res = executeQuery(query, context, internal, stage, may_have_embedded_data); @@ -876,7 +898,6 @@ void executeQuery( } else if (streams.in) { - /// FIXME: try to prettify this cast using `as<>()` const auto * ast_query_with_output = dynamic_cast(ast.get()); WriteBuffer * out_buf = &ostr; @@ -895,9 +916,6 @@ void executeQuery( ? getIdentifierName(ast_query_with_output->format) : 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()); /// Save previous progress callback if any. TODO Do it more conveniently. @@ -936,9 +954,6 @@ void executeQuery( ? getIdentifierName(ast_query_with_output->format) : 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()) { pipeline.addSimpleTransform([](const Block & header) diff --git a/tests/queries/0_stateless/01553_settings_early_apply.reference b/tests/queries/0_stateless/01553_settings_early_apply.reference new file mode 100644 index 00000000000..3dad208be5d --- /dev/null +++ b/tests/queries/0_stateless/01553_settings_early_apply.reference @@ -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 +} diff --git a/tests/queries/0_stateless/01553_settings_early_apply.sql b/tests/queries/0_stateless/01553_settings_early_apply.sql new file mode 100644 index 00000000000..48178c38f33 --- /dev/null +++ b/tests/queries/0_stateless/01553_settings_early_apply.sql @@ -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;