Treat query as function argument.

This commit is contained in:
Amos Bird 2020-09-09 15:41:38 +08:00
parent fbf06f9858
commit b40998ca00
No known key found for this signature in database
GPG Key ID: 80D430DCBECFEDB4
5 changed files with 27 additions and 17 deletions

View File

@ -152,7 +152,7 @@ void QueryNormalizer::visitChildren(const ASTPtr & node, Data & data)
{
if (const auto * func_node = node->as<ASTFunction>())
{
if (func_node->query)
if (func_node->tryGetQueryArgument())
{
if (func_node->name != "view")
throw Exception("Query argument can only be used in the `view` TableFunction", ErrorCodes::BAD_ARGUMENTS);

View File

@ -48,7 +48,6 @@ ASTPtr ASTFunction::clone() const
auto res = std::make_shared<ASTFunction>(*this);
res->children.clear();
if (query) { res->query = query->clone(); res->children.push_back(res->query); }
if (arguments) { res->arguments = arguments->clone(); res->children.push_back(res->arguments); }
if (parameters) { res->parameters = parameters->clone(); res->children.push_back(res->parameters); }
@ -112,6 +111,16 @@ static bool highlightStringLiteralWithMetacharacters(const ASTPtr & node, const
}
ASTSelectWithUnionQuery * ASTFunction::tryGetQueryArgument() const
{
if (arguments && arguments->children.size() == 1)
{
return arguments->children[0]->as<ASTSelectWithUnionQuery>();
}
return nullptr;
}
void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const
{
FormatStateStacked nested_need_parens = frame;
@ -119,7 +128,7 @@ void ASTFunction::formatImplWithoutAlias(const FormatSettings & settings, Format
nested_need_parens.need_parens = true;
nested_dont_need_parens.need_parens = false;
if (query)
if (auto * query = tryGetQueryArgument())
{
std::string nl_or_nothing = settings.one_line ? "" : "\n";
std::string indent_str = settings.one_line ? "" : std::string(4u * frame.indent, ' ');

View File

@ -2,6 +2,7 @@
#include <Parsers/ASTWithAlias.h>
#include <Parsers/ASTExpressionList.h>
#include <Parsers/ASTSelectWithUnionQuery.h>
namespace DB
@ -13,7 +14,6 @@ class ASTFunction : public ASTWithAlias
{
public:
String name;
ASTPtr query; // It's possible for a function to accept a query as its only argument.
ASTPtr arguments;
/// parameters - for parametric aggregate function. Example: quantile(0.9)(x) - what in first parens are 'parameters'.
ASTPtr parameters;
@ -26,6 +26,8 @@ public:
void updateTreeHashImpl(SipHash & hash_state) const override;
ASTSelectWithUnionQuery * tryGetQueryArgument() const;
protected:
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
void appendColumnNameImpl(WriteBuffer & ostr) const override;

View File

@ -260,8 +260,10 @@ bool ParserFunction::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
++pos;
auto function_node = std::make_shared<ASTFunction>();
tryGetIdentifierNameInto(identifier, function_node->name);
function_node->query = query;
function_node->children.push_back(function_node->query);
auto expr_list_with_single_query = std::make_shared<ASTExpressionList>();
expr_list_with_single_query->children.push_back(query);
function_node->arguments = expr_list_with_single_query;
function_node->children.push_back(function_node->arguments);
node = function_node;
return true;
}

View File

@ -20,18 +20,15 @@ StoragePtr TableFunctionView::executeImpl(const ASTPtr & ast_function, const Con
{
if (const auto * function = ast_function->as<ASTFunction>())
{
if (function->query)
if (auto * select = function->tryGetQueryArgument())
{
if (auto * select = function->query->as<ASTSelectWithUnionQuery>())
{
auto sample = InterpreterSelectWithUnionQuery::getSampleBlock(function->query, context);
auto columns = ColumnsDescription(sample.getNamesAndTypesList());
ASTCreateQuery create;
create.select = select;
auto res = StorageView::create(StorageID(getDatabaseName(), table_name), create, columns);
res->startup();
return res;
}
auto sample = InterpreterSelectWithUnionQuery::getSampleBlock(function->arguments->children[0] /* ASTPtr */, context);
auto columns = ColumnsDescription(sample.getNamesAndTypesList());
ASTCreateQuery create;
create.select = select;
auto res = StorageView::create(StorageID(getDatabaseName(), table_name), create, columns);
res->startup();
return res;
}
}
throw Exception("Table function '" + getName() + "' requires a query argument.", ErrorCodes::BAD_ARGUMENTS);