frame grammar tmp

This commit is contained in:
Alexander Kuzmenkov 2021-01-19 04:00:39 +03:00
parent d0922e2985
commit f346a9bf8b
6 changed files with 132 additions and 6 deletions

View File

@ -39,6 +39,26 @@ struct WindowFunctionDescription
std::string dump() const;
};
struct WindowFrame
{
enum class FrameType { Rows, Groups, Range };
enum class OffsetType { Unbounded, Current, Offset };
// This flag signifies that the frame properties were not set explicitly by
// user, but the fields of this structure still have to contain proper values
// for the default frame of ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
bool is_default = true;
FrameType type = FrameType::Rows;
/*
* We don't need these yet.
* OffsetType begin_offset = Unbounded;
* OffsetType end_offset = Current;
*/
};
struct WindowDescription
{
std::string window_name;
@ -54,7 +74,7 @@ struct WindowDescription
// then by ORDER BY. This field holds this combined sort order.
SortDescription full_sort_description;
// No frame info as of yet.
WindowFrame frame;
// The window functions that are calculated for this window.
std::vector<WindowFunctionDescription> window_functions;

View File

@ -515,6 +515,20 @@ void makeWindowDescription(WindowDescription & desc, const IAST * ast)
desc.full_sort_description = desc.partition_by;
desc.full_sort_description.insert(desc.full_sort_description.end(),
desc.order_by.begin(), desc.order_by.end());
if (definition.frame.type != WindowFrame::FrameType::Rows)
{
std::string name = definition.frame.type == WindowFrame::FrameType::Rows
? "ROWS"
: definition.frame.type == WindowFrame::FrameType::Groups
? "GROUPS" : "RANGE";
throw Exception(ErrorCodes::NOT_IMPLEMENTED,
"Window frame '{}' is not implemented (while processing '{}')",
name, ast->formatForErrorMessage());
}
desc.frame = definition.frame;
}
void ExpressionAnalyzer::makeWindowDescriptions(ActionsDAGPtr actions)

View File

@ -22,6 +22,8 @@ ASTPtr ASTWindowDefinition::clone() const
result->children.push_back(result->order_by);
}
result->frame = frame;
return result;
}
@ -31,12 +33,12 @@ String ASTWindowDefinition::getID(char) const
}
void ASTWindowDefinition::formatImpl(const FormatSettings & settings,
FormatState & state, FormatStateStacked frame) const
FormatState & state, FormatStateStacked format_frame) const
{
if (partition_by)
{
settings.ostr << "PARTITION BY ";
partition_by->formatImpl(settings, state, frame);
partition_by->formatImpl(settings, state, format_frame);
}
if (partition_by && order_by)
@ -47,7 +49,16 @@ void ASTWindowDefinition::formatImpl(const FormatSettings & settings,
if (order_by)
{
settings.ostr << "ORDER BY ";
order_by->formatImpl(settings, state, frame);
order_by->formatImpl(settings, state, format_frame);
}
if (!frame.is_default)
{
const auto name = frame.type == WindowFrame::FrameType::Rows
? "ROWS" : frame.type == WindowFrame::FrameType::Groups
? "GROUPS" : "RANGE";
settings.ostr << name << " BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW";
}
}
@ -56,8 +67,8 @@ std::string ASTWindowDefinition::getDefaultWindowName() const
WriteBufferFromOwnString ostr;
FormatSettings settings{ostr, true /* one_line */};
FormatState state;
FormatStateStacked frame;
formatImpl(settings, state, frame);
FormatStateStacked format_frame;
formatImpl(settings, state, format_frame);
return ostr.str();
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <Interpreters/AggregateDescription.h>
#include <Parsers/IAST.h>
@ -12,6 +14,8 @@ struct ASTWindowDefinition : public IAST
ASTPtr order_by;
WindowFrame frame;
ASTPtr clone() const override;

View File

@ -504,6 +504,65 @@ bool ParserWindowReference::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
return parser_definition.parse(pos, function->window_definition, expected);
}
static bool tryParseFrameDefinition(ASTWindowDefinition * node, IParser::Pos & pos,
Expected & expected)
{
ParserKeyword keyword_rows("ROWS");
ParserKeyword keyword_groups("GROUPS");
ParserKeyword keyword_range("RANGE");
if (keyword_rows.ignore(pos, expected))
{
node->frame.type = WindowFrame::FrameType::Rows;
}
else if (keyword_groups.ignore(pos, expected))
{
node->frame.type = WindowFrame::FrameType::Groups;
}
else if (keyword_range.ignore(pos, expected))
{
node->frame.type = WindowFrame::FrameType::Range;
}
else
{
/* No frame clause. */
return true;
}
ParserKeyword keyword_between("BETWEEN");
ParserKeyword keyword_unbounded("UNBOUNDED");
ParserKeyword keyword_preceding("PRECEDING");
ParserKeyword keyword_and("AND");
ParserKeyword keyword_current_row("CURRENT ROW");
if (!keyword_between.ignore(pos, expected))
{
return false;
}
if (!keyword_unbounded.ignore(pos, expected))
{
return false;
}
if (!keyword_preceding.ignore(pos, expected))
{
return false;
}
if (!keyword_and.ignore(pos, expected))
{
return false;
}
if (!keyword_current_row.ignore(pos, expected))
{
return false;
}
return true;
}
bool ParserWindowDefinition::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
{
auto result = std::make_shared<ASTWindowDefinition>();
@ -548,6 +607,12 @@ bool ParserWindowDefinition::parseImpl(Pos & pos, ASTPtr & node, Expected & expe
}
}
if (!tryParseFrameDefinition(result.get(), pos, expected))
{
/* Broken frame definition. */
return false;
}
ParserToken parser_closing_bracket(TokenType::ClosingRoundBracket);
if (!parser_closing_bracket.ignore(pos, expected))
{

View File

@ -92,3 +92,15 @@ from numbers(10)
window
w1 as (partition by intDiv(number, 3))
;
-- ROWS frame
select
sum(number)
over (order by number rows between unbounded preceding and current row)
from numbers(3);
select
sum(number)
over (order by number groups between unbounded preceding and current row)
from numbers(3);