Updated to get column data type based not function , not the query parameter type , added test for the same - 40907 Parameterized views as table functions

This commit is contained in:
Smita Kulkarni 2022-12-19 15:05:38 +01:00
parent 22c2956a06
commit 5001cf9fa2
12 changed files with 72 additions and 22 deletions

View File

@ -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);

View File

@ -256,11 +256,15 @@ 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() + "')");
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);
}
}

View File

@ -29,12 +29,14 @@ public:
std::unordered_set<String> 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); }

View File

@ -362,10 +362,11 @@ using ReplacePositionalArgumentsVisitor = InDepthNodeVisitor<OneTypeMatcher<Repl
/// Expand asterisks and qualified asterisks with column names.
/// There would be columns in normal form & column aliases after translation. Column & column alias would be normalized in QueryNormalizer.
void translateQualifiedNames(ASTPtr & query, const ASTSelectQuery & select_query, const NameSet & source_columns_set,
const TablesWithColumns & tables_with_columns, const NameToNameMap & parameter_values = {})
const TablesWithColumns & tables_with_columns, const NameToNameMap & parameter_values = {},
const NameToNameMap & parameter_types = {})
{
LogAST log;
TranslateQualifiedNamesVisitor::Data visitor_data(source_columns_set, tables_with_columns, true/* has_columns */, parameter_values);
TranslateQualifiedNamesVisitor::Data visitor_data(source_columns_set, tables_with_columns, true/* has_columns */, parameter_values, parameter_types);
TranslateQualifiedNamesVisitor visitor(visitor_data, log.stream());
visitor.visit(query);
@ -1305,7 +1306,8 @@ TreeRewriterResultPtr TreeRewriter::analyzeSelect(
const Names & required_result_columns,
std::shared_ptr<TableJoin> 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<ASTSelectQuery>();
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,13 +1410,17 @@ TreeRewriterResultPtr TreeRewriter::analyzeSelect(
{
if ((pos = column_name.find(parameter.first)) != std::string::npos)
{
String parameter_name("_CAST(" + parameter.second + ", '" + column.type->getName() + "')");
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;
}
}
}
}
}
result.collectUsedColumns(query, true, settings.query_plan_optimize_primary_key);

View File

@ -131,7 +131,8 @@ public:
const Names & required_result_columns = {},
std::shared_ptr<TableJoin> 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);

View File

@ -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;
}

View File

@ -13,4 +13,6 @@ NameSet analyzeReceiveQueryParams(const std::string & query);
NameSet analyzeReceiveQueryParams(const ASTPtr & ast);
NameToNameMap analyzeReceiveQueryParamsWithType(const ASTPtr & ast);
}

View File

@ -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)
{

View File

@ -24,6 +24,7 @@
#include <Processors/QueryPlan/Optimizations/QueryPlanOptimizationSettings.h>
#include <Interpreters/ReplaceQueryParameterVisitor.h>
#include <Parsers/QueryParameterVisitor.h>
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);
}

View File

@ -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;
};
}

View File

@ -20,3 +20,8 @@ FROM
30
40
60
1
2
3
3
5

View File

@ -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;