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
22static grn_rc
23window_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
44static grn_rc
45window_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
272static grn_rc
273window_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
385grn_rc
386grn_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