mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-11 17:02:25 +00:00
Fix SETTINGS parsing after FORMAT for SELECT queries
There are two possible ways to pass the SETTINGS clause: - SELECT 1 FORMAT Null SETTINGS max_block_size = 1 - SELECT 1 SETTINGS max_block_size = 1[ FORMAT Null] And when the SETTINGS goes after FORMAT it is parsed in ParserQueryWithOutput, and these settings are not applied for the query from the ASTSelectQuery::initSettings() So propagate settings from the ParserQueryWithOutput to the ASTSelectQuery settings.
This commit is contained in:
parent
fde8c87a1f
commit
781f1597f2
@ -14,12 +14,15 @@
|
|||||||
#include <Parsers/ParserWatchQuery.h>
|
#include <Parsers/ParserWatchQuery.h>
|
||||||
#include <Parsers/ParserSetQuery.h>
|
#include <Parsers/ParserSetQuery.h>
|
||||||
#include <Parsers/ASTExplainQuery.h>
|
#include <Parsers/ASTExplainQuery.h>
|
||||||
|
#include <Parsers/ASTSelectWithUnionQuery.h>
|
||||||
|
#include <Parsers/ASTSetQuery.h>
|
||||||
#include <Parsers/ParserShowAccessEntitiesQuery.h>
|
#include <Parsers/ParserShowAccessEntitiesQuery.h>
|
||||||
#include <Parsers/ParserShowAccessQuery.h>
|
#include <Parsers/ParserShowAccessQuery.h>
|
||||||
#include <Parsers/ParserShowCreateAccessEntityQuery.h>
|
#include <Parsers/ParserShowCreateAccessEntityQuery.h>
|
||||||
#include <Parsers/ParserShowGrantsQuery.h>
|
#include <Parsers/ParserShowGrantsQuery.h>
|
||||||
#include <Parsers/ParserShowPrivilegesQuery.h>
|
#include <Parsers/ParserShowPrivilegesQuery.h>
|
||||||
#include <Parsers/ParserExplainQuery.h>
|
#include <Parsers/ParserExplainQuery.h>
|
||||||
|
#include <Parsers/QueryWithOutputSettingsPushDownVisitor.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
@ -107,6 +110,14 @@ bool ParserQueryWithOutput::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
|
|||||||
if (!parser_settings.parse(pos, query_with_output.settings_ast, expected))
|
if (!parser_settings.parse(pos, query_with_output.settings_ast, expected))
|
||||||
return false;
|
return false;
|
||||||
query_with_output.children.push_back(query_with_output.settings_ast);
|
query_with_output.children.push_back(query_with_output.settings_ast);
|
||||||
|
|
||||||
|
// SETTINGS after FORMAT is not parsed by the SELECT parser (ParserSelectQuery)
|
||||||
|
// Pass them manually, to apply in InterpreterSelectQuery::initSettings()
|
||||||
|
if (query->as<ASTSelectWithUnionQuery>())
|
||||||
|
{
|
||||||
|
QueryWithOutputSettingsPushDownVisitor::Data data{query_with_output.settings_ast};
|
||||||
|
QueryWithOutputSettingsPushDownVisitor(data).visit(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto * ast = query->as<ASTExplainQuery>())
|
if (auto * ast = query->as<ASTExplainQuery>())
|
||||||
|
56
src/Parsers/QueryWithOutputSettingsPushDownVisitor.cpp
Normal file
56
src/Parsers/QueryWithOutputSettingsPushDownVisitor.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <Common/SettingsChanges.h>
|
||||||
|
#include <Parsers/QueryWithOutputSettingsPushDownVisitor.h>
|
||||||
|
#include <Parsers/ASTSelectWithUnionQuery.h>
|
||||||
|
#include <Parsers/ASTSelectQuery.h>
|
||||||
|
#include <Parsers/ASTSetQuery.h>
|
||||||
|
#include <Parsers/ASTSubquery.h>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
bool QueryWithOutputSettingsPushDownMatcher::needChildVisit(ASTPtr & node, const ASTPtr & child)
|
||||||
|
{
|
||||||
|
if (node->as<ASTSelectWithUnionQuery>())
|
||||||
|
return true;
|
||||||
|
if (node->as<ASTSubquery>())
|
||||||
|
return true;
|
||||||
|
if (child->as<ASTSelectQuery>())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryWithOutputSettingsPushDownMatcher::visit(ASTPtr & ast, Data & data)
|
||||||
|
{
|
||||||
|
if (auto * select_query = ast->as<ASTSelectQuery>())
|
||||||
|
visit(*select_query, ast, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueryWithOutputSettingsPushDownMatcher::visit(ASTSelectQuery & select_query, ASTPtr &, Data & data)
|
||||||
|
{
|
||||||
|
ASTPtr select_settings_ast = select_query.settings();
|
||||||
|
if (!select_settings_ast)
|
||||||
|
{
|
||||||
|
select_query.setExpression(ASTSelectQuery::Expression::SETTINGS, data.settings_ast->clone());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsChanges & select_settings = select_settings_ast->as<ASTSetQuery &>().changes;
|
||||||
|
SettingsChanges & settings = data.settings_ast->as<ASTSetQuery &>().changes;
|
||||||
|
|
||||||
|
for (auto & setting : settings)
|
||||||
|
{
|
||||||
|
auto it = std::find_if(select_settings.begin(), select_settings.end(), [&](auto & select_setting)
|
||||||
|
{
|
||||||
|
return select_setting.name == setting.name;
|
||||||
|
});
|
||||||
|
if (it == select_settings.end())
|
||||||
|
select_settings.push_back(setting);
|
||||||
|
else
|
||||||
|
it->value = setting.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
39
src/Parsers/QueryWithOutputSettingsPushDownVisitor.h
Normal file
39
src/Parsers/QueryWithOutputSettingsPushDownVisitor.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Parsers/IAST.h>
|
||||||
|
#include <Interpreters/InDepthNodeVisitor.h>
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ASTSelectQuery;
|
||||||
|
struct SettingChange;
|
||||||
|
using SettingsChanges = std::vector<SettingChange>;
|
||||||
|
|
||||||
|
/// Pushdown SETTINGS clause that goes after FORMAT to the SELECT query:
|
||||||
|
/// (since settings after FORMAT parsed separatelly not in the ParserSelectQuery but in ParserQueryWithOutput)
|
||||||
|
///
|
||||||
|
/// SELECT 1 FORMAT Null SETTINGS max_block_size = 1 ->
|
||||||
|
/// SELECT 1 SETTINGS max_block_size = 1 FORMAT Null SETTINGS max_block_size = 1
|
||||||
|
///
|
||||||
|
/// Otherwise settings after FORMAT will not be applied.
|
||||||
|
class QueryWithOutputSettingsPushDownMatcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Visitor = InDepthNodeVisitor<QueryWithOutputSettingsPushDownMatcher, true>;
|
||||||
|
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
const ASTPtr & settings_ast;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool needChildVisit(ASTPtr & node, const ASTPtr & child);
|
||||||
|
static void visit(ASTPtr & ast, Data & data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void visit(ASTSelectQuery &, ASTPtr &, Data &);
|
||||||
|
};
|
||||||
|
|
||||||
|
using QueryWithOutputSettingsPushDownVisitor = QueryWithOutputSettingsPushDownMatcher::Visitor;
|
||||||
|
|
||||||
|
}
|
@ -116,6 +116,7 @@ SRCS(
|
|||||||
parseUserName.cpp
|
parseUserName.cpp
|
||||||
queryToString.cpp
|
queryToString.cpp
|
||||||
TokenIterator.cpp
|
TokenIterator.cpp
|
||||||
|
QueryWithOutputSettingsPushDownVisitor.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
END()
|
END()
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
21
tests/queries/0_stateless/01401_FORMAT_SETTINGS.sh
Executable file
21
tests/queries/0_stateless/01401_FORMAT_SETTINGS.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||||
|
. $CURDIR/../shell_config.sh
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
# test via http, since client parses settings by itself additionally
|
||||||
|
|
||||||
|
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT DISTINCT blockSize() FROM numbers(2) SETTINGS max_block_size = 1 FORMAT CSV'
|
||||||
|
# push down
|
||||||
|
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT DISTINCT blockSize() FROM numbers(2) FORMAT CSV SETTINGS max_block_size = 1'
|
||||||
|
# push down append
|
||||||
|
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT DISTINCT blockSize() FROM numbers(2) SETTINGS max_compress_block_size = 1 FORMAT CSV SETTINGS max_block_size = 1'
|
||||||
|
# overwrite on push down (since these settings goes latest)
|
||||||
|
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT DISTINCT blockSize() FROM numbers(2) SETTINGS max_block_size = 2 FORMAT CSV SETTINGS max_block_size = 1'
|
||||||
|
# on push-down
|
||||||
|
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT DISTINCT blockSize() FROM numbers(2) SETTINGS max_block_size = 1 FORMAT CSV'
|
||||||
|
# no settings
|
||||||
|
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT DISTINCT blockSize() FROM numbers(2) FORMAT CSV'
|
||||||
|
${CLICKHOUSE_CURL} -sS "${CLICKHOUSE_URL}" -d 'SELECT DISTINCT blockSize() FROM numbers(2)'
|
Loading…
Reference in New Issue
Block a user