2021-01-30 01:16:44 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <Common/FieldVisitors.h>
|
|
|
|
#include <Core/Field.h>
|
|
|
|
#include <Parsers/IAST_fwd.h>
|
|
|
|
#include <AggregateFunctions/IAggregateFunction.h>
|
|
|
|
#include <Core/SortDescription.h>
|
|
|
|
#include <DataTypes/IDataType.h>
|
|
|
|
#include <Core/Names.h>
|
|
|
|
#include <Core/Types.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
class ASTFunction;
|
|
|
|
|
|
|
|
struct WindowFunctionDescription
|
|
|
|
{
|
|
|
|
std::string column_name;
|
2021-02-09 16:50:39 +00:00
|
|
|
const ASTFunction * function_node = nullptr;
|
2021-01-30 01:16:44 +00:00
|
|
|
AggregateFunctionPtr aggregate_function;
|
|
|
|
Array function_parameters;
|
|
|
|
DataTypes argument_types;
|
|
|
|
Names argument_names;
|
|
|
|
|
|
|
|
std::string dump() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct WindowFrame
|
|
|
|
{
|
|
|
|
enum class FrameType { Rows, Groups, Range };
|
|
|
|
enum class BoundaryType { 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 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
|
|
|
|
bool is_default = true;
|
|
|
|
|
|
|
|
FrameType type = FrameType::Range;
|
|
|
|
|
2021-02-09 11:56:11 +00:00
|
|
|
// UNBOUNDED FOLLOWING for the frame end is forbidden by the standard, but for
|
|
|
|
// uniformity the begin_preceding still has to be set to true for UNBOUNDED
|
|
|
|
// frame start.
|
2021-02-05 09:13:19 +00:00
|
|
|
// Offset might be both preceding and following, controlled by begin_preceding,
|
|
|
|
// but the offset value must be positive.
|
2021-01-30 01:16:44 +00:00
|
|
|
BoundaryType begin_type = BoundaryType::Unbounded;
|
|
|
|
// This should have been a Field but I'm getting some crazy linker errors.
|
|
|
|
int64_t begin_offset = 0;
|
2021-02-05 09:13:19 +00:00
|
|
|
bool begin_preceding = true;
|
2021-01-30 01:16:44 +00:00
|
|
|
|
2021-02-09 11:56:11 +00:00
|
|
|
// Here as well, Unbounded can only be UNBOUNDED FOLLOWING, and end_preceding
|
|
|
|
// must be false.
|
2021-01-30 01:16:44 +00:00
|
|
|
BoundaryType end_type = BoundaryType::Current;
|
|
|
|
int64_t end_offset = 0;
|
2021-02-05 09:13:19 +00:00
|
|
|
bool end_preceding = false;
|
2021-01-30 01:16:44 +00:00
|
|
|
|
|
|
|
|
2021-02-03 12:50:25 +00:00
|
|
|
// Throws BAD_ARGUMENTS exception if the frame definition is incorrect, e.g.
|
|
|
|
// the frame start comes later than the frame end.
|
|
|
|
void checkValid() const;
|
|
|
|
|
|
|
|
std::string toString() const;
|
|
|
|
void toString(WriteBuffer & buf) const;
|
|
|
|
|
2021-01-30 01:16:44 +00:00
|
|
|
bool operator == (const WindowFrame & other) const
|
|
|
|
{
|
|
|
|
// We don't compare is_default because it's not a real property of the
|
|
|
|
// frame, and only influences how we display it.
|
|
|
|
return other.type == type
|
|
|
|
&& other.begin_type == begin_type
|
|
|
|
&& other.begin_offset == begin_offset
|
2021-02-05 09:13:19 +00:00
|
|
|
&& other.begin_preceding == begin_preceding
|
2021-01-30 01:16:44 +00:00
|
|
|
&& other.end_type == end_type
|
|
|
|
&& other.end_offset == end_offset
|
2021-02-05 09:13:19 +00:00
|
|
|
&& other.end_preceding == end_preceding
|
2021-01-30 01:16:44 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string toString(FrameType type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case FrameType::Rows:
|
|
|
|
return "ROWS";
|
|
|
|
case FrameType::Groups:
|
|
|
|
return "GROUPS";
|
|
|
|
case FrameType::Range:
|
|
|
|
return "RANGE";
|
|
|
|
}
|
2021-02-01 23:23:34 +00:00
|
|
|
|
|
|
|
// Somehow GCC 10 doesn't understand that the above switch is exhaustive.
|
|
|
|
assert(false);
|
|
|
|
return "<unknown frame>";
|
2021-01-30 01:16:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static std::string toString(BoundaryType type)
|
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case BoundaryType::Unbounded:
|
|
|
|
return "UNBOUNDED";
|
|
|
|
case BoundaryType::Offset:
|
|
|
|
return "OFFSET";
|
|
|
|
case BoundaryType::Current:
|
|
|
|
return "CURRENT ROW";
|
|
|
|
}
|
2021-02-01 23:23:34 +00:00
|
|
|
|
|
|
|
// Somehow GCC 10 doesn't understand that the above switch is exhaustive.
|
|
|
|
assert(false);
|
|
|
|
return "<unknown frame boundary>";
|
2021-01-30 01:16:44 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct WindowDescription
|
|
|
|
{
|
|
|
|
std::string window_name;
|
|
|
|
|
|
|
|
// We don't care about the particular order of keys for PARTITION BY, only
|
|
|
|
// that they are sorted. For now we always require ASC, but we could be more
|
|
|
|
// flexible and match any direction, or even different order of columns.
|
|
|
|
SortDescription partition_by;
|
|
|
|
|
|
|
|
SortDescription order_by;
|
|
|
|
|
|
|
|
// To calculate the window function, we sort input data first by PARTITION BY,
|
|
|
|
// then by ORDER BY. This field holds this combined sort order.
|
|
|
|
SortDescription full_sort_description;
|
|
|
|
|
|
|
|
WindowFrame frame;
|
|
|
|
|
|
|
|
// The window functions that are calculated for this window.
|
|
|
|
std::vector<WindowFunctionDescription> window_functions;
|
|
|
|
|
2021-02-09 15:36:08 +00:00
|
|
|
|
2021-01-30 01:16:44 +00:00
|
|
|
std::string dump() const;
|
2021-02-09 15:36:08 +00:00
|
|
|
|
|
|
|
void checkValid() const;
|
2021-01-30 01:16:44 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
using WindowFunctionDescriptions = std::vector<WindowFunctionDescription>;
|
|
|
|
|
|
|
|
using WindowDescriptions = std::unordered_map<std::string, WindowDescription>;
|
|
|
|
|
|
|
|
}
|