mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-21 01:00:48 +00:00
added former WITH clause to SELECT query
This commit is contained in:
parent
9b99dfb53d
commit
37b6c98752
@ -1228,6 +1228,7 @@ static ASTPtr addTypeConversion(std::unique_ptr<ASTLiteral> && ast, const String
|
||||
auto func = std::make_shared<ASTFunction>(ast->range);
|
||||
ASTPtr res = func;
|
||||
func->alias = ast->alias;
|
||||
func->prefer_alias_to_column_name = ast->prefer_alias_to_column_name;
|
||||
ast->alias.clear();
|
||||
func->kind = ASTFunction::FUNCTION;
|
||||
func->name = "CAST";
|
||||
@ -1300,6 +1301,7 @@ void ExpressionAnalyzer::executeScalarSubqueriesImpl(ASTPtr & ast)
|
||||
{
|
||||
auto lit = std::make_unique<ASTLiteral>(ast->range, (*block.safeGetByPosition(0).column)[0]);
|
||||
lit->alias = subquery->alias;
|
||||
lit->prefer_alias_to_column_name = subquery->prefer_alias_to_column_name;
|
||||
ast = addTypeConversion(std::move(lit), block.safeGetByPosition(0).type->getName());
|
||||
}
|
||||
else
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <Parsers/ASTLiteral.h>
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/ASTWithAlias.h>
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <IO/WriteBufferFromString.h>
|
||||
|
||||
@ -8,7 +9,7 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
String ASTFunction::getColumnName() const
|
||||
String ASTFunction::getColumnNameImpl() const
|
||||
{
|
||||
WriteBufferFromOwnString wb;
|
||||
writeString(name, wb);
|
||||
|
@ -34,8 +34,6 @@ public:
|
||||
ASTFunction() = default;
|
||||
ASTFunction(const StringRange range_) : ASTWithAlias(range_) {}
|
||||
|
||||
String getColumnName() const override;
|
||||
|
||||
/** Get text identifying the AST node. */
|
||||
String getID() const override;
|
||||
|
||||
@ -43,6 +41,7 @@ public:
|
||||
|
||||
protected:
|
||||
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
|
||||
String getColumnNameImpl() const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -29,8 +29,6 @@ public:
|
||||
ASTIdentifier(const StringRange range_, const String & name_, const Kind kind_ = Column)
|
||||
: ASTWithAlias(range_), name(name_), kind(kind_) {}
|
||||
|
||||
String getColumnName() const override { return name; }
|
||||
|
||||
/** Get the text that identifies this element. */
|
||||
String getID() const override { return "Identifier_" + name; }
|
||||
|
||||
@ -43,6 +41,7 @@ public:
|
||||
|
||||
protected:
|
||||
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
|
||||
String getColumnNameImpl() const override { return name; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ namespace DB
|
||||
{
|
||||
|
||||
|
||||
String ASTLiteral::getColumnName() const
|
||||
String ASTLiteral::getColumnNameImpl() const
|
||||
{
|
||||
/// Special case for very large arrays. Instead of listing all elements, will use hash of them.
|
||||
/// (Otherwise column name will be too long, that will lead to significant slowdown of expression analysis.)
|
||||
|
@ -18,8 +18,6 @@ public:
|
||||
ASTLiteral() = default;
|
||||
ASTLiteral(const StringRange range_, const Field & value_) : ASTWithAlias(range_), value(value_) {}
|
||||
|
||||
String getColumnName() const override;
|
||||
|
||||
/** Get the text that identifies this element. */
|
||||
String getID() const override { return "Literal_" + applyVisitor(FieldVisitorDump(), value); }
|
||||
|
||||
@ -30,6 +28,7 @@ protected:
|
||||
{
|
||||
settings.ostr << applyVisitor(FieldVisitorToString(), value);
|
||||
}
|
||||
String getColumnNameImpl() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -197,6 +197,7 @@ std::shared_ptr<ASTSelectQuery> ASTSelectQuery::cloneImpl(bool traverse_union_al
|
||||
* And if the cloning order does not match the parsing order,
|
||||
* then different servers will get different identifiers.
|
||||
*/
|
||||
CLONE(with_expression_list)
|
||||
CLONE(select_expression_list)
|
||||
CLONE(tables)
|
||||
CLONE(prewhere_expression)
|
||||
@ -232,6 +233,15 @@ void ASTSelectQuery::formatQueryImpl(const FormatSettings & s, FormatState & sta
|
||||
frame.need_parens = false;
|
||||
std::string indent_str = s.one_line ? "" : std::string(4 * frame.indent, ' ');
|
||||
|
||||
if (with_expression_list)
|
||||
{
|
||||
s.ostr << (s.hilite ? hilite_keyword : "") << indent_str << "WITH " << (s.hilite ? hilite_none : "");
|
||||
s.one_line
|
||||
? with_expression_list->formatImpl(s, state, frame)
|
||||
: typeid_cast<const ASTExpressionList &>(*with_expression_list).formatImplMultiline(s, state, frame);
|
||||
s.ostr << s.nl_or_ws;
|
||||
}
|
||||
|
||||
s.ostr << (s.hilite ? hilite_keyword : "") << indent_str << "SELECT " << (distinct ? "DISTINCT " : "") << (s.hilite ? hilite_none : "");
|
||||
|
||||
s.one_line
|
||||
|
@ -46,6 +46,7 @@ private:
|
||||
|
||||
public:
|
||||
bool distinct = false;
|
||||
ASTPtr with_expression_list;
|
||||
ASTPtr select_expression_list;
|
||||
ASTPtr tables;
|
||||
ASTPtr prewhere_expression;
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
String ASTSubquery::getColumnName() const
|
||||
String ASTSubquery::getColumnNameImpl() const
|
||||
{
|
||||
/// This is a hack. We use alias, if available, because otherwise tree could change during analysis.
|
||||
return alias.empty() ? getTreeID() : alias;
|
||||
|
@ -31,8 +31,6 @@ public:
|
||||
return ptr;
|
||||
}
|
||||
|
||||
String getColumnName() const override;
|
||||
|
||||
protected:
|
||||
void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override
|
||||
{
|
||||
@ -46,6 +44,7 @@ protected:
|
||||
children[0]->formatImpl(settings, state, frame_nested);
|
||||
settings.ostr << nl_or_nothing << indent_str << ")";
|
||||
}
|
||||
String getColumnNameImpl() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -14,10 +14,14 @@ class ASTWithAlias : public IAST
|
||||
public:
|
||||
/// The alias, if any, or an empty string.
|
||||
String alias;
|
||||
/// If is true, getColumnName returns alias. Uses for aliases in former WITH section of SELECT query.
|
||||
/// Example: 'WITH pow(2, 2) as a SELECT pow(a, 2)' returns 'pow(a, 2)' instead of 'pow(pow(2, 2), 2)'
|
||||
bool prefer_alias_to_column_name = false;
|
||||
|
||||
using IAST::IAST;
|
||||
|
||||
String getAliasOrColumnName() const override { return alias.empty() ? getColumnName() : alias; }
|
||||
String getColumnName() const override final { return prefer_alias_to_column_name && !alias.empty() ? alias : getColumnNameImpl(); }
|
||||
String getAliasOrColumnName() const override { return alias.empty() ? getColumnNameImpl() : alias; }
|
||||
String tryGetAlias() const override { return alias; }
|
||||
void setAlias(const String & to) override { alias = to; }
|
||||
|
||||
@ -25,6 +29,9 @@ public:
|
||||
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override final;
|
||||
|
||||
virtual void formatImplWithoutAlias(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const = 0;
|
||||
|
||||
protected:
|
||||
virtual String getColumnNameImpl() const = 0;
|
||||
};
|
||||
|
||||
/// helper for setting aliases and chaining result to other functions
|
||||
|
@ -767,7 +767,10 @@ bool ParserWithOptionalAliasImpl<ParserAlias>::parseImpl(Pos & pos, ASTPtr & nod
|
||||
String alias_name = typeid_cast<ASTIdentifier &>(*alias_node).name;
|
||||
|
||||
if (ASTWithAlias * ast_with_alias = dynamic_cast<ASTWithAlias *>(node.get()))
|
||||
{
|
||||
ast_with_alias->alias = alias_name;
|
||||
ast_with_alias->prefer_alias_to_column_name = prefer_alias_to_column_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
expected.add(pos, "alias cannot be here");
|
||||
|
@ -209,11 +209,13 @@ template <typename ParserAlias>
|
||||
class ParserWithOptionalAliasImpl : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserWithOptionalAliasImpl(ParserPtr && elem_parser_, bool allow_alias_without_as_keyword_)
|
||||
: elem_parser(std::move(elem_parser_)), allow_alias_without_as_keyword(allow_alias_without_as_keyword_) {}
|
||||
ParserWithOptionalAliasImpl(ParserPtr && elem_parser_, bool allow_alias_without_as_keyword_, bool prefer_alias_to_column_name_ = false)
|
||||
: elem_parser(std::move(elem_parser_)), allow_alias_without_as_keyword(allow_alias_without_as_keyword_),
|
||||
prefer_alias_to_column_name(prefer_alias_to_column_name_) {}
|
||||
protected:
|
||||
ParserPtr elem_parser;
|
||||
bool allow_alias_without_as_keyword;
|
||||
bool prefer_alias_to_column_name;
|
||||
|
||||
const char * getName() const { return "element of expression with optional alias"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
|
||||
|
@ -532,14 +532,16 @@ bool ParserTupleElementExpression::parseImpl(Pos & pos, ASTPtr & node, Expected
|
||||
}
|
||||
|
||||
|
||||
ParserExpressionWithOptionalAlias::ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword)
|
||||
: impl(std::make_unique<ParserWithOptionalAlias>(std::make_unique<ParserExpression>(), allow_alias_without_as_keyword))
|
||||
ParserExpressionWithOptionalAlias::ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword, bool prefer_alias_to_column_name)
|
||||
: impl(std::make_unique<ParserWithOptionalAlias>(std::make_unique<ParserExpression>(),
|
||||
allow_alias_without_as_keyword, prefer_alias_to_column_name))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ParserExpressionInCastExpression::ParserExpressionInCastExpression(bool allow_alias_without_as_keyword)
|
||||
: impl(std::make_unique<ParserCastExpressionWithOptionalAlias>(std::make_unique<ParserExpression>(), allow_alias_without_as_keyword))
|
||||
: impl(std::make_unique<ParserCastExpressionWithOptionalAlias>(std::make_unique<ParserExpression>(),
|
||||
allow_alias_without_as_keyword, false))
|
||||
{
|
||||
}
|
||||
|
||||
@ -547,7 +549,7 @@ ParserExpressionInCastExpression::ParserExpressionInCastExpression(bool allow_al
|
||||
bool ParserExpressionList::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
{
|
||||
return ParserList(
|
||||
std::make_unique<ParserExpressionWithOptionalAlias>(allow_alias_without_as_keyword),
|
||||
std::make_unique<ParserExpressionWithOptionalAlias>(allow_alias_without_as_keyword, prefer_alias_to_column_name),
|
||||
std::make_unique<ParserToken>(TokenType::Comma))
|
||||
.parse(pos, node, expected);
|
||||
}
|
||||
|
@ -311,7 +311,7 @@ using ParserExpression = ParserLambdaExpression;
|
||||
class ParserExpressionWithOptionalAlias : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword);
|
||||
ParserExpressionWithOptionalAlias(bool allow_alias_without_as_keyword, bool prefer_alias_to_column_name_ = false);
|
||||
protected:
|
||||
ParserPtr impl;
|
||||
|
||||
@ -343,11 +343,12 @@ protected:
|
||||
class ParserExpressionList : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserExpressionList(bool allow_alias_without_as_keyword_)
|
||||
: allow_alias_without_as_keyword(allow_alias_without_as_keyword_) {}
|
||||
ParserExpressionList(bool allow_alias_without_as_keyword_, bool prefer_alias_to_column_name_ = false)
|
||||
: allow_alias_without_as_keyword(allow_alias_without_as_keyword_), prefer_alias_to_column_name(prefer_alias_to_column_name_) {}
|
||||
|
||||
protected:
|
||||
bool allow_alias_without_as_keyword;
|
||||
bool prefer_alias_to_column_name;
|
||||
|
||||
const char * getName() const { return "list of expressions"; }
|
||||
bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected);
|
||||
@ -357,8 +358,8 @@ protected:
|
||||
class ParserNotEmptyExpressionList : public IParserBase
|
||||
{
|
||||
public:
|
||||
ParserNotEmptyExpressionList(bool allow_alias_without_as_keyword)
|
||||
: nested_parser(allow_alias_without_as_keyword) {}
|
||||
ParserNotEmptyExpressionList(bool allow_alias_without_as_keyword, bool prefer_alias_to_column_name = false)
|
||||
: nested_parser(allow_alias_without_as_keyword, prefer_alias_to_column_name) {}
|
||||
private:
|
||||
ParserExpressionList nested_parser;
|
||||
protected:
|
||||
|
@ -42,10 +42,20 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
ParserKeyword s_by("BY");
|
||||
|
||||
ParserNotEmptyExpressionList exp_list(false);
|
||||
ParserNotEmptyExpressionList exp_list_for_former_with_clause(false, true); /// Set prefer_alias_to_column_name for each alias.
|
||||
ParserNotEmptyExpressionList exp_list_for_select_clause(true); /// Allows aliases without AS keyword.
|
||||
ParserExpression exp_elem;
|
||||
ParserOrderByExpressionList order_list;
|
||||
|
||||
/// WITH expr list
|
||||
{
|
||||
if (s_with.ignore(pos, expected))
|
||||
{
|
||||
if (!exp_list_for_former_with_clause.parse(pos, select_query->with_expression_list, expected))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// SELECT [DISTINCT] expr list
|
||||
{
|
||||
if (!s_select.ignore(pos, expected))
|
||||
@ -175,6 +185,8 @@ bool ParserSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||
|
||||
select_query->range = StringRange(begin, pos);
|
||||
|
||||
if (select_query->with_expression_list)
|
||||
select_query->children.push_back(select_query->with_expression_list);
|
||||
select_query->children.push_back(select_query->select_expression_list);
|
||||
if (select_query->tables)
|
||||
select_query->children.push_back(select_query->tables);
|
||||
|
Loading…
Reference in New Issue
Block a user