mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 00:30:49 +00:00
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:
parent
22c2956a06
commit
5001cf9fa2
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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); }
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -13,4 +13,6 @@ NameSet analyzeReceiveQueryParams(const std::string & query);
|
||||
|
||||
NameSet analyzeReceiveQueryParams(const ASTPtr & ast);
|
||||
|
||||
NameToNameMap analyzeReceiveQueryParamsWithType(const ASTPtr & ast);
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -20,3 +20,8 @@ FROM
|
||||
30
|
||||
40
|
||||
60
|
||||
1
|
||||
2
|
||||
3
|
||||
3
|
||||
5
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user