diff --git a/src/Interpreters/InterpreterSelectQuery.cpp b/src/Interpreters/InterpreterSelectQuery.cpp index 9714596dce8..8381fee22b1 100644 --- a/src/Interpreters/InterpreterSelectQuery.cpp +++ b/src/Interpreters/InterpreterSelectQuery.cpp @@ -506,6 +506,7 @@ InterpreterSelectQuery::InterpreterSelectQuery( /// Allow push down and other optimizations for VIEW: replace with subquery and rewrite it. ASTPtr view_table; NameToNameMap parameter_values; + NameToNameMap parameter_types; if (view) { query_info.is_parameterized_view = view->isParameterizedView(); @@ -518,6 +519,7 @@ InterpreterSelectQuery::InterpreterSelectQuery( { parameter_values = analyzeFunctionParamValues(query_ptr); view->setParameterValues(parameter_values); + parameter_types = view->getParameterValues(); } view->replaceWithSubquery(getSelectQuery(), view_table, metadata_snapshot, view->isParameterizedView()); if (query_info.is_parameterized_view) @@ -535,7 +537,8 @@ InterpreterSelectQuery::InterpreterSelectQuery( required_result_column_names, table_join, query_info.is_parameterized_view, - parameter_values); + parameter_values, + parameter_types); query_info.syntax_analyzer_result = syntax_analyzer_result; context->setDistributed(syntax_analyzer_result->is_remote_storage); diff --git a/src/Interpreters/TranslateQualifiedNamesVisitor.cpp b/src/Interpreters/TranslateQualifiedNamesVisitor.cpp index 1596cb90a14..ff97eccab58 100644 --- a/src/Interpreters/TranslateQualifiedNamesVisitor.cpp +++ b/src/Interpreters/TranslateQualifiedNamesVisitor.cpp @@ -256,9 +256,13 @@ void TranslateQualifiedNamesMatcher::visit(ASTExpressionList & node, const ASTPt { if ((pos = column_name.find(parameter.first)) != std::string::npos) { - String parameter_name("_CAST(" + parameter.second + ", '" + column.type->getName() + "')"); - column_name.replace(pos, parameter.first.size(), parameter_name); - break; + auto parameter_datatype_iterator = data.parameter_types.find(parameter.first); + if (parameter_datatype_iterator != data.parameter_types.end()) + { + String parameter_name("_CAST(" + parameter.second + ", '" + parameter_datatype_iterator->second + "')"); + column_name.replace(pos, parameter.first.size(), parameter_name); + break; + } } } addIdentifier(columns, table.table, column_name); diff --git a/src/Interpreters/TranslateQualifiedNamesVisitor.h b/src/Interpreters/TranslateQualifiedNamesVisitor.h index 7fc95a19d1b..6c804ad6c90 100644 --- a/src/Interpreters/TranslateQualifiedNamesVisitor.h +++ b/src/Interpreters/TranslateQualifiedNamesVisitor.h @@ -29,12 +29,14 @@ public: std::unordered_set join_using_columns; bool has_columns; NameToNameMap parameter_values; + NameToNameMap parameter_types; - Data(const NameSet & source_columns_, const TablesWithColumns & tables_, bool has_columns_ = true, const NameToNameMap & parameter_values_ = {}) + Data(const NameSet & source_columns_, const TablesWithColumns & tables_, bool has_columns_ = true, const NameToNameMap & parameter_values_ = {}, const NameToNameMap & parameter_types_ = {}) : source_columns(source_columns_) , tables(tables_) , has_columns(has_columns_) , parameter_values(parameter_values_) + , parameter_types(parameter_types_) {} bool hasColumn(const String & name) const { return source_columns.count(name); } diff --git a/src/Interpreters/TreeRewriter.cpp b/src/Interpreters/TreeRewriter.cpp index ab3189f39d2..3c7367b869e 100644 --- a/src/Interpreters/TreeRewriter.cpp +++ b/src/Interpreters/TreeRewriter.cpp @@ -362,10 +362,11 @@ using ReplacePositionalArgumentsVisitor = InDepthNodeVisitor table_join, bool is_parameterized_view, - const NameToNameMap parameter_values) const + const NameToNameMap parameter_values, + const NameToNameMap parameter_types) const { auto * select_query = query->as(); if (!select_query) @@ -1343,7 +1345,7 @@ TreeRewriterResultPtr TreeRewriter::analyzeSelect( result.analyzed_join->setColumnsFromJoinedTable(std::move(columns_from_joined_table), source_columns_set, right_table.table.getQualifiedNamePrefix()); } - translateQualifiedNames(query, *select_query, source_columns_set, tables_with_columns, parameter_values); + translateQualifiedNames(query, *select_query, source_columns_set, tables_with_columns, parameter_values, parameter_types); /// Optimizes logical expressions. LogicalExpressionsOptimizer(select_query, settings.optimize_min_equality_disjunction_chain_length.value).perform(); @@ -1408,9 +1410,13 @@ TreeRewriterResultPtr TreeRewriter::analyzeSelect( { if ((pos = column_name.find(parameter.first)) != std::string::npos) { - String parameter_name("_CAST(" + parameter.second + ", '" + column.type->getName() + "')"); - column.name.replace(pos, parameter.first.size(), parameter_name); - break; + auto parameter_datatype_iterator = parameter_types.find(parameter.first); + if (parameter_datatype_iterator != parameter_types.end()) + { + String parameter_name("_CAST(" + parameter.second + ", '" + parameter_datatype_iterator->second + "')"); + column.name.replace(pos, parameter.first.size(), parameter_name); + break; + } } } } diff --git a/src/Interpreters/TreeRewriter.h b/src/Interpreters/TreeRewriter.h index 1f400588c6e..b94043b8983 100644 --- a/src/Interpreters/TreeRewriter.h +++ b/src/Interpreters/TreeRewriter.h @@ -131,7 +131,8 @@ public: const Names & required_result_columns = {}, std::shared_ptr table_join = {}, bool is_parameterized_view = false, - const NameToNameMap parameter_values = {}) const; + const NameToNameMap parameter_values = {}, + const NameToNameMap parameter_types = {}) const; private: static void normalize(ASTPtr & query, Aliases & aliases, const NameSet & source_columns_set, bool ignore_alias, const Settings & settings, bool allow_self_aliases, ContextPtr context_, bool is_create_parameterized_view = false); diff --git a/src/Parsers/QueryParameterVisitor.cpp b/src/Parsers/QueryParameterVisitor.cpp index 14750845034..1282c12cce6 100644 --- a/src/Parsers/QueryParameterVisitor.cpp +++ b/src/Parsers/QueryParameterVisitor.cpp @@ -10,8 +10,8 @@ namespace DB class QueryParameterVisitor { public: - explicit QueryParameterVisitor(NameSet & parameters_name) - : query_parameters(parameters_name) + explicit QueryParameterVisitor(NameToNameMap & parameters) + : query_parameters(parameters) { } @@ -27,30 +27,44 @@ public: } private: - NameSet & query_parameters; + NameToNameMap & query_parameters; void visitQueryParameter(const ASTQueryParameter & query_parameter) { - query_parameters.insert(query_parameter.name); + query_parameters[query_parameter.name]= query_parameter.type; } }; NameSet analyzeReceiveQueryParams(const std::string & query) { - NameSet query_params; + NameToNameMap query_params; const char * query_begin = query.data(); const char * query_end = query.data() + query.size(); ParserQuery parser(query_end); ASTPtr extract_query_ast = parseQuery(parser, query_begin, query_end, "analyzeReceiveQueryParams", 0, 0); QueryParameterVisitor(query_params).visit(extract_query_ast); - return query_params; + + NameSet query_param_names; + for (const auto & query_param : query_params) + query_param_names.insert(query_param.first); + return query_param_names; } NameSet analyzeReceiveQueryParams(const ASTPtr & ast) { - NameSet query_params; + NameToNameMap query_params; + QueryParameterVisitor(query_params).visit(ast); + NameSet query_param_names; + for (const auto & query_param : query_params) + query_param_names.insert(query_param.first); + return query_param_names; +} + +NameToNameMap analyzeReceiveQueryParamsWithType(const ASTPtr & ast) +{ + NameToNameMap query_params; QueryParameterVisitor(query_params).visit(ast); return query_params; } diff --git a/src/Parsers/QueryParameterVisitor.h b/src/Parsers/QueryParameterVisitor.h index 6d9d49e1ed2..40b2fa6978f 100644 --- a/src/Parsers/QueryParameterVisitor.h +++ b/src/Parsers/QueryParameterVisitor.h @@ -13,4 +13,6 @@ NameSet analyzeReceiveQueryParams(const std::string & query); NameSet analyzeReceiveQueryParams(const ASTPtr & ast); +NameToNameMap analyzeReceiveQueryParamsWithType(const ASTPtr & ast); + } diff --git a/src/Storages/StorageSnapshot.cpp b/src/Storages/StorageSnapshot.cpp index 8dfb7b288e3..b88e07d93b8 100644 --- a/src/Storages/StorageSnapshot.cpp +++ b/src/Storages/StorageSnapshot.cpp @@ -119,10 +119,10 @@ Block StorageSnapshot::getSampleBlockForColumns(const Names & column_names,const const auto & columns = getMetadataForQuery()->getColumns(); for (const auto & name : column_names) { - std::string column_name = name; + const std::string & column_name = name; std::string substituted_column_name = name; std::string::size_type pos = 0u; - for (auto parameter : parameter_values) + for (const auto & parameter : parameter_values) { if ((pos = substituted_column_name.find("_CAST(" + parameter.second)) != std::string::npos) { diff --git a/src/Storages/StorageView.cpp b/src/Storages/StorageView.cpp index d9e79607ce4..f9ab6b0bc40 100644 --- a/src/Storages/StorageView.cpp +++ b/src/Storages/StorageView.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace DB { @@ -102,6 +103,7 @@ StorageView::StorageView( description.inner_query = query.select->ptr(); is_parameterized_view = query.isParameterizedView(); + parameter_types = analyzeReceiveQueryParamsWithType(description.inner_query); storage_metadata.setSelectQuery(description); setInMemoryMetadata(storage_metadata); } diff --git a/src/Storages/StorageView.h b/src/Storages/StorageView.h index e913e98901f..756106a95d1 100644 --- a/src/Storages/StorageView.h +++ b/src/Storages/StorageView.h @@ -50,9 +50,15 @@ public: parameter_values = parameter_values_; } + NameToNameMap getParameterValues() const + { + return parameter_types; + } + protected: bool is_parameterized_view; NameToNameMap parameter_values; + NameToNameMap parameter_types; }; } diff --git a/tests/queries/0_stateless/02428_parameterized_view.reference b/tests/queries/0_stateless/02428_parameterized_view.reference index 9ec1cb0efd2..38355617601 100644 --- a/tests/queries/0_stateless/02428_parameterized_view.reference +++ b/tests/queries/0_stateless/02428_parameterized_view.reference @@ -20,3 +20,8 @@ FROM 30 40 60 +1 +2 +3 +3 +5 diff --git a/tests/queries/0_stateless/02428_parameterized_view.sql b/tests/queries/0_stateless/02428_parameterized_view.sql index 9d55dba970a..d2118cd1279 100644 --- a/tests/queries/0_stateless/02428_parameterized_view.sql +++ b/tests/queries/0_stateless/02428_parameterized_view.sql @@ -4,6 +4,7 @@ DROP VIEW IF EXISTS pv3; DROP VIEW IF EXISTS pv4; DROP VIEW IF EXISTS pv5; DROP VIEW IF EXISTS pv6; +DROP VIEW IF EXISTS pv7; DROP VIEW IF EXISTS v1; DROP TABLE IF EXISTS Catalog; DROP TABLE IF EXISTS system.pv1; @@ -68,11 +69,15 @@ SELECT Price FROM pv5(price=30, quantity=8,limit=1); CREATE VIEW pv6 AS SELECT Price+{price:UInt64} FROM Catalog GROUP BY Price+{price:UInt64} ORDER BY Price+{price:UInt64}; SELECT * FROM pv6(price=10); +CREATE VIEW pv7 AS SELECT Price/{price:UInt64} FROM Catalog ORDER BY Price; +SELECT * FROM pv7(price=10); + DROP VIEW pv1; DROP VIEW pv2; DROP VIEW pv3; DROP VIEW pv5; DROP VIEW pv6; +DROP VIEW pv7; DROP VIEW v1; DROP TABLE Catalog; DROP TABLE system.pv1;