aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Analyzer/WindowNode.h
blob: 30e1128b93c777186ea7bcf107bec6d7288f634e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#pragma once

#include <Analyzer/IQueryTreeNode.h>
#include <Analyzer/ListNode.h>

#include <Interpreters/WindowDescription.h>

namespace DB
{

/** Window node represents window function window description.
  *
  * Example: SELECT * FROM test_table WINDOW window AS (PARTITION BY id);
  * window AS (PARTITION BY id) - window node.
  *
  * Example: SELECT count() OVER (PARTITION BY id) FROM test_table;
  * PARTITION BY id - window node.
  *
  * Window node can also refer to its parent window node.
  * Example: SELECT count() OVER (parent_window ORDER BY id) FROM test_table WINDOW parent_window AS (PARTITION BY id);
  * parent_window ORDER BY id - window node.
  *
  * Window node initially initialized with window frame.
  *
  * If window frame has OFFSET begin type, additionally frame begin offset node must be initialized.
  * If window frame has OFFSET end type, additionally frame end offset node must be initialized.
  * During query analysis pass they must be resolved, validated and window node window frame offset constants must be updated.
  */
class WindowNode;
using WindowNodePtr = std::shared_ptr<WindowNode>;

class WindowNode final : public IQueryTreeNode
{
public:
    /// Initialize window node with window frame
    explicit WindowNode(WindowFrame window_frame_);

    /// Get window node window frame
    const WindowFrame & getWindowFrame() const
    {
        return window_frame;
    }

    /// Get window node window frame
    WindowFrame & getWindowFrame()
    {
        return window_frame;
    }

    /// Returns true if window node has parent window name, false otherwise
    bool hasParentWindowName() const
    {
        return parent_window_name.empty();
    }

    /// Get parent window name
    const String & getParentWindowName() const
    {
        return parent_window_name;
    }

    /// Set parent window name
    void setParentWindowName(String parent_window_name_value)
    {
        parent_window_name = std::move(parent_window_name_value);
    }

    /// Returns true if window node has order by, false otherwise
    bool hasOrderBy() const
    {
        return !getOrderBy().getNodes().empty();
    }

    /// Get order by
    const ListNode & getOrderBy() const
    {
        return children[order_by_child_index]->as<const ListNode &>();
    }

    /// Get order by
    ListNode & getOrderBy()
    {
        return children[order_by_child_index]->as<ListNode &>();
    }

    /// Get order by node
    const QueryTreeNodePtr & getOrderByNode() const
    {
        return children[order_by_child_index];
    }

    /// Get order by node
    QueryTreeNodePtr & getOrderByNode()
    {
        return children[order_by_child_index];
    }

    /// Returns true if window node has partition by, false otherwise
    bool hasPartitionBy() const
    {
        return !getPartitionBy().getNodes().empty();
    }

    /// Get partition by
    const ListNode & getPartitionBy() const
    {
        return children[partition_by_child_index]->as<const ListNode &>();
    }

    /// Get partition by
    ListNode & getPartitionBy()
    {
        return children[partition_by_child_index]->as<ListNode &>();
    }

    /// Get partition by node
    const QueryTreeNodePtr & getPartitionByNode() const
    {
        return children[partition_by_child_index];
    }

    /// Get partition by node
    QueryTreeNodePtr & getPartitionByNode()
    {
        return children[partition_by_child_index];
    }

    /// Returns true if window node has FRAME begin offset, false otherwise
    bool hasFrameBeginOffset() const
    {
        return getFrameBeginOffsetNode() != nullptr;
    }

    /// Get FRAME begin offset node
    const QueryTreeNodePtr & getFrameBeginOffsetNode() const
    {
        return children[frame_begin_offset_child_index];
    }

    /// Get FRAME begin offset node
    QueryTreeNodePtr & getFrameBeginOffsetNode()
    {
        return children[frame_begin_offset_child_index];
    }

    /// Returns true if window node has FRAME end offset, false otherwise
    bool hasFrameEndOffset() const
    {
        return getFrameEndOffsetNode() != nullptr;
    }

    /// Get FRAME end offset node
    const QueryTreeNodePtr & getFrameEndOffsetNode() const
    {
        return children[frame_end_offset_child_index];
    }

    /// Get FRAME end offset node
    QueryTreeNodePtr & getFrameEndOffsetNode()
    {
        return children[frame_end_offset_child_index];
    }

    QueryTreeNodeType getNodeType() const override
    {
        return QueryTreeNodeType::WINDOW;
    }

    void dumpTreeImpl(WriteBuffer & buffer, FormatState & format_state, size_t indent) const override;

protected:
    bool isEqualImpl(const IQueryTreeNode & rhs) const override;

    void updateTreeHashImpl(HashState & hash_state) const override;

    QueryTreeNodePtr cloneImpl() const override;

    ASTPtr toASTImpl(const ConvertToASTOptions & options) const override;

private:
    static constexpr size_t order_by_child_index = 0;
    static constexpr size_t partition_by_child_index = 1;
    static constexpr size_t frame_begin_offset_child_index = 3;
    static constexpr size_t frame_end_offset_child_index = 4;
    static constexpr size_t children_size = frame_end_offset_child_index + 1;

    WindowFrame window_frame;
    String parent_window_name;
};

}