1/*
2 Copyright (c) 2016, 2017 MariaDB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17#ifndef SQL_WINDOW_INCLUDED
18#define SQL_WINDOW_INCLUDED
19
20#include "filesort.h"
21#include "records.h"
22
23class Item_window_func;
24
25/*
26 Window functions module.
27
28 Each instance of window function has its own element in SELECT_LEX::window_specs.
29*/
30
31
32class Window_frame_bound : public Sql_alloc
33{
34
35public:
36
37 enum Bound_precedence_type
38 {
39 PRECEDING,
40 CURRENT, // Used for CURRENT ROW window frame bounds
41 FOLLOWING
42 };
43
44 Bound_precedence_type precedence_type;
45
46
47 /*
48 For UNBOUNDED PRECEDING / UNBOUNDED FOLLOWING window frame bounds
49 precedence type is seto to PRECEDING / FOLLOWING and
50 offset is set to NULL.
51 The offset is not meaningful with precedence type CURRENT
52 */
53 Item *offset;
54
55 Window_frame_bound(Bound_precedence_type prec_type,
56 Item *offset_val)
57 : precedence_type(prec_type), offset(offset_val) {}
58
59 bool is_unbounded() { return offset == NULL; }
60
61 void print(String *str, enum_query_type query_type);
62
63};
64
65
66class Window_frame : public Sql_alloc
67{
68
69public:
70
71 enum Frame_units
72 {
73 UNITS_ROWS,
74 UNITS_RANGE
75 };
76
77 enum Frame_exclusion
78 {
79 EXCL_NONE,
80 EXCL_CURRENT_ROW,
81 EXCL_GROUP,
82 EXCL_TIES
83 };
84
85 Frame_units units;
86
87 Window_frame_bound *top_bound;
88
89 Window_frame_bound *bottom_bound;
90
91 Frame_exclusion exclusion;
92
93 Window_frame(Frame_units win_frame_units,
94 Window_frame_bound *win_frame_top_bound,
95 Window_frame_bound *win_frame_bottom_bound,
96 Frame_exclusion win_frame_exclusion)
97 : units(win_frame_units), top_bound(win_frame_top_bound),
98 bottom_bound(win_frame_bottom_bound), exclusion(win_frame_exclusion) {}
99
100 bool check_frame_bounds();
101
102 void print(String *str, enum_query_type query_type);
103
104};
105
106class Window_spec : public Sql_alloc
107{
108 bool window_names_are_checked;
109 public:
110 virtual ~Window_spec() {}
111
112 LEX_CSTRING *window_ref;
113
114 SQL_I_List<ORDER> *partition_list;
115
116 SQL_I_List<ORDER> *order_list;
117
118 Window_frame *window_frame;
119
120 Window_spec *referenced_win_spec;
121
122 Window_spec(LEX_CSTRING *win_ref,
123 SQL_I_List<ORDER> *part_list,
124 SQL_I_List<ORDER> *ord_list,
125 Window_frame *win_frame)
126 : window_names_are_checked(false), window_ref(win_ref),
127 partition_list(part_list), order_list(ord_list),
128 window_frame(win_frame), referenced_win_spec(NULL) {}
129
130 virtual const char *name() { return NULL; }
131
132 bool check_window_names(List_iterator_fast<Window_spec> &it);
133
134 const char *window_reference()
135 {
136 return window_ref ? window_ref->str : NULL;
137 }
138
139 void join_partition_and_order_lists()
140 {
141 *(partition_list->next)= order_list->first;
142 }
143
144 void disjoin_partition_and_order_lists()
145 {
146 *(partition_list->next)= NULL;
147 }
148
149 void print(String *str, enum_query_type query_type);
150
151};
152
153class Window_def : public Window_spec
154{
155 public:
156
157 LEX_CSTRING *window_name;
158
159 Window_def(LEX_CSTRING *win_name,
160 LEX_CSTRING *win_ref,
161 SQL_I_List<ORDER> *part_list,
162 SQL_I_List<ORDER> *ord_list,
163 Window_frame *win_frame)
164 : Window_spec(win_ref, part_list, ord_list, win_frame),
165 window_name(win_name) {}
166
167 const char *name() { return window_name->str; }
168
169};
170
171int setup_windows(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables,
172 List<Item> &fields, List<Item> &all_fields,
173 List<Window_spec> &win_specs, List<Item_window_func> &win_funcs);
174
175
176//////////////////////////////////////////////////////////////////////////////
177// Classes that make window functions computation a part of SELECT's query plan
178//////////////////////////////////////////////////////////////////////////////
179
180class Frame_cursor;
181/*
182 This handles computation of one window function.
183
184 Currently, we make a spearate filesort() call for each window function.
185*/
186
187class Window_func_runner : public Sql_alloc
188{
189public:
190 /* Add the function to be computed during the execution pass */
191 bool add_function_to_run(Item_window_func *win_func);
192
193 /* Compute and fill the fields in the table. */
194 bool exec(THD *thd, TABLE *tbl, SORT_INFO *filesort_result);
195
196private:
197 /* A list of window functions for which this Window_func_runner will compute
198 values during the execution phase. */
199 List<Item_window_func> window_functions;
200};
201
202
203/*
204 Represents a group of window functions that require the same sorting of
205 rows and so share the filesort() call.
206
207*/
208
209class Window_funcs_sort : public Sql_alloc
210{
211public:
212 bool setup(THD *thd, SQL_SELECT *sel, List_iterator<Item_window_func> &it,
213 st_join_table *join_tab);
214 bool exec(JOIN *join);
215 void cleanup() { delete filesort; }
216
217 friend class Window_funcs_computation;
218
219private:
220 Window_func_runner runner;
221
222 /* Window functions can be computed over this sorting */
223 Filesort *filesort;
224};
225
226
227struct st_join_table;
228class Explain_aggr_window_funcs;
229
230/*
231 This is a "window function computation phase": a single object of this class
232 takes care of computing all window functions in a SELECT.
233
234 - JOIN optimizer is exected to call setup() during query optimization.
235 - JOIN::exec() should call exec() once it has collected join output in a
236 temporary table.
237*/
238
239class Window_funcs_computation : public Sql_alloc
240{
241 List<Window_funcs_sort> win_func_sorts;
242public:
243 bool setup(THD *thd, List<Item_window_func> *window_funcs, st_join_table *tab);
244 bool exec(JOIN *join);
245
246 Explain_aggr_window_funcs *save_explain_plan(MEM_ROOT *mem_root, bool is_analyze);
247 void cleanup();
248};
249
250
251#endif /* SQL_WINDOW_INCLUDED */
252