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 | |
23 | class 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 | |
32 | class Window_frame_bound : public Sql_alloc |
33 | { |
34 | |
35 | public: |
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 | |
66 | class Window_frame : public Sql_alloc |
67 | { |
68 | |
69 | public: |
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 | |
106 | class 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 | |
153 | class 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 | |
171 | int 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 | |
180 | class 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 | |
187 | class Window_func_runner : public Sql_alloc |
188 | { |
189 | public: |
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 | |
196 | private: |
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 | |
209 | class Window_funcs_sort : public Sql_alloc |
210 | { |
211 | public: |
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 | |
219 | private: |
220 | Window_func_runner runner; |
221 | |
222 | /* Window functions can be computed over this sorting */ |
223 | Filesort *filesort; |
224 | }; |
225 | |
226 | |
227 | struct st_join_table; |
228 | class 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 | |
239 | class Window_funcs_computation : public Sql_alloc |
240 | { |
241 | List<Window_funcs_sort> win_func_sorts; |
242 | public: |
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 | |