diff --git a/dbms/programs/client/Client.cpp b/dbms/programs/client/Client.cpp index 0edffbcf4de148194f18f6b9bb43048f8a7dd840..66acc7fcea56fea182c0ecdcd0273ecc9f3796ab 100644 --- a/dbms/programs/client/Client.cpp +++ b/dbms/programs/client/Client.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -1206,6 +1207,10 @@ private: const auto & id = typeid_cast(*query_with_output->format); current_format = id.name; } + if (query_with_output->settings) + { + InterpreterSetQuery(query_with_output->settings, context).executeForCurrentContext(); + } } if (has_vertical_output_suffix) diff --git a/dbms/src/Interpreters/executeQuery.cpp b/dbms/src/Interpreters/executeQuery.cpp index 3911e437fa63f14cea5ffac36cb8c1a15b7f2816..435de7c6f1f2dc4b1bc4e7dde0d0fb429014b083 100644 --- a/dbms/src/Interpreters/executeQuery.cpp +++ b/dbms/src/Interpreters/executeQuery.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "DNSCacheUpdater.h" @@ -502,6 +503,9 @@ void executeQuery( ? *getIdentifierName(ast_query_with_output->format) : context.getDefaultFormat(); + if (ast_query_with_output && ast_query_with_output->settings) + InterpreterSetQuery(ast_query_with_output->settings, context).executeForCurrentContext(); + BlockOutputStreamPtr out = context.getOutputFormat(format_name, *out_buf, streams.in->getHeader()); if (auto stream = dynamic_cast(streams.in.get())) diff --git a/dbms/src/Parsers/ASTQueryWithOutput.cpp b/dbms/src/Parsers/ASTQueryWithOutput.cpp index 62abe5de9e11707b55359613219f05c1cd695e81..fd6957c436b132b0b0da504abfe0c5d1188f742d 100644 --- a/dbms/src/Parsers/ASTQueryWithOutput.cpp +++ b/dbms/src/Parsers/ASTQueryWithOutput.cpp @@ -15,6 +15,11 @@ void ASTQueryWithOutput::cloneOutputOptions(ASTQueryWithOutput & cloned) const cloned.format = format->clone(); cloned.children.push_back(cloned.format); } + if (settings) + { + cloned.settings = settings->clone(); + cloned.children.push_back(cloned.settings); + } } void ASTQueryWithOutput::formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const @@ -34,6 +39,12 @@ void ASTQueryWithOutput::formatImpl(const FormatSettings & s, FormatState & stat s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "FORMAT " << (s.hilite ? hilite_none : ""); format->formatImpl(s, state, frame); } + + if (settings) + { + s.ostr << (s.hilite ? hilite_keyword : "") << s.nl_or_ws << indent_str << "SETTINGS " << (s.hilite ? hilite_none : ""); + settings->formatImpl(s, state, frame); + } } bool ASTQueryWithOutput::resetOutputASTIfExist(IAST & ast) @@ -42,6 +53,7 @@ bool ASTQueryWithOutput::resetOutputASTIfExist(IAST & ast) { ast_with_output->format.reset(); ast_with_output->out_file.reset(); + ast_with_output->settings.reset(); return true; } diff --git a/dbms/src/Parsers/ASTQueryWithOutput.h b/dbms/src/Parsers/ASTQueryWithOutput.h index 0660b1bec636cdbbdd7511621097504cb4ed4b45..ec525b3aca9b85b2dff158e4ddc88ddf5b6249b0 100644 --- a/dbms/src/Parsers/ASTQueryWithOutput.h +++ b/dbms/src/Parsers/ASTQueryWithOutput.h @@ -6,13 +6,15 @@ namespace DB { -/** Query with output options (supporting [INTO OUTFILE 'file_name'] [FORMAT format_name] suffix). +/** Query with output options + * (supporting [INTO OUTFILE 'file_name'] [FORMAT format_name] [SETTINGS key1 = value1, key2 = value2, ...] suffix). */ class ASTQueryWithOutput : public IAST { public: ASTPtr out_file; ASTPtr format; + ASTPtr settings; void formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const final; diff --git a/dbms/src/Parsers/ParserQueryWithOutput.cpp b/dbms/src/Parsers/ParserQueryWithOutput.cpp index 2e1a5ff529a13e8c702cf7b9bbceed4774cdc8d7..830060cb9537a7482bf93fd014fb94262d07b9cd 100644 --- a/dbms/src/Parsers/ParserQueryWithOutput.cpp +++ b/dbms/src/Parsers/ParserQueryWithOutput.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -81,6 +82,16 @@ bool ParserQueryWithOutput::parseImpl(Pos & pos, ASTPtr & node, Expected & expec query_with_output.children.push_back(query_with_output.format); } + // SETTINGS key1 = value1, key2 = value2, ... + ParserKeyword s_settings("SETTINGS"); + if (s_settings.ignore(pos, expected)) + { + ParserSetQuery parser_settings(true); + if (!parser_settings.parse(pos, query_with_output.settings, expected)) + return false; + query_with_output.children.push_back(query_with_output.settings); + } + if (explain_ast) { node = std::make_shared(); diff --git a/dbms/src/Parsers/ParserQueryWithOutput.h b/dbms/src/Parsers/ParserQueryWithOutput.h index b0d08465354d7658a7ed0d8a0e728cb7a7939525..3163bc38437cbd209962eb0239b523bb6591fc92 100644 --- a/dbms/src/Parsers/ParserQueryWithOutput.h +++ b/dbms/src/Parsers/ParserQueryWithOutput.h @@ -7,7 +7,7 @@ namespace DB { -/// Parse queries supporting [INTO OUTFILE 'file_name'] [FORMAT format_name] suffix. +/// Parse queries supporting [INTO OUTFILE 'file_name'] [FORMAT format_name] [SETTINGS key1 = value1, key2 = value2, ...] suffix. class ParserQueryWithOutput : public IParserBase { public: