mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-02 12:32:04 +00:00
Fixed review comments and updated FunctionParameterValuesVisitor to use visitFunction - 40907 Parameterized views as table functions
This commit is contained in:
parent
5001cf9fa2
commit
a6f860f24e
@ -510,9 +510,10 @@ InterpreterSelectQuery::InterpreterSelectQuery(
|
||||
if (view)
|
||||
{
|
||||
query_info.is_parameterized_view = view->isParameterizedView();
|
||||
/// We need to fetch the parameters set for SELECT parameterized view before the query is replaced.
|
||||
/// We need to fetch the parameters set for SELECT ... FROM parameterized_view(<params>) before the query is replaced.
|
||||
/// replaceWithSubquery replaces the function child and adds the subquery in its place.
|
||||
/// the parameters are children of function child, if function is replaced the parameters are also gone from tree
|
||||
/// the parameters are children of function child, if function (which corresponds to parametrised view and has
|
||||
/// parameters in its arguments: `parametrised_view(<params>)`) is replaced the parameters are also gone from tree
|
||||
/// So we need to get the parameters before they are removed from the tree
|
||||
/// and after query is replaced, we use these parameters to substitute in the parameterized view query
|
||||
if (query_info.is_parameterized_view)
|
||||
|
@ -27,8 +27,8 @@ public:
|
||||
|
||||
void visit(const ASTPtr & ast)
|
||||
{
|
||||
if (const auto * expression = ast->as<ASTExpressionList>())
|
||||
visitExpressionList(*expression);
|
||||
if (const auto * function = ast->as<ASTFunction>())
|
||||
visitFunction(*function);
|
||||
for (const auto & child : ast->children)
|
||||
visit(child);
|
||||
}
|
||||
@ -36,18 +36,23 @@ public:
|
||||
private:
|
||||
NameToNameMap & parameter_values;
|
||||
|
||||
void visitExpressionList(const ASTExpressionList & expression_list)
|
||||
void visitFunction(const ASTFunction & parameter_function)
|
||||
{
|
||||
if (expression_list.children.size() != 2)
|
||||
if (parameter_function.name != "equals" && parameter_function.children.size() != 1)
|
||||
return;
|
||||
|
||||
if (const auto * identifier = expression_list.children[0]->as<ASTIdentifier>())
|
||||
const auto * expression_list = parameter_function.children[0]->as<ASTExpressionList>();
|
||||
|
||||
if (expression_list && expression_list->children.size() != 2)
|
||||
return;
|
||||
|
||||
if (const auto * identifier = expression_list->children[0]->as<ASTIdentifier>())
|
||||
{
|
||||
if (const auto * literal = expression_list.children[1]->as<ASTLiteral>())
|
||||
if (const auto * literal = expression_list->children[1]->as<ASTLiteral>())
|
||||
{
|
||||
parameter_values[identifier->name()] = convertFieldToString(literal->value);
|
||||
}
|
||||
else if (const auto * function = expression_list.children[1]->as<ASTFunction>())
|
||||
else if (const auto * function = expression_list->children[1]->as<ASTFunction>())
|
||||
{
|
||||
if (isFunctionCast(function))
|
||||
{
|
||||
|
@ -117,10 +117,11 @@ Block StorageSnapshot::getSampleBlockForColumns(const Names & column_names,const
|
||||
Block res;
|
||||
|
||||
const auto & columns = getMetadataForQuery()->getColumns();
|
||||
for (const auto & name : column_names)
|
||||
for (const auto & column_name : column_names)
|
||||
{
|
||||
const std::string & column_name = name;
|
||||
std::string substituted_column_name = name;
|
||||
/// substituted_column_name is used for parameterized view (which are created using query parameters
|
||||
/// and SELECT is used with substitution of these query parameters )
|
||||
std::string substituted_column_name = column_name;
|
||||
std::string::size_type pos = 0u;
|
||||
for (const auto & parameter : parameter_values)
|
||||
{
|
||||
@ -141,17 +142,17 @@ Block StorageSnapshot::getSampleBlockForColumns(const Names & column_names,const
|
||||
{
|
||||
res.insert({object_column->type->createColumn(), object_column->type, column_name});
|
||||
}
|
||||
else if (auto it = virtual_columns.find(name); it != virtual_columns.end())
|
||||
else if (auto it = virtual_columns.find(column_name); it != virtual_columns.end())
|
||||
{
|
||||
/// Virtual columns must be appended after ordinary, because user can
|
||||
/// override them.
|
||||
const auto & type = it->second;
|
||||
res.insert({type->createColumn(), type, name});
|
||||
res.insert({type->createColumn(), type, column_name});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Exception(ErrorCodes::NOT_FOUND_COLUMN_IN_BLOCK,
|
||||
"Column {} not found in table {}", backQuote(name), storage.getStorageID().getNameForLogs());
|
||||
"Column {} not found in table {}", backQuote(substituted_column_name), storage.getStorageID().getNameForLogs());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
Loading…
Reference in New Issue
Block a user