1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2016-2017 Brazil |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License version 2.1 as published by the Free Software Foundation. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with this library; if not, write to the Free Software |
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ |
18 | |
19 | #include "grn_db.h" |
20 | #include "grn_window_functions.h" |
21 | |
22 | static grn_rc |
23 | window_record_number(grn_ctx *ctx, |
24 | grn_obj *output_column, |
25 | grn_window *window, |
26 | grn_obj **args, |
27 | int n_args) |
28 | { |
29 | grn_id id; |
30 | uint32_t nth_record = 1; |
31 | grn_obj value; |
32 | |
33 | GRN_UINT32_INIT(&value, 0); |
34 | while ((id = grn_window_next(ctx, window))) { |
35 | GRN_UINT32_SET(ctx, &value, nth_record); |
36 | grn_obj_set_value(ctx, output_column, id, &value, GRN_OBJ_SET); |
37 | nth_record++; |
38 | } |
39 | GRN_OBJ_FIN(ctx, &value); |
40 | |
41 | return GRN_SUCCESS; |
42 | } |
43 | |
44 | static grn_rc |
45 | window_sum(grn_ctx *ctx, |
46 | grn_obj *output_column, |
47 | grn_window *window, |
48 | grn_obj **args, |
49 | int n_args) |
50 | { |
51 | grn_id id; |
52 | grn_obj *target; |
53 | |
54 | if (n_args != 1) { |
55 | GRN_PLUGIN_ERROR(ctx, |
56 | GRN_INVALID_ARGUMENT, |
57 | "window_sum(): wrong number of arguments (%d for 1)" , |
58 | n_args); |
59 | return ctx->rc; |
60 | } |
61 | |
62 | target = args[0]; |
63 | if (target->header.type != GRN_ACCESSOR) { |
64 | grn_obj inspected; |
65 | GRN_TEXT_INIT(&inspected, 0); |
66 | grn_inspect(ctx, &inspected, target); |
67 | GRN_PLUGIN_ERROR(ctx, |
68 | GRN_INVALID_ARGUMENT, |
69 | "window_sum(): " |
70 | "the target column must be accessor: <%.*s>" , |
71 | (int)GRN_TEXT_LEN(&inspected), |
72 | GRN_TEXT_VALUE(&inspected)); |
73 | GRN_OBJ_FIN(ctx, &inspected); |
74 | return ctx->rc; |
75 | } |
76 | |
77 | { |
78 | const grn_id output_column_range_id = grn_obj_get_range(ctx, output_column); |
79 | const grn_id target_range_id = grn_obj_get_range(ctx, target); |
80 | grn_obj sum; |
81 | grn_obj value; |
82 | |
83 | switch (target_range_id) { |
84 | case GRN_DB_INT8 : |
85 | case GRN_DB_INT16 : |
86 | case GRN_DB_INT32 : |
87 | case GRN_DB_INT64 : |
88 | case GRN_DB_UINT8 : |
89 | case GRN_DB_UINT16 : |
90 | case GRN_DB_UINT32 : |
91 | case GRN_DB_UINT64 : |
92 | case GRN_DB_FLOAT : |
93 | break; |
94 | default : |
95 | { |
96 | grn_obj inspected; |
97 | GRN_TEXT_INIT(&inspected, 0); |
98 | grn_inspect(ctx, &inspected, target); |
99 | GRN_PLUGIN_ERROR(ctx, |
100 | GRN_INVALID_ARGUMENT, |
101 | "window_sum(): " |
102 | "the target column must be number column: <%.*s>" , |
103 | (int)GRN_TEXT_LEN(&inspected), |
104 | GRN_TEXT_VALUE(&inspected)); |
105 | GRN_OBJ_FIN(ctx, &inspected); |
106 | return ctx->rc; |
107 | } |
108 | break; |
109 | } |
110 | |
111 | switch (output_column_range_id) { |
112 | case GRN_DB_INT8 : |
113 | case GRN_DB_INT16 : |
114 | case GRN_DB_INT32 : |
115 | case GRN_DB_INT64 : |
116 | GRN_INT64_INIT(&sum, 0); |
117 | break; |
118 | case GRN_DB_UINT8 : |
119 | case GRN_DB_UINT16 : |
120 | case GRN_DB_UINT32 : |
121 | case GRN_DB_UINT64 : |
122 | GRN_UINT64_INIT(&sum, 0); |
123 | break; |
124 | case GRN_DB_FLOAT : |
125 | GRN_FLOAT_INIT(&sum, 0); |
126 | break; |
127 | default : |
128 | { |
129 | grn_obj inspected; |
130 | GRN_TEXT_INIT(&inspected, 0); |
131 | grn_inspect(ctx, &inspected, output_column); |
132 | GRN_PLUGIN_ERROR(ctx, |
133 | GRN_INVALID_ARGUMENT, |
134 | "window_sum(): " |
135 | "the output column must be number column: <%.*s>" , |
136 | (int)GRN_TEXT_LEN(&inspected), |
137 | GRN_TEXT_VALUE(&inspected)); |
138 | GRN_OBJ_FIN(ctx, &inspected); |
139 | return ctx->rc; |
140 | } |
141 | break; |
142 | } |
143 | GRN_VOID_INIT(&value); |
144 | |
145 | if (grn_window_is_sorted(ctx, window)) { |
146 | while ((id = grn_window_next(ctx, window))) { |
147 | GRN_BULK_REWIND(&value); |
148 | grn_obj_get_value(ctx, target, id, &value); |
149 | switch (target_range_id) { |
150 | case GRN_DB_INT8 : |
151 | GRN_INT64_SET(ctx, |
152 | &sum, |
153 | GRN_INT64_VALUE(&sum) + GRN_INT8_VALUE(&value)); |
154 | break; |
155 | case GRN_DB_INT16 : |
156 | GRN_INT64_SET(ctx, |
157 | &sum, |
158 | GRN_INT64_VALUE(&sum) + GRN_INT16_VALUE(&value)); |
159 | break; |
160 | case GRN_DB_INT32 : |
161 | GRN_INT64_SET(ctx, |
162 | &sum, |
163 | GRN_INT64_VALUE(&sum) + GRN_INT32_VALUE(&value)); |
164 | break; |
165 | case GRN_DB_INT64 : |
166 | GRN_INT64_SET(ctx, |
167 | &sum, |
168 | GRN_INT64_VALUE(&sum) + GRN_INT64_VALUE(&value)); |
169 | break; |
170 | case GRN_DB_UINT8 : |
171 | GRN_UINT64_SET(ctx, |
172 | &sum, |
173 | GRN_UINT64_VALUE(&sum) + GRN_UINT8_VALUE(&value)); |
174 | break; |
175 | case GRN_DB_UINT16 : |
176 | GRN_UINT64_SET(ctx, |
177 | &sum, |
178 | GRN_UINT64_VALUE(&sum) + GRN_UINT16_VALUE(&value)); |
179 | break; |
180 | case GRN_DB_UINT32 : |
181 | GRN_UINT64_SET(ctx, |
182 | &sum, |
183 | GRN_UINT64_VALUE(&sum) + GRN_UINT32_VALUE(&value)); |
184 | break; |
185 | case GRN_DB_UINT64 : |
186 | GRN_UINT64_SET(ctx, |
187 | &sum, |
188 | GRN_UINT64_VALUE(&sum) + GRN_UINT64_VALUE(&value)); |
189 | break; |
190 | case GRN_DB_FLOAT : |
191 | GRN_FLOAT_SET(ctx, |
192 | &sum, |
193 | GRN_FLOAT_VALUE(&sum) + GRN_FLOAT_VALUE(&value)); |
194 | break; |
195 | default : |
196 | break; |
197 | } |
198 | grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET); |
199 | } |
200 | } else { |
201 | int64_t sum_raw_int64 = 0; |
202 | uint64_t sum_raw_uint64 = 0; |
203 | double sum_raw_double = 0.0; |
204 | |
205 | while ((id = grn_window_next(ctx, window))) { |
206 | GRN_BULK_REWIND(&value); |
207 | grn_obj_get_value(ctx, target, id, &value); |
208 | switch (target_range_id) { |
209 | case GRN_DB_INT8 : |
210 | sum_raw_int64 += GRN_INT8_VALUE(&value); |
211 | break; |
212 | case GRN_DB_INT16 : |
213 | sum_raw_int64 += GRN_INT16_VALUE(&value); |
214 | break; |
215 | case GRN_DB_INT32 : |
216 | sum_raw_int64 += GRN_INT32_VALUE(&value); |
217 | break; |
218 | case GRN_DB_INT64 : |
219 | sum_raw_int64 += GRN_INT64_VALUE(&value); |
220 | break; |
221 | case GRN_DB_UINT8 : |
222 | sum_raw_uint64 += GRN_UINT8_VALUE(&value); |
223 | break; |
224 | case GRN_DB_UINT16 : |
225 | sum_raw_uint64 += GRN_UINT16_VALUE(&value); |
226 | break; |
227 | case GRN_DB_UINT32 : |
228 | sum_raw_uint64 += GRN_UINT32_VALUE(&value); |
229 | break; |
230 | case GRN_DB_UINT64 : |
231 | sum_raw_uint64 += GRN_UINT64_VALUE(&value); |
232 | break; |
233 | case GRN_DB_FLOAT : |
234 | sum_raw_double += GRN_FLOAT_VALUE(&value); |
235 | break; |
236 | default : |
237 | break; |
238 | } |
239 | } |
240 | |
241 | switch (output_column_range_id) { |
242 | case GRN_DB_INT8 : |
243 | case GRN_DB_INT16 : |
244 | case GRN_DB_INT32 : |
245 | case GRN_DB_INT64 : |
246 | GRN_INT64_SET(ctx, &sum, sum_raw_int64); |
247 | break; |
248 | case GRN_DB_UINT8 : |
249 | case GRN_DB_UINT16 : |
250 | case GRN_DB_UINT32 : |
251 | case GRN_DB_UINT64 : |
252 | GRN_UINT64_SET(ctx, &sum, sum_raw_uint64); |
253 | break; |
254 | case GRN_DB_FLOAT : |
255 | GRN_FLOAT_SET(ctx, &sum, sum_raw_double); |
256 | break; |
257 | } |
258 | |
259 | grn_window_rewind(ctx, window); |
260 | while ((id = grn_window_next(ctx, window))) { |
261 | grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET); |
262 | } |
263 | } |
264 | |
265 | GRN_OBJ_FIN(ctx, &value); |
266 | GRN_OBJ_FIN(ctx, &sum); |
267 | } |
268 | |
269 | return GRN_SUCCESS; |
270 | } |
271 | |
272 | static grn_rc |
273 | window_count(grn_ctx *ctx, |
274 | grn_obj *output_column, |
275 | grn_window *window, |
276 | grn_obj **args, |
277 | int n_args) |
278 | { |
279 | grn_id id; |
280 | grn_id output_column_range_id; |
281 | grn_obj n_records; |
282 | uint32_t n_records_raw = 0; |
283 | |
284 | |
285 | if (n_args != 0) { |
286 | GRN_PLUGIN_ERROR(ctx, |
287 | GRN_INVALID_ARGUMENT, |
288 | "window_count(): wrong number of arguments (%d for 0)" , |
289 | n_args); |
290 | return ctx->rc; |
291 | } |
292 | |
293 | output_column_range_id = grn_obj_get_range(ctx, output_column); |
294 | switch (output_column_range_id) { |
295 | case GRN_DB_INT8 : |
296 | case GRN_DB_INT16 : |
297 | case GRN_DB_INT32 : |
298 | case GRN_DB_INT64 : |
299 | GRN_INT64_INIT(&n_records, 0); |
300 | break; |
301 | case GRN_DB_UINT8 : |
302 | case GRN_DB_UINT16 : |
303 | case GRN_DB_UINT32 : |
304 | case GRN_DB_UINT64 : |
305 | GRN_UINT64_INIT(&n_records, 0); |
306 | break; |
307 | case GRN_DB_FLOAT : |
308 | GRN_FLOAT_INIT(&n_records, 0); |
309 | break; |
310 | default : |
311 | { |
312 | grn_obj inspected; |
313 | GRN_TEXT_INIT(&inspected, 0); |
314 | grn_inspect(ctx, &inspected, output_column); |
315 | GRN_PLUGIN_ERROR(ctx, |
316 | GRN_INVALID_ARGUMENT, |
317 | "window_count(): " |
318 | "the output column must be number column: <%.*s>" , |
319 | (int)GRN_TEXT_LEN(&inspected), |
320 | GRN_TEXT_VALUE(&inspected)); |
321 | GRN_OBJ_FIN(ctx, &inspected); |
322 | return ctx->rc; |
323 | } |
324 | break; |
325 | } |
326 | |
327 | if (grn_window_is_sorted(ctx, window)) { |
328 | while ((id = grn_window_next(ctx, window))) { |
329 | n_records_raw++; |
330 | switch (output_column_range_id) { |
331 | case GRN_DB_INT8 : |
332 | case GRN_DB_INT16 : |
333 | case GRN_DB_INT32 : |
334 | case GRN_DB_INT64 : |
335 | GRN_INT64_SET(ctx, &n_records, n_records_raw); |
336 | break; |
337 | case GRN_DB_UINT8 : |
338 | case GRN_DB_UINT16 : |
339 | case GRN_DB_UINT32 : |
340 | case GRN_DB_UINT64 : |
341 | GRN_UINT64_SET(ctx, &n_records, n_records_raw); |
342 | break; |
343 | case GRN_DB_FLOAT : |
344 | GRN_FLOAT_SET(ctx, &n_records, n_records_raw); |
345 | break; |
346 | default : |
347 | break; |
348 | } |
349 | grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET); |
350 | } |
351 | } else { |
352 | while ((id = grn_window_next(ctx, window))) { |
353 | n_records_raw++; |
354 | } |
355 | |
356 | switch (output_column_range_id) { |
357 | case GRN_DB_INT8 : |
358 | case GRN_DB_INT16 : |
359 | case GRN_DB_INT32 : |
360 | case GRN_DB_INT64 : |
361 | GRN_INT64_SET(ctx, &n_records, n_records_raw); |
362 | break; |
363 | case GRN_DB_UINT8 : |
364 | case GRN_DB_UINT16 : |
365 | case GRN_DB_UINT32 : |
366 | case GRN_DB_UINT64 : |
367 | GRN_UINT64_SET(ctx, &n_records, n_records_raw); |
368 | break; |
369 | case GRN_DB_FLOAT : |
370 | GRN_FLOAT_SET(ctx, &n_records, n_records_raw); |
371 | break; |
372 | } |
373 | |
374 | grn_window_rewind(ctx, window); |
375 | while ((id = grn_window_next(ctx, window))) { |
376 | grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET); |
377 | } |
378 | } |
379 | |
380 | GRN_OBJ_FIN(ctx, &n_records); |
381 | |
382 | return GRN_SUCCESS; |
383 | } |
384 | |
385 | grn_rc |
386 | grn_db_init_builtin_window_functions(grn_ctx *ctx) |
387 | { |
388 | /* For backward compatibility. */ |
389 | grn_window_function_create(ctx, |
390 | "record_number" , -1, |
391 | window_record_number); |
392 | grn_window_function_create(ctx, |
393 | "window_record_number" , -1, |
394 | window_record_number); |
395 | |
396 | grn_window_function_create(ctx, |
397 | "window_sum" , -1, |
398 | window_sum); |
399 | |
400 | grn_window_function_create(ctx, |
401 | "window_count" , -1, |
402 | window_count); |
403 | |
404 | return GRN_SUCCESS; |
405 | } |
406 | |