Fixed review comments and updated FunctionParameterValuesVisitor to use visitFunction - 40907 Parameterized views as table functions

This commit is contained in:
Smita Kulkarni 2022-12-23 17:57:17 +01:00
parent 5001cf9fa2
commit a6f860f24e
3 changed files with 22 additions and 15 deletions

View File

@ -510,9 +510,10 @@ InterpreterSelectQuery::InterpreterSelectQuery(
if (view) if (view)
{ {
query_info.is_parameterized_view = view->isParameterizedView(); 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. /// 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 /// 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 /// and after query is replaced, we use these parameters to substitute in the parameterized view query
if (query_info.is_parameterized_view) if (query_info.is_parameterized_view)

View File

@ -27,8 +27,8 @@ public:
void visit(const ASTPtr & ast) void visit(const ASTPtr & ast)
{ {
if (const auto * expression = ast->as<ASTExpressionList>()) if (const auto * function = ast->as<ASTFunction>())
visitExpressionList(*expression); visitFunction(*function);
for (const auto & child : ast->children) for (const auto & child : ast->children)
visit(child); visit(child);
} }
@ -36,18 +36,23 @@ public:
private: private:
NameToNameMap & parameter_values; 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; 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); 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)) if (isFunctionCast(function))
{ {

View File

@ -117,10 +117,11 @@ Block StorageSnapshot::getSampleBlockForColumns(const Names & column_names,const
Block res; Block res;
const auto & columns = getMetadataForQuery()->getColumns(); const auto & columns = getMetadataForQuery()->getColumns();
for (const auto & name : column_names) for (const auto & column_name : column_names)
{ {
const std::string & column_name = name; /// substituted_column_name is used for parameterized view (which are created using query parameters
std::string substituted_column_name = name; /// and SELECT is used with substitution of these query parameters )
std::string substituted_column_name = column_name;
std::string::size_type pos = 0u; std::string::size_type pos = 0u;
for (const auto & parameter : parameter_values) 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}); 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 /// Virtual columns must be appended after ordinary, because user can
/// override them. /// override them.
const auto & type = it->second; const auto & type = it->second;
res.insert({type->createColumn(), type, name}); res.insert({type->createColumn(), type, column_name});
} }
else else
{ {
throw Exception(ErrorCodes::NOT_FOUND_COLUMN_IN_BLOCK, 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; return res;