Support SETTINGS argument of table functions

This commit is contained in:
vdimir 2023-03-13 11:41:00 +00:00 committed by Vladimir C
parent 023d14a894
commit ebd71f226c
5 changed files with 79 additions and 0 deletions

View File

@ -838,8 +838,14 @@ QueryTreeNodePtr QueryTreeBuilder::buildJoinTree(const ASTPtr & tables_in_select
const auto & function_arguments_list = table_function_expression.arguments->as<ASTExpressionList &>().children;
for (const auto & argument : function_arguments_list)
{
if (!node->getSettingsChanges().empty())
throw Exception(ErrorCodes::LOGICAL_ERROR, "Table function '{}' has arguments after SETTINGS",
table_function_expression.formatForErrorMessage());
if (argument->as<ASTSelectQuery>() || argument->as<ASTSelectWithUnionQuery>() || argument->as<ASTSelectIntersectExceptQuery>())
node->getArguments().getNodes().push_back(buildSelectOrUnionExpression(argument, false /*is_subquery*/, {} /*cte_name*/, context));
else if (const auto * ast_set = argument->as<ASTSetQuery>())
node->setSettingsChanges(ast_set->changes);
else
node->getArguments().getNodes().push_back(buildExpression(argument, context));
}

View File

@ -7,6 +7,7 @@
#include <Storages/IStorage.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTSetQuery.h>
#include <Interpreters/Context.h>
@ -71,6 +72,13 @@ void TableFunctionNode::dumpTreeImpl(WriteBuffer & buffer, FormatState & format_
buffer << '\n' << std::string(indent + 2, ' ') << "ARGUMENTS\n";
arguments.dumpTreeImpl(buffer, format_state, indent + 4);
}
if (!settings_changes.empty())
{
buffer << '\n' << std::string(indent + 6, ' ') << "SETTINGS";
for (const auto & change : settings_changes)
buffer << fmt::format(" {}={}", change.name, toString(change.value));
}
}
bool TableFunctionNode::isEqualImpl(const IQueryTreeNode & rhs) const
@ -99,6 +107,16 @@ void TableFunctionNode::updateTreeHashImpl(HashState & state) const
if (table_expression_modifiers)
table_expression_modifiers->updateTreeHash(state);
for (const auto & change : settings_changes)
{
state.update(change.name.size());
state.update(change.name);
const auto & value_dump = change.value.dump();
state.update(value_dump.size());
state.update(value_dump);
}
}
QueryTreeNodePtr TableFunctionNode::cloneImpl() const
@ -109,6 +127,7 @@ QueryTreeNodePtr TableFunctionNode::cloneImpl() const
result->storage_id = storage_id;
result->storage_snapshot = storage_snapshot;
result->table_expression_modifiers = table_expression_modifiers;
result->settings_changes = settings_changes;
return result;
}
@ -123,6 +142,14 @@ ASTPtr TableFunctionNode::toASTImpl(ConvertToASTOptions options) const
table_function_ast->children.push_back(arguments.toAST(options));
table_function_ast->arguments = table_function_ast->children.back();
if (!settings_changes.empty())
{
auto settings_ast = std::make_shared<ASTSetQuery>();
settings_ast->changes = settings_changes;
settings_ast->is_standalone = false;
table_function_ast->arguments->children.push_back(std::move(settings_ast));
}
return table_function_ast;
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <Common/SettingsChanges.h>
#include <Storages/IStorage_fwd.h>
#include <Storages/TableLockHolder.h>
#include <Storages/StorageSnapshot.h>
@ -122,6 +124,18 @@ public:
return table_expression_modifiers;
}
/// Get settings changes passed to table function
const SettingsChanges & getSettingsChanges() const
{
return settings_changes;
}
/// Set settings changes passed as last argument to table function
void setSettingsChanges(SettingsChanges settings_changes_)
{
settings_changes = std::move(settings_changes_);
}
/// Set table expression modifiers
void setTableExpressionModifiers(TableExpressionModifiers table_expression_modifiers_value)
{
@ -151,6 +165,7 @@ private:
StorageID storage_id;
StorageSnapshotPtr storage_snapshot;
std::optional<TableExpressionModifiers> table_expression_modifiers;
SettingsChanges settings_changes;
static constexpr size_t arguments_child_index = 0;
static constexpr size_t children_size = arguments_child_index + 1;

View File

@ -37,3 +37,24 @@
-5
---
4
QUERY id: 0
PROJECTION COLUMNS
key String
PROJECTION
LIST id: 1, nodes: 1
COLUMN id: 2, column_name: key, result_type: String, source_id: 3
JOIN TREE
TABLE_FUNCTION id: 3, table_function_name: mysql
ARGUMENTS
LIST id: 4, nodes: 5
CONSTANT id: 5, constant_value: \'127.0.0.1:9004\', constant_value_type: String
CONSTANT id: 6, constant_value: \'default\', constant_value_type: String
CONSTANT id: 7, constant_value: \'foo\', constant_value_type: String
CONSTANT id: 8, constant_value: \'default\', constant_value_type: String
CONSTANT id: 9, constant_value: \'\', constant_value_type: String
SETTINGS connection_wait_timeout=123 connect_timeout=40123002 read_write_timeout=40123001 connection_pool_size=3
SELECT key AS key
FROM mysql(\'127.0.0.1:9004\', \'default\', \'foo\', \'default\', \'\', SETTINGS connection_wait_timeout = 123, connect_timeout = 40123002, read_write_timeout = 40123001, connection_pool_size = 3)
---
5

View File

@ -30,3 +30,13 @@ SELECT b FROM mysql('127.0.0.1:9004', currentDatabase(), foo, 'default', '') WHE
SELECT '---';
SELECT count() FROM mysql('127.0.0.1:9004', currentDatabase(), foo, 'default', '') WHERE c != 'twee';
EXPLAIN QUERY TREE dump_ast = 1
SELECT * FROM mysql(
'127.0.0.1:9004', 'default', 'foo', 'default', '',
SETTINGS connection_wait_timeout = 123, connect_timeout = 40123002, read_write_timeout = 40123001, connection_pool_size = 3
);
SELECT '---';
SELECT count() FROM mysql('127.0.0.1:9004', currentDatabase(), foo, 'default', '', SETTINGS connection_pool_size = 1);
SELECT count() FROM mysql('127.0.0.1:9004', currentDatabase(), foo, 'default', '', SETTINGS connection_pool_size = 0); -- { serverError BAD_ARGUMENTS }