Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include "sql_rank.h"
15 : #include "gdk_analytic.h"
16 :
17 : static void
18 3463 : unfix_inputs(int nargs, ...)
19 : {
20 3463 : va_list valist;
21 :
22 3463 : va_start(valist, nargs);
23 14677 : for (int i = 0; i < nargs; i++) {
24 11214 : BAT *b = va_arg(valist, BAT *);
25 17011 : BBPreclaim(b);
26 : }
27 3463 : va_end(valist);
28 3463 : }
29 :
30 : static void
31 3232 : finalize_output(bat *res, BAT *r, str msg)
32 : {
33 3232 : if (res && r && !msg) {
34 3075 : r->tsorted = BATcount(r) <= 1;
35 3075 : r->trevsorted = BATcount(r) <= 1;
36 3075 : r->tkey = BATcount(r) <= 1;
37 3075 : *res = r->batCacheid;
38 3075 : BBPkeepref(r);
39 157 : } else if (r)
40 12 : BBPreclaim(r);
41 3232 : }
42 :
43 : str
44 1269 : SQLdiff(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
45 : {
46 1269 : BAT *r = NULL, *b = NULL, *c = NULL;
47 1269 : bat *res = NULL;
48 1269 : str msg = MAL_SUCCEED;
49 :
50 1269 : (void)cntxt;
51 1269 : if (isaBatType(getArgType(mb, pci, 1))) {
52 1236 : gdk_return gdk_code = GDK_SUCCEED;
53 :
54 1236 : res = getArgReference_bat(stk, pci, 0);
55 1236 : if (pci->argc > 2) {
56 81 : if (isaBatType(getArgType(mb, pci, 2))) {
57 81 : if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
58 0 : msg = createException(SQL, "sql.diff", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
59 0 : goto bailout;
60 : }
61 81 : if (!(r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT))) {
62 0 : msg = createException(SQL, "sql.diff", SQLSTATE(HY013) MAL_MALLOC_FAIL);
63 0 : goto bailout;
64 : }
65 81 : c = b;
66 81 : if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 2))))) {
67 0 : msg = createException(SQL, "sql.diff", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
68 0 : goto bailout;
69 : }
70 81 : gdk_code = GDKanalyticaldiff(r, b, c, NULL, b->ttype);
71 : } else { /* the input is a constant, so the output is the previous sql.diff output */
72 0 : BBPretain(*res = *getArgReference_bat(stk, pci, 1));
73 0 : return MAL_SUCCEED;
74 : }
75 : } else {
76 1155 : if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
77 0 : msg = createException(SQL, "sql.diff", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
78 0 : goto bailout;
79 : }
80 1155 : if (!(r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT))) {
81 0 : msg = createException(SQL, "sql.diff", SQLSTATE(HY013) MAL_MALLOC_FAIL);
82 0 : goto bailout;
83 : }
84 1155 : gdk_code = GDKanalyticaldiff(r, b, NULL, NULL, b->ttype);
85 : }
86 1236 : if (gdk_code != GDK_SUCCEED)
87 0 : msg = createException(SQL, "sql.diff", GDK_EXCEPTION);
88 33 : } else if (pci->argc > 2 && isaBatType(getArgType(mb, pci, 2))) {
89 0 : bit *restrict prev = getArgReference_bit(stk, pci, 1);
90 :
91 0 : res = getArgReference_bat(stk, pci, 0);
92 0 : if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, 2))))) {
93 0 : msg = createException(SQL, "sql.diff", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
94 0 : goto bailout;
95 : }
96 0 : if (!(r = COLnew(b->hseqbase, TYPE_bit, BATcount(b), TRANSIENT))) {
97 0 : msg = createException(SQL, "sql.diff", SQLSTATE(HY013) MAL_MALLOC_FAIL);
98 0 : goto bailout;
99 : }
100 :
101 0 : if (GDKanalyticaldiff(r, b, NULL, prev, b->ttype) != GDK_SUCCEED)
102 0 : msg = createException(SQL, "sql.diff", GDK_EXCEPTION);
103 : } else {
104 33 : bit *res = getArgReference_bit(stk, pci, 0);
105 33 : *res = FALSE;
106 : }
107 :
108 1269 : bailout:
109 1269 : unfix_inputs(2, b, c);
110 1269 : finalize_output(res, r, msg);
111 1269 : return msg;
112 : }
113 :
114 : str
115 800 : SQLwindow_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
116 : {
117 800 : str msg = MAL_SUCCEED;
118 800 : bool preceding;
119 800 : oid second_half;
120 800 : int unit, bound, excl, part_offset = (pci->argc > 6);
121 800 : bat *res = NULL;
122 800 : BAT *r = NULL, *b = NULL, *p = NULL, *l = NULL;
123 :
124 800 : if ((pci->argc != 6 && pci->argc != 7) || getArgType(mb, pci, part_offset + 2) != TYPE_int ||
125 800 : getArgType(mb, pci, part_offset + 3) != TYPE_int || getArgType(mb, pci, part_offset + 4) != TYPE_int) {
126 0 : throw(SQL, "sql.window_bound", SQLSTATE(42000) "Invalid arguments");
127 : }
128 :
129 800 : unit = *getArgReference_int(stk, pci, part_offset + 2);
130 800 : bound = *getArgReference_int(stk, pci, part_offset + 3);
131 800 : excl = *getArgReference_int(stk, pci, part_offset + 4);
132 :
133 800 : assert(unit >= 0 && unit <= 3);
134 800 : assert(bound >= 0 && bound <= 5);
135 800 : assert(excl >= 0 && excl <= 2);
136 800 : preceding = (bound % 2 == 0);
137 800 : second_half = !(bound < 2 || bound == 4);
138 :
139 800 : (void)cntxt;
140 800 : if (isaBatType(getArgType(mb, pci, 1))) {
141 766 : int tp1, tp2 = getArgType(mb, pci, part_offset + 5);
142 766 : ptr limit = NULL;
143 766 : bool is_a_bat;
144 :
145 766 : res = getArgReference_bat(stk, pci, 0);
146 766 : if ((!(b = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 1))))) {
147 0 : msg = createException(SQL, "sql.window_bound", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 0 : goto bailout;
149 : }
150 766 : tp1 = b->ttype;
151 :
152 766 : if (excl != 0) {
153 0 : msg = createException(SQL, "sql.window_bound", SQLSTATE(42000) "Only EXCLUDE NO OTHERS exclusion is currently implemented");
154 0 : goto bailout;
155 : }
156 :
157 766 : is_a_bat = isaBatType(tp2);
158 766 : if (is_a_bat)
159 14 : tp2 = getBatType(tp2);
160 :
161 766 : if (!(r = COLnew(b->hseqbase, TYPE_oid, BATcount(b), TRANSIENT))) {
162 0 : msg = createException(SQL, "sql.window_bound", SQLSTATE(HY013) MAL_MALLOC_FAIL);
163 0 : goto bailout;
164 : }
165 766 : if (is_a_bat) { //SQL_CURRENT_ROW shall never fall in limit validation
166 14 : if ((!(l = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 5))))) {
167 0 : msg = createException(SQL, "sql.window_bound", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
168 0 : goto bailout;
169 : }
170 : } else {
171 752 : limit = getArgReference(stk, pci, part_offset + 5);
172 : }
173 766 : if (part_offset) {
174 375 : if ((!(p = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
175 0 : msg = createException(SQL, "sql.window_bound", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
176 0 : goto bailout;
177 : }
178 : }
179 :
180 : //On RANGE frame, when "CURRENT ROW" is not specified, the ranges are calculated with SQL intervals in mind
181 766 : if (GDKanalyticalwindowbounds(r, b, p, l, limit, tp1, tp2, unit, preceding, second_half) != GDK_SUCCEED)
182 8 : msg = createException(SQL, "sql.window_bound", GDK_EXCEPTION);
183 : } else {
184 34 : oid *res = getArgReference_oid(stk, pci, 0);
185 :
186 34 : *res = preceding ? 0 : 1;
187 : }
188 :
189 800 : bailout:
190 800 : unfix_inputs(3, b, p, l);
191 800 : finalize_output(res, r, msg);
192 800 : return msg;
193 : }
194 :
195 : str
196 64 : SQLrow_number(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
197 : {
198 64 : BAT *r = NULL, *b = NULL, *p = NULL;
199 64 : bat *res = NULL;
200 64 : str msg = MAL_SUCCEED;
201 :
202 64 : if (pci->argc != 4 ||
203 64 : (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
204 64 : (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
205 0 : throw(SQL, "sql.row_number", SQLSTATE(42000) "row_number(:any_1,:bit,:bit)");
206 : }
207 64 : (void)cntxt;
208 64 : if (isaBatType(getArgType(mb, pci, 1))) {
209 62 : BUN cnt;
210 62 : int j, *rp, *end;
211 62 : bit *np;
212 :
213 62 : res = getArgReference_bat(stk, pci, 0);
214 62 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
215 0 : msg = createException(SQL, "sql.row_number", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
216 0 : goto bailout;
217 : }
218 62 : if (!(r = COLnew(b->hseqbase, TYPE_int, BATcount(b), TRANSIENT))) {
219 0 : msg = createException(SQL, "sql.row_number", SQLSTATE(HY013) MAL_MALLOC_FAIL);
220 0 : goto bailout;
221 : }
222 62 : r->tsorted = r->trevsorted = r->tkey = BATcount(b) <= 1;
223 :
224 62 : cnt = BATcount(b);
225 62 : rp = (int*)Tloc(r, 0);
226 62 : if (isaBatType(getArgType(mb, pci, 2))) {
227 : /* order info not used */
228 22 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
229 0 : msg = createException(SQL, "sql.row_number", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
230 0 : goto bailout;
231 : }
232 22 : BATiter pi = bat_iterator(p);
233 22 : np = (bit*)pi.base;
234 22 : end = rp + cnt;
235 1248277 : for(j=1; rp<end; j++, np++, rp++) {
236 1248255 : if (*np)
237 29054 : j=1;
238 1248255 : *rp = j;
239 : }
240 22 : bat_iterator_end(&pi);
241 : } else { /* single value, ie no partitions, order info not used */
242 40 : int icnt = (int) cnt;
243 21067858 : for(j=1; j<=icnt; j++, rp++)
244 21067818 : *rp = j;
245 40 : r->tsorted = true;
246 40 : r->tkey = true;
247 : }
248 62 : BATsetcount(r, cnt);
249 62 : r->tnonil = true;
250 62 : r->tnil = false;
251 : } else {
252 2 : int *res = getArgReference_int(stk, pci, 0);
253 :
254 2 : *res = 1;
255 : }
256 :
257 64 : bailout:
258 64 : unfix_inputs(2, b, p);
259 64 : if (res && r && !msg) {
260 62 : r->tkey = BATcount(r) <= 1;
261 62 : *res = r->batCacheid;
262 62 : BBPkeepref(r);
263 2 : } else if (r)
264 0 : BBPreclaim(r);
265 : return msg;
266 : }
267 :
268 : str
269 114 : SQLrank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
270 : {
271 114 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
272 114 : bat *res = NULL;
273 114 : str msg = MAL_SUCCEED;
274 :
275 114 : if (pci->argc != 4 ||
276 114 : (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
277 114 : (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
278 0 : throw(SQL, "sql.rank", SQLSTATE(42000) "rank(:any_1,:bit,:bit)");
279 : }
280 114 : (void)cntxt;
281 114 : if (isaBatType(getArgType(mb, pci, 1))) {
282 104 : BUN cnt;
283 104 : int j, k, *rp, *end;
284 104 : bit *np, *no;
285 :
286 104 : res = getArgReference_bat(stk, pci, 0);
287 104 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
288 0 : msg = createException(SQL, "sql.rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
289 0 : goto bailout;
290 : }
291 104 : if (!(r = COLnew(b->hseqbase, TYPE_int, BATcount(b), TRANSIENT))) {
292 0 : msg = createException(SQL, "sql.rank", SQLSTATE(HY013) MAL_MALLOC_FAIL);
293 0 : goto bailout;
294 : }
295 104 : r->tsorted = r->trevsorted = r->tkey = BATcount(b) <= 1;
296 :
297 104 : cnt = BATcount(b);
298 104 : rp = (int*)Tloc(r, 0);
299 104 : end = rp + cnt;
300 104 : if (isaBatType(getArgType(mb, pci, 2))) {
301 36 : if (isaBatType(getArgType(mb, pci, 3))) {
302 25 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
303 0 : msg = createException(SQL, "sql.rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
304 0 : goto bailout;
305 : }
306 25 : BATiter pi = bat_iterator(p);
307 25 : BATiter oi = bat_iterator(o);
308 25 : np = (bit*)pi.base;
309 25 : no = (bit*)oi.base;
310 1109272 : for(j=1,k=1; rp<end; k++, np++, no++, rp++) {
311 1109247 : if (*np)
312 8239 : j=k=1;
313 1109247 : if (*no)
314 995593 : j=k;
315 1109247 : *rp = j;
316 : }
317 25 : bat_iterator_end(&pi);
318 25 : bat_iterator_end(&oi);
319 : } else { /* single value, ie no ordering */
320 11 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
321 0 : msg = createException(SQL, "sql.rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
322 0 : goto bailout;
323 : }
324 11 : BATiter pi = bat_iterator(p);
325 11 : np = (bit*)pi.base;
326 183 : for(j=1; rp<end; np++, rp++) {
327 161 : if (*np)
328 161 : j=1;
329 161 : *rp = j;
330 : }
331 11 : bat_iterator_end(&pi);
332 : }
333 : } else { /* single value, ie no partitions */
334 68 : if (isaBatType(getArgType(mb, pci, 3))) {
335 22 : if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
336 0 : msg = createException(SQL, "sql.rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
337 0 : goto bailout;
338 : }
339 22 : BATiter oi = bat_iterator(o);
340 22 : no = (bit*)oi.base;
341 16549 : for(j=1,k=1; rp<end; k++, no++, rp++) {
342 16527 : if (*no)
343 15413 : j=k;
344 16527 : *rp = j;
345 : }
346 22 : bat_iterator_end(&oi);
347 : } else { /* single value, ie no ordering */
348 598075 : for(; rp<end; rp++)
349 598029 : *rp = 1;
350 46 : r->tsorted = true;
351 46 : r->trevsorted = true;
352 : }
353 : }
354 104 : BATsetcount(r, cnt);
355 104 : r->tnonil = true;
356 104 : r->tnil = false;
357 : } else {
358 10 : int *res = getArgReference_int(stk, pci, 0);
359 :
360 10 : *res = 1;
361 : }
362 :
363 114 : bailout:
364 114 : unfix_inputs(3, b, p, o);
365 114 : if (res && r && !msg) {
366 104 : r->tkey = BATcount(r) <= 1;
367 104 : *res = r->batCacheid;
368 104 : BBPkeepref(r);
369 10 : } else if (r)
370 0 : BBPreclaim(r);
371 : return msg;
372 : }
373 :
374 : str
375 19 : SQLdense_rank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
376 : {
377 19 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
378 19 : bat *res = NULL;
379 19 : str msg = MAL_SUCCEED;
380 :
381 19 : if (pci->argc != 4 ||
382 19 : (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
383 19 : (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
384 0 : throw(SQL, "sql.dense_rank", SQLSTATE(42000) "dense_rank(:any_1,:bit,:bit)");
385 : }
386 19 : (void)cntxt;
387 19 : if (isaBatType(getArgType(mb, pci, 1))) {
388 18 : BUN cnt;
389 18 : int j, *rp, *end;
390 18 : bit *np, *no;
391 :
392 18 : res = getArgReference_bat(stk, pci, 0);
393 18 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
394 0 : msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
395 0 : goto bailout;
396 : }
397 18 : if (!(r = COLnew(b->hseqbase, TYPE_int, BATcount(b), TRANSIENT))) {
398 0 : msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY013) MAL_MALLOC_FAIL);
399 0 : goto bailout;
400 : }
401 18 : r->tsorted = r->trevsorted = r->tkey = BATcount(b) <= 1;
402 :
403 18 : cnt = BATcount(b);
404 18 : rp = (int*)Tloc(r, 0);
405 18 : end = rp + cnt;
406 18 : if (isaBatType(getArgType(mb, pci, 2))) {
407 11 : if (isaBatType(getArgType(mb, pci, 3))) {
408 6 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
409 0 : msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
410 0 : goto bailout;
411 : }
412 6 : BATiter pi = bat_iterator(p);
413 6 : BATiter oi = bat_iterator(o);
414 6 : np = (bit*)pi.base;
415 6 : no = (bit*)oi.base;
416 210 : for(j=1; rp<end; np++, no++, rp++) {
417 204 : if (*np)
418 : j=1;
419 189 : else if (*no)
420 12 : j++;
421 204 : *rp = j;
422 : }
423 6 : bat_iterator_end(&pi);
424 6 : bat_iterator_end(&oi);
425 : } else { /* single value, ie no ordering */
426 5 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
427 0 : msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
428 0 : goto bailout;
429 : }
430 5 : BATiter pi = bat_iterator(p);
431 5 : np = (bit*)pi.base;
432 110 : for(j=1; rp<end; np++, rp++) {
433 100 : if (*np)
434 100 : j=1;
435 100 : *rp = j;
436 : }
437 5 : bat_iterator_end(&pi);
438 : }
439 : } else { /* single value, ie no partitions */
440 7 : if (isaBatType(getArgType(mb, pci, 3))) {
441 5 : if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
442 0 : msg = createException(SQL, "sql.dense_rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
443 0 : goto bailout;
444 : }
445 5 : BATiter oi = bat_iterator(o);
446 5 : no = (bit*)oi.base;
447 62 : for(j=1; rp<end; no++, rp++) {
448 57 : if (*no)
449 32 : j++;
450 57 : *rp = j;
451 : }
452 5 : bat_iterator_end(&oi);
453 : } else { /* single value, ie no ordering */
454 39 : for(; rp<end; rp++)
455 37 : *rp = 1;
456 2 : r->tsorted = true;
457 2 : r->trevsorted = true;
458 : }
459 : }
460 18 : BATsetcount(r, cnt);
461 18 : r->tnonil = true;
462 18 : r->tnil = false;
463 : } else {
464 1 : int *res = getArgReference_int(stk, pci, 0);
465 :
466 1 : *res = 1;
467 : }
468 :
469 19 : bailout:
470 19 : unfix_inputs(3, b, p, o);
471 19 : if (res && r && !msg) {
472 18 : r->tkey = BATcount(r) <= 1;
473 18 : *res = r->batCacheid;
474 18 : BBPkeepref(r);
475 1 : } else if (r)
476 0 : BBPreclaim(r);
477 : return msg;
478 : }
479 :
480 : str
481 16 : SQLpercent_rank(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
482 : {
483 16 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
484 16 : bat *res = NULL;
485 16 : str msg = MAL_SUCCEED;
486 :
487 16 : if (pci->argc != 4 ||
488 16 : (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
489 16 : (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
490 0 : throw(SQL, "sql.percent_rank", SQLSTATE(42000) "percent_rank(:any_1,:bit,:bit)");
491 : }
492 16 : (void)cntxt;
493 16 : if (isaBatType(getArgType(mb, pci, 1))) {
494 16 : BUN ncnt, cnt;
495 16 : int j, k;
496 16 : dbl *rp, *end, cnt_cast;
497 16 : bit *np, *np2, *no, *no2;
498 :
499 16 : res = getArgReference_bat(stk, pci, 0);
500 16 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
501 0 : msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
502 0 : goto bailout;
503 : }
504 16 : if (!(r = COLnew(b->hseqbase, TYPE_dbl, BATcount(b), TRANSIENT))) {
505 0 : msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY013) MAL_MALLOC_FAIL);
506 0 : goto bailout;
507 : }
508 16 : r->tsorted = r->trevsorted = r->tkey = BATcount(b) <= 1;
509 :
510 16 : cnt = BATcount(b);
511 16 : rp = (dbl*)Tloc(r, 0);
512 16 : end = rp + cnt;
513 16 : if (isaBatType(getArgType(mb, pci, 2))) {
514 9 : if (isaBatType(getArgType(mb, pci, 3))) {
515 6 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
516 0 : msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
517 0 : goto bailout;
518 : }
519 6 : BATiter pi = bat_iterator(p);
520 6 : np = (bit*)pi.base;
521 6 : np2 = np + BATcount(p);
522 6 : BATiter oi = bat_iterator(o);
523 6 : no2 = no = (bit*)oi.base;
524 :
525 762 : for (; np<np2; np++, no++) {
526 756 : if (*np) {
527 38 : ncnt = no - no2;
528 38 : if (ncnt == 1) {
529 28 : for (; no2<no; no2++, rp++)
530 14 : *rp = 0.0;
531 : } else {
532 24 : cnt_cast = (dbl) (ncnt - 1);
533 24 : j = 0;
534 24 : k = 0;
535 757 : for (; no2<no; k++, no2++, rp++) {
536 733 : if (*no2)
537 352 : j=k;
538 733 : *rp = j / cnt_cast;
539 : }
540 : }
541 : }
542 : }
543 6 : bat_iterator_end(&pi);
544 6 : ncnt = no - no2;
545 6 : if (ncnt == 1) {
546 8 : for (; no2<no; no2++, rp++)
547 4 : *rp = 0.0;
548 : } else {
549 2 : cnt_cast = (dbl) (ncnt - 1);
550 2 : j = 0;
551 2 : k = 0;
552 7 : for (; no2<no; k++, no2++, rp++) {
553 5 : if (*no2)
554 2 : j=k;
555 5 : *rp = j / cnt_cast;
556 : }
557 : }
558 6 : bat_iterator_end(&oi);
559 : } else { /* single value, ie no ordering */
560 381 : for(; rp<end; rp++)
561 378 : *rp = 0.0;
562 3 : r->tsorted = true;
563 3 : r->trevsorted = true;
564 : }
565 : } else { /* single value, ie no partitions */
566 7 : if (isaBatType(getArgType(mb, pci, 3))) {
567 6 : if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
568 0 : msg = createException(SQL, "sql.percent_rank", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
569 0 : goto bailout;
570 : }
571 6 : BATiter oi = bat_iterator(o);
572 6 : no = (bit*)oi.base;
573 :
574 6 : if (cnt == 1) {
575 0 : for (; rp<end; rp++)
576 0 : *rp = 0.0;
577 0 : r->tsorted = true;
578 0 : r->trevsorted = true;
579 : } else {
580 6 : cnt_cast = (dbl) (cnt - 1);
581 762 : for(j=0,k=0; rp<end; k++, no++, rp++) {
582 756 : if (*no)
583 248 : j=k;
584 756 : *rp = j / cnt_cast;
585 : }
586 : }
587 6 : bat_iterator_end(&oi);
588 : } else { /* single value, ie no ordering */
589 11 : for(; rp<end; rp++)
590 10 : *rp = 0.0;
591 1 : r->tsorted = true;
592 1 : r->trevsorted = true;
593 : }
594 : }
595 16 : BATsetcount(r, cnt);
596 16 : r->tnonil = true;
597 16 : r->tnil = false;
598 : } else {
599 0 : dbl *res = getArgReference_dbl(stk, pci, 0);
600 :
601 0 : *res = 0.0;
602 : }
603 :
604 16 : bailout:
605 16 : unfix_inputs(3, b, p, o);
606 16 : if (res && r && !msg) {
607 16 : r->tkey = BATcount(r) <= 1;
608 16 : *res = r->batCacheid;
609 16 : BBPkeepref(r);
610 0 : } else if (r)
611 0 : BBPreclaim(r);
612 : return msg;
613 : }
614 :
615 : str
616 18 : SQLcume_dist(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
617 : {
618 18 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL;
619 18 : bat *res = NULL;
620 18 : str msg = MAL_SUCCEED;
621 :
622 18 : if (pci->argc != 4 ||
623 18 : (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
624 18 : (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit)){
625 0 : throw(SQL, "sql.cume_dist", SQLSTATE(42000) "cume_dist(:any_1,:bit,:bit)");
626 : }
627 18 : (void)cntxt;
628 18 : if (isaBatType(getArgType(mb, pci, 1))) {
629 18 : BUN ncnt, j = 0;
630 18 : bit *np, *no, *bo1, *bo2, *end;
631 18 : dbl *rb, *rp, cnt_cast, nres;
632 :
633 18 : res = getArgReference_bat(stk, pci, 0);
634 18 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
635 0 : msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
636 0 : goto bailout;
637 : }
638 18 : if (!(r = COLnew(b->hseqbase, TYPE_dbl, BATcount(b), TRANSIENT))) {
639 0 : msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY013) MAL_MALLOC_FAIL);
640 0 : goto bailout;
641 : }
642 18 : r->tsorted = r->trevsorted = r->tkey = BATcount(b) <= 1;
643 :
644 18 : rb = rp = (dbl*)Tloc(r, 0);
645 18 : if (isaBatType(getArgType(mb, pci, 2))) {
646 11 : if (isaBatType(getArgType(mb, pci, 3))) {
647 7 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, 2))) || !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
648 0 : msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
649 0 : goto bailout;
650 : }
651 7 : BATiter pi = bat_iterator(p);
652 7 : np = (bit*)pi.base;
653 7 : end = np + BATcount(p);
654 7 : BATiter oi = bat_iterator(o);
655 7 : bo1 = bo2 = no = (bit*)oi.base;
656 :
657 773 : for (; np<end; np++, no++) {
658 766 : if (*np) {
659 40 : ncnt = no - bo2;
660 40 : cnt_cast = (dbl) ncnt;
661 40 : j = 0;
662 792 : for (; bo2<no; bo2++) {
663 752 : if (*bo2) {
664 368 : j += (bo2 - bo1);
665 368 : nres = j / cnt_cast;
666 1028 : for (; bo1 < bo2; bo1++, rb++)
667 660 : *rb = nres;
668 : }
669 : }
670 132 : for (; bo1 < bo2; bo1++, rb++)
671 92 : *rb = 1.0;
672 : }
673 : }
674 7 : j = 0;
675 7 : ncnt = no - bo2;
676 7 : cnt_cast = (dbl) ncnt;
677 21 : for (; bo2<no; bo2++) {
678 14 : if (*bo2) {
679 10 : j += (bo2 - bo1);
680 10 : nres = j / cnt_cast;
681 14 : for (; bo1 < bo2; bo1++, rb++)
682 4 : *rb = nres;
683 : }
684 : }
685 17 : for (; bo1 < bo2; bo1++, rb++)
686 10 : *rb = 1.0;
687 7 : bat_iterator_end(&pi);
688 7 : bat_iterator_end(&oi);
689 : } else { /* single value, ie no ordering */
690 4 : rp = rb + BATcount(b);
691 392 : for (; rb<rp; rb++)
692 388 : *rb = 1.0;
693 4 : r->tsorted = true;
694 4 : r->trevsorted = true;
695 : }
696 : } else { /* single value, ie no partitions */
697 7 : if (isaBatType(getArgType(mb, pci, 3))) {
698 6 : if (!(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
699 0 : msg = createException(SQL, "sql.cume_dist", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
700 0 : goto bailout;
701 : }
702 6 : BATiter oi = bat_iterator(o);
703 6 : bo1 = bo2 = (bit*)oi.base;
704 6 : no = bo1 + BATcount(b);
705 6 : cnt_cast = (dbl) BATcount(b);
706 762 : for (; bo2<no; bo2++) {
707 756 : if (*bo2) {
708 248 : j += (bo2 - bo1);
709 248 : nres = j / cnt_cast;
710 973 : for (; bo1 < bo2; bo1++, rb++)
711 725 : *rb = nres;
712 : }
713 : }
714 37 : for (; bo1 < bo2; bo1++, rb++)
715 31 : *rb = 1.0;
716 6 : bat_iterator_end(&oi);
717 : } else { /* single value, ie no ordering */
718 1 : rp = rb + BATcount(b);
719 11 : for (; rb<rp; rb++)
720 10 : *rb = 1.0;
721 1 : r->tsorted = true;
722 1 : r->trevsorted = true;
723 : }
724 : }
725 18 : BATsetcount(r, BATcount(b));
726 18 : r->tnonil = true;
727 18 : r->tnil = false;
728 : } else {
729 0 : dbl *res = getArgReference_dbl(stk, pci, 0);
730 :
731 0 : *res = 1.0;
732 : }
733 :
734 18 : bailout:
735 18 : unfix_inputs(3, b, p, o);
736 18 : if (res && r && !msg) {
737 18 : r->tkey = BATcount(r) <= 1;
738 18 : *res = r->batCacheid;
739 18 : BBPkeepref(r);
740 0 : } else if (r)
741 0 : BBPreclaim(r);
742 : return msg;
743 : }
744 :
745 : #define NTILE_VALUE_SINGLE_IMP(TPE) \
746 : do { \
747 : TPE val = *(TPE*) VALget(ntile); \
748 : if (!is_##TPE##_nil(val) && val < 1) { \
749 : msg = createException(SQL, "sql.ntile", SQLSTATE(42000) "ntile must be greater than zero"); \
750 : goto bailout; \
751 : } \
752 : if (!is_##TPE##_nil(val)) \
753 : val = 1; \
754 : VALset(res, tp2, &val); \
755 : } while(0)
756 :
757 : str
758 64 : SQLntile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
759 : {
760 64 : BAT *r = NULL, *b = NULL, *p = NULL, *n = NULL;
761 64 : bat *res = NULL;
762 64 : str msg = MAL_SUCCEED;
763 :
764 64 : (void)cntxt;
765 64 : if (pci->argc != 5 || (getArgType(mb, pci, 3) != TYPE_bit && getBatType(getArgType(mb, pci, 3)) != TYPE_bit) ||
766 64 : (getArgType(mb, pci, 4) != TYPE_bit && getBatType(getArgType(mb, pci, 4)) != TYPE_bit)) {
767 0 : throw(SQL, "sql.ntile", SQLSTATE(42000) "ntile(:any_1,:number,:bit,:bit)");
768 : }
769 :
770 64 : if (isaBatType(getArgType(mb, pci, 1))) {
771 62 : int tp2 = 0;
772 62 : ptr ntile = NULL;
773 62 : res = getArgReference_bat(stk, pci, 0);
774 :
775 62 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
776 0 : msg = createException(SQL, "sql.ntile", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
777 0 : goto bailout;
778 : }
779 62 : if (isaBatType(getArgType(mb, pci, 2))) {
780 27 : tp2 = getBatType(getArgType(mb, pci, 2));
781 27 : if (!(n = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
782 0 : msg = createException(SQL, "sql.ntile", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
783 0 : goto bailout;
784 : }
785 : } else {
786 35 : tp2 = getArgType(mb, pci, 2);
787 35 : ntile = getArgReference(stk, pci, 2);
788 : }
789 62 : if (!(r = COLnew(b->hseqbase, tp2, BATcount(b), TRANSIENT))) {
790 0 : msg = createException(SQL, "sql.ntile", SQLSTATE(HY013) MAL_MALLOC_FAIL);
791 0 : goto bailout;
792 : }
793 62 : if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
794 0 : msg = createException(SQL, "sql.ntile", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
795 0 : goto bailout;
796 : }
797 62 : if ((p && BATcount(b) != BATcount(p)) || (n && BATcount(b) != BATcount(n))) {
798 0 : msg = createException(SQL, "sql.ntile", ILLEGAL_ARGUMENT " Requires bats of identical size");
799 0 : goto bailout;
800 : }
801 :
802 62 : if (GDKanalyticalntile(r, b, p, n, tp2, ntile) != GDK_SUCCEED)
803 0 : msg = createException(SQL, "sql.ntile", GDK_EXCEPTION);
804 : } else {
805 2 : ValRecord *res = &(stk)->stk[(pci)->argv[0]];
806 2 : ValRecord *ntile = &(stk)->stk[(pci)->argv[2]];
807 2 : int tp2 = getArgType(mb, pci, 2);
808 :
809 2 : switch (tp2) {
810 2 : case TYPE_bte:
811 2 : NTILE_VALUE_SINGLE_IMP(bte);
812 2 : break;
813 0 : case TYPE_sht:
814 0 : NTILE_VALUE_SINGLE_IMP(sht);
815 0 : break;
816 0 : case TYPE_int:
817 0 : NTILE_VALUE_SINGLE_IMP(int);
818 0 : break;
819 0 : case TYPE_lng:
820 0 : NTILE_VALUE_SINGLE_IMP(lng);
821 0 : break;
822 : #ifdef HAVE_HGE
823 0 : case TYPE_hge:
824 0 : NTILE_VALUE_SINGLE_IMP(hge);
825 0 : break;
826 : #endif
827 0 : default:
828 0 : msg = createException(SQL, "sql.ntile", SQLSTATE(42000) "ntile not available for %s", ATOMname(tp2));
829 : }
830 : }
831 :
832 64 : bailout:
833 64 : unfix_inputs(3, b, p, n);
834 64 : finalize_output(res, r, msg);
835 64 : return msg;
836 : }
837 :
838 : static str
839 368 : SQLanalytics_args(BAT **r, BAT **b, int *frame_type, BAT **p, BAT **o, BAT **s, BAT **e, Client cntxt, MalBlkPtr mb,
840 : MalStkPtr stk, InstrPtr pci, int rtype, const char *mod)
841 : {
842 368 : (void) cntxt;
843 368 : if (pci->argc != 7)
844 0 : throw(SQL, mod, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", mod);
845 :
846 368 : *frame_type = *getArgReference_int(stk, pci, 4);
847 368 : assert(*frame_type >= 0 && *frame_type <= 6);
848 :
849 368 : if (isaBatType(getArgType(mb, pci, 1)) && !(*b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))
850 0 : throw(SQL, mod, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
851 368 : if (*b && !(*r = COLnew((*b)->hseqbase, rtype ? rtype : (*b)->ttype, BATcount(*b), TRANSIENT)))
852 0 : throw(MAL, mod, SQLSTATE(HY013) MAL_MALLOC_FAIL);
853 368 : if (isaBatType(getArgType(mb, pci, 2)) && !(*p = BATdescriptor(*getArgReference_bat(stk, pci, 2))))
854 0 : throw(SQL, mod, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
855 368 : if ((*frame_type == 3 || *frame_type == 4) && isaBatType(getArgType(mb, pci, 3)) && !(*o = BATdescriptor(*getArgReference_bat(stk, pci, 3))))
856 0 : throw(SQL, mod, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
857 368 : if (*frame_type < 3 && isaBatType(getArgType(mb, pci, 5)) && !(*s = BATdescriptor(*getArgReference_bat(stk, pci, 5))))
858 0 : throw(SQL, mod, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
859 368 : if (*frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(*e = BATdescriptor(*getArgReference_bat(stk, pci, 6))))
860 0 : throw(SQL, mod, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
861 368 : if ((*s && BATcount(*b) != BATcount(*s)) || (*e && BATcount(*b) != BATcount(*e)) ||
862 368 : (*p && BATcount(*b) != BATcount(*p)) || (*o && BATcount(*b) != BATcount(*o)))
863 0 : throw(SQL, mod, ILLEGAL_ARGUMENT " Requires bats of identical size");
864 368 : if ((*p && (*p)->ttype != TYPE_bit) || (*o && (*o)->ttype != TYPE_bit) || (*s && (*s)->ttype != TYPE_oid) || (*e && (*e)->ttype != TYPE_oid))
865 0 : throw(SQL, mod, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
866 :
867 : return MAL_SUCCEED;
868 : }
869 :
870 : static str
871 175 : SQLanalytical_func(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
872 : gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int))
873 : {
874 175 : int tpe = getArgType(mb, pci, 1), frame_type;
875 175 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
876 175 : str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, 0, op);
877 175 : bat *res = NULL;
878 :
879 175 : if (msg)
880 0 : goto bailout;
881 175 : if (b) {
882 165 : res = getArgReference_bat(stk, pci, 0);
883 :
884 165 : if (func(r, p, o, b, s, e, getBatType(tpe), frame_type) != GDK_SUCCEED)
885 0 : msg = createException(SQL, op, GDK_EXCEPTION);
886 : } else {
887 10 : ValRecord *res = &(stk)->stk[(pci)->argv[0]];
888 10 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
889 :
890 10 : if (!VALcopy(res, in))
891 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
892 : }
893 :
894 10 : bailout:
895 175 : unfix_inputs(5, b, p, o, s, e);
896 175 : finalize_output(res, r, msg);
897 175 : return msg;
898 : }
899 :
900 : static str
901 67 : do_limit_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
902 : gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, int))
903 : {
904 67 : int tpe = getArgType(mb, pci, 1);
905 67 : BAT *r = NULL, *b = NULL, *s = NULL, *e = NULL; /* p and o are ignored for this one */
906 67 : bat *res = NULL;
907 67 : str msg = MAL_SUCCEED;
908 :
909 67 : (void) cntxt;
910 67 : if (pci->argc != 7)
911 0 : throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", op);
912 67 : tpe = getArgType(mb, pci, 1);
913 :
914 67 : if (isaBatType(tpe))
915 67 : tpe = getBatType(tpe);
916 67 : if (isaBatType(getArgType(mb, pci, 1))) {
917 67 : res = getArgReference_bat(stk, pci, 0);
918 :
919 67 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
920 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
921 0 : goto bailout;
922 : }
923 67 : if (!(r = COLnew(b->hseqbase, b->ttype, BATcount(b), TRANSIENT))) {
924 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
925 0 : goto bailout;
926 : }
927 67 : if (!(s = BATdescriptor(*getArgReference_bat(stk, pci, 5)))) {
928 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
929 0 : goto bailout;
930 : }
931 67 : if (!(e = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
932 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
933 0 : goto bailout;
934 : }
935 67 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e))) {
936 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
937 0 : goto bailout;
938 : }
939 67 : if ((s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
940 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
941 0 : goto bailout;
942 : }
943 :
944 67 : if (func(r, b, s, e, tpe) != GDK_SUCCEED)
945 0 : msg = createException(SQL, op, GDK_EXCEPTION);
946 : } else {
947 0 : ValRecord *res = &(stk)->stk[(pci)->argv[0]];
948 0 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
949 :
950 0 : if (!VALcopy(res, in))
951 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
952 : }
953 :
954 0 : bailout:
955 67 : unfix_inputs(3, b, s, e);
956 67 : finalize_output(res, r, msg);
957 67 : return msg;
958 : }
959 :
960 : str
961 36 : SQLfirst_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
962 : {
963 36 : return do_limit_value(cntxt, mb, stk, pci, "sql.first_value", GDKanalyticalfirst);
964 : }
965 :
966 : str
967 31 : SQLlast_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
968 : {
969 31 : return do_limit_value(cntxt, mb, stk, pci, "sql.last_value", GDKanalyticallast);
970 : }
971 :
972 : #define NTH_VALUE_SINGLE_IMP(TPE) \
973 : do { \
974 : TPE val = *(TPE*) VALget(nth); \
975 : if (!VALisnil(nth) && val < 1) \
976 : throw(SQL, "sql.nth_value", SQLSTATE(42000) "nth_value must be greater than zero"); \
977 : if (VALisnil(nth) || val > 1) { \
978 : ValRecord def = (ValRecord) {.vtype = TYPE_void,}; \
979 : if (!VALinit(&def, tp1, ATOMnilptr(tp1)) || !VALcopy(res, &def)) { \
980 : VALclear(&def); \
981 : throw(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
982 : } \
983 : VALclear(&def); \
984 : } else { \
985 : if (!VALcopy(res, in)) \
986 : throw(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
987 : } \
988 : } while(0)
989 :
990 : str
991 44 : SQLnth_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
992 : {
993 44 : BAT *r = NULL, *b = NULL, *l = NULL, *s = NULL, *e = NULL; /* p and o are ignored for this one */
994 44 : int tpe;
995 44 : bat *res = NULL;
996 44 : str msg = MAL_SUCCEED;
997 44 : bool is_a_bat;
998 :
999 44 : (void) cntxt;
1000 44 : if (pci->argc != 8)
1001 0 : throw(SQL, "sql.nth_value", ILLEGAL_ARGUMENT "sql.nth_value requires exactly 8 arguments");
1002 :
1003 44 : tpe = getArgType(mb, pci, 1);
1004 44 : is_a_bat = isaBatType(getArgType(mb, pci, 2));
1005 :
1006 44 : if (isaBatType(tpe)) {
1007 40 : lng *nth = NULL;
1008 40 : res = getArgReference_bat(stk, pci, 0);
1009 :
1010 40 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
1011 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1012 0 : goto bailout;
1013 : }
1014 40 : tpe = getBatType(tpe);
1015 40 : if (b && !(r = COLnew(b->hseqbase, tpe, BATcount(b), TRANSIENT))) {
1016 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1017 0 : goto bailout;
1018 : }
1019 40 : if (is_a_bat) {
1020 5 : if (!(l = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
1021 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1022 0 : goto bailout;
1023 : }
1024 : } else {
1025 35 : nth = getArgReference_lng(stk, pci, 2);
1026 : }
1027 40 : if (!(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
1028 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1029 0 : goto bailout;
1030 : }
1031 40 : if (!(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
1032 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1033 0 : goto bailout;
1034 : }
1035 40 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (l && BATcount(b) != BATcount(l))) {
1036 0 : msg = createException(SQL, "sql.nth_value", ILLEGAL_ARGUMENT " Requires bats of identical size");
1037 0 : goto bailout;
1038 : }
1039 40 : if ((s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
1040 0 : msg = createException(SQL, "sql.nth_value", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
1041 0 : goto bailout;
1042 : }
1043 :
1044 40 : if (GDKanalyticalnthvalue(r, b, s, e, l, nth, tpe) != GDK_SUCCEED)
1045 0 : msg = createException(SQL, "sql.nth_value", GDK_EXCEPTION);
1046 : } else {
1047 4 : ValRecord *res = &(stk)->stk[(pci)->argv[0]];
1048 4 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
1049 4 : lng nth = 0;
1050 :
1051 4 : if (getArgType(mb, pci, 2) != TYPE_lng) {
1052 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(42000) "nth_value offset not available for type %s", ATOMname(getArgType(mb, pci, 2)));
1053 0 : goto bailout;
1054 : }
1055 4 : nth = *getArgReference_lng(stk, pci, 2);
1056 4 : if (!is_lng_nil(nth) && nth < 1) {
1057 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(42000) "nth_value must be greater than zero");
1058 0 : goto bailout;
1059 : }
1060 4 : if (is_lng_nil(nth) || nth > 1) {
1061 0 : ValRecord def = (ValRecord) {.vtype = TYPE_void,};
1062 0 : if (!VALinit(&def, tpe, ATOMnilptr(tpe)) || !VALcopy(res, &def)) {
1063 0 : VALclear(&def);
1064 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1065 0 : goto bailout;
1066 : }
1067 0 : VALclear(&def);
1068 : } else {
1069 4 : if (!VALcopy(res, in))
1070 0 : msg = createException(SQL, "sql.nth_value", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1071 : }
1072 : }
1073 :
1074 4 : bailout:
1075 44 : unfix_inputs(4, b, l, s, e);
1076 44 : finalize_output(res, r, msg);
1077 44 : return msg;
1078 : }
1079 :
1080 : #define CHECK_L_VALUE(TPE) \
1081 : do { \
1082 : TPE rval; \
1083 : if (tp2_is_a_bat) { \
1084 : if (!(l = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) { \
1085 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); \
1086 : goto bailout; \
1087 : } \
1088 : MT_lock_set(&l->theaplock); \
1089 : rval = ((TPE*)Tloc(l, 0))[0]; \
1090 : MT_lock_unset(&l->theaplock); \
1091 : } else { \
1092 : rval = *getArgReference_##TPE(stk, pci, 2); \
1093 : } \
1094 : if (!is_##TPE##_nil(rval) && rval < 0) { \
1095 : gdk_call = dual; \
1096 : rval *= -1; \
1097 : } \
1098 : l_value = is_##TPE##_nil(rval) ? BUN_NONE : (BUN)rval; \
1099 : } while(0)
1100 :
1101 : static str
1102 69 : do_lead_lag(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op, const char* desc,
1103 : gdk_return (*func)(BAT *, BAT *, BAT *, BUN, const void* restrict, int),
1104 : gdk_return (*dual)(BAT *, BAT *, BAT *, BUN, const void* restrict, int))
1105 : {
1106 69 : int tp1, tp2, tp3, base = 2;
1107 69 : BUN l_value = 1;
1108 69 : void *restrict default_value;
1109 69 : gdk_return (*gdk_call)(BAT *, BAT *, BAT *, BUN, const void* restrict, int) = func;
1110 69 : BAT *b = NULL, *l = NULL, *d = NULL, *p = NULL, *r = NULL;
1111 69 : bool tp2_is_a_bat, free_default_value = false;
1112 69 : str msg = MAL_SUCCEED;
1113 69 : bat *res = NULL;
1114 :
1115 69 : (void)cntxt;
1116 69 : if (pci->argc < 4 || pci->argc > 6)
1117 0 : throw(SQL, op, SQLSTATE(42000) "%s called with invalid number of arguments", desc);
1118 :
1119 69 : tp1 = getArgType(mb, pci, 1);
1120 :
1121 69 : if (pci->argc > 4) { //contains (lag or lead) value;
1122 28 : tp2 = getArgType(mb, pci, 2);
1123 28 : tp2_is_a_bat = isaBatType(tp2);
1124 28 : if (tp2_is_a_bat)
1125 6 : tp2 = getBatType(tp2);
1126 :
1127 28 : switch (tp2) {
1128 28 : case TYPE_bte:
1129 28 : CHECK_L_VALUE(bte);
1130 : break;
1131 0 : case TYPE_sht:
1132 0 : CHECK_L_VALUE(sht);
1133 : break;
1134 0 : case TYPE_int:
1135 0 : CHECK_L_VALUE(int);
1136 : break;
1137 0 : case TYPE_lng:
1138 0 : CHECK_L_VALUE(lng);
1139 : break;
1140 : #ifdef HAVE_HGE
1141 0 : case TYPE_hge:
1142 0 : CHECK_L_VALUE(hge);
1143 : break;
1144 : #endif
1145 0 : default:
1146 0 : throw(SQL, op, SQLSTATE(42000) "%s value not available for %s", desc, ATOMname(tp2));
1147 : }
1148 : base = 3;
1149 : }
1150 :
1151 69 : if (pci->argc > 5) { //contains default value;
1152 9 : tp3 = getArgType(mb, pci, 3);
1153 9 : if (isaBatType(tp3)) {
1154 3 : BATiter bpi;
1155 3 : size_t default_size;
1156 3 : const void *p;
1157 :
1158 3 : tp3 = getBatType(tp3);
1159 3 : if (!(d = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
1160 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1161 0 : goto bailout;
1162 : }
1163 3 : bpi = bat_iterator(d);
1164 3 : p = BUNtail(bpi, 0);
1165 3 : default_size = ATOMlen(tp3, p);
1166 3 : default_value = GDKmalloc(default_size);
1167 3 : if (default_value)
1168 3 : memcpy(default_value, p, default_size);
1169 3 : bat_iterator_end(&bpi);
1170 3 : if (!default_value) {
1171 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1172 0 : goto bailout;
1173 : }
1174 3 : free_default_value = true;
1175 : } else {
1176 6 : ValRecord *in = &(stk)->stk[(pci)->argv[3]];
1177 6 : default_value = VALget(in);
1178 : }
1179 : base = 4;
1180 : } else {
1181 60 : int tpe = tp1;
1182 60 : if (isaBatType(tpe))
1183 54 : tpe = getBatType(tp1);
1184 60 : default_value = (void *)ATOMnilptr(tpe);
1185 : }
1186 :
1187 69 : assert(default_value); //default value must be set
1188 :
1189 69 : if (isaBatType(tp1)) {
1190 59 : res = getArgReference_bat(stk, pci, 0);
1191 59 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
1192 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1193 0 : goto bailout;
1194 : }
1195 :
1196 59 : tp1 = getBatType(tp1);
1197 59 : if (!(r = COLnew(b->hseqbase, tp1, BATcount(b), TRANSIENT))) {
1198 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1199 0 : goto bailout;
1200 : }
1201 59 : if (isaBatType(getArgType(mb, pci, base))) {
1202 36 : if (!(p = BATdescriptor(*getArgReference_bat(stk, pci, base)))) {
1203 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1204 0 : goto bailout;
1205 : }
1206 : }
1207 59 : if ((p && BATcount(b) != BATcount(p)) || (l && BATcount(b) != BATcount(l)) || (d && BATcount(b) != BATcount(d))) {
1208 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
1209 0 : goto bailout;
1210 : }
1211 :
1212 59 : if (gdk_call(r, b, p, l_value, default_value, tp1) != GDK_SUCCEED)
1213 0 : msg = createException(SQL, op, GDK_EXCEPTION);
1214 : } else {
1215 10 : ValRecord *res = &(stk)->stk[(pci)->argv[0]];
1216 10 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
1217 :
1218 10 : if (l_value == 0) {
1219 4 : if (!VALcopy(res, in))
1220 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1221 : } else {
1222 6 : ValRecord def = (ValRecord) {.vtype = TYPE_void,};
1223 :
1224 6 : if (!VALinit(&def, tp1, default_value) || !VALcopy(res, &def))
1225 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1226 6 : VALclear(&def);
1227 : }
1228 : }
1229 :
1230 69 : bailout:
1231 69 : if (free_default_value)
1232 3 : GDKfree(default_value);
1233 69 : unfix_inputs(4, b, p, l, d);
1234 69 : finalize_output(res, r, msg);
1235 69 : return msg;
1236 : }
1237 :
1238 : str
1239 35 : SQLlag(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1240 : {
1241 35 : return do_lead_lag(cntxt, mb, stk, pci, "sql.lag", "lag", GDKanalyticallag, GDKanalyticallead);
1242 : }
1243 :
1244 : str
1245 34 : SQLlead(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1246 : {
1247 34 : return do_lead_lag(cntxt, mb, stk, pci, "sql.lead", "lead", GDKanalyticallead, GDKanalyticallag);
1248 : }
1249 :
1250 : str
1251 73 : SQLmin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1252 : {
1253 73 : return SQLanalytical_func(cntxt, mb, stk, pci, "sql.min", GDKanalyticalmin);
1254 : }
1255 :
1256 : str
1257 102 : SQLmax(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1258 : {
1259 102 : return SQLanalytical_func(cntxt, mb, stk, pci, "sql.max", GDKanalyticalmax);
1260 : }
1261 :
1262 : str
1263 587 : SQLbasecount(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1264 : {
1265 587 : lng *res = getArgReference_lng(stk, pci, 0);
1266 587 : str sname = *getArgReference_str(stk, pci, 1);
1267 587 : str tname = *getArgReference_str(stk, pci, 2);
1268 587 : mvc *m = NULL;
1269 587 : str msg;
1270 587 : sql_schema *s = NULL;
1271 587 : sql_table *t = NULL;
1272 587 : sql_column *c = NULL;
1273 :
1274 587 : if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL)
1275 : return msg;
1276 587 : if ((msg = checkSQLContext(cntxt)) != NULL)
1277 : return msg;
1278 587 : if (!(s = mvc_bind_schema(m, sname)))
1279 0 : throw(SQL, "sql.count", SQLSTATE(3F000) "Schema missing %s", sname);
1280 587 : if (!(t = mvc_bind_table(m, s, tname)))
1281 0 : throw(SQL, "sql.count", SQLSTATE(42S02) "Table missing %s.%s",sname,tname);
1282 587 : if (!isTable(t))
1283 0 : throw(SQL, "sql.count", SQLSTATE(42000) "%s '%s' is not persistent",
1284 0 : TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->base.name);
1285 587 : if (!ol_first_node(t->columns))
1286 0 : throw(SQL, "sql.count", SQLSTATE(42S22) "Column missing %s.%s",sname,tname);
1287 587 : c = ol_first_node(t->columns)->data;
1288 587 : sqlstore *store = m->session->tr->store;
1289 :
1290 587 : *res = store->storage_api.count_col(m->session->tr, c, 10);
1291 587 : return msg;
1292 : }
1293 :
1294 : str
1295 174 : SQLcount(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1296 : {
1297 174 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1298 174 : int tpe, frame_type;
1299 174 : bit ignore_nils;
1300 174 : bat *res = NULL;
1301 174 : str msg = MAL_SUCCEED;
1302 :
1303 174 : (void) cntxt;
1304 174 : if (pci->argc != 8)
1305 0 : throw(SQL, "sql.count", ILLEGAL_ARGUMENT "sql.count requires exactly 8 arguments");
1306 174 : tpe = getArgType(mb, pci, 1);
1307 174 : ignore_nils = *getArgReference_bit(stk, pci, 2);
1308 174 : frame_type = *getArgReference_int(stk, pci, 5);
1309 174 : assert(frame_type >= 0 && frame_type <= 6);
1310 :
1311 174 : if (isaBatType(tpe))
1312 159 : tpe = getBatType(tpe);
1313 174 : if (isaBatType(getArgType(mb, pci, 1)) && (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
1314 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1315 0 : goto bailout;
1316 : }
1317 159 : if (b && !(r = COLnew(b->hseqbase, TYPE_lng, BATcount(b), TRANSIENT))) {
1318 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1319 0 : goto bailout;
1320 : }
1321 174 : if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
1322 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1323 0 : goto bailout;
1324 : }
1325 174 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 4)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 4)))) {
1326 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1327 0 : goto bailout;
1328 : }
1329 174 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
1330 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1331 0 : goto bailout;
1332 : }
1333 81 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 7)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
1334 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1335 0 : goto bailout;
1336 : }
1337 174 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o))) {
1338 0 : msg = createException(SQL, "sql.count", ILLEGAL_ARGUMENT " Requires bats of identical size");
1339 0 : goto bailout;
1340 : }
1341 174 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
1342 0 : msg = createException(SQL, "sql.count", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
1343 0 : goto bailout;
1344 : }
1345 :
1346 174 : if (b) {
1347 159 : res = getArgReference_bat(stk, pci, 0);
1348 :
1349 159 : if (GDKanalyticalcount(r, p, o, b, s, e, ignore_nils, tpe, frame_type) != GDK_SUCCEED)
1350 0 : msg = createException(SQL, "sql.count", GDK_EXCEPTION);
1351 : } else {
1352 15 : lng *res = getArgReference_lng(stk, pci, 0);
1353 15 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
1354 :
1355 30 : *res = (VALisnil(in) && ignore_nils) ? 0 : 1;
1356 : }
1357 :
1358 174 : bailout:
1359 174 : unfix_inputs(5, b, p, o, s, e);
1360 174 : finalize_output(res, r, msg);
1361 174 : return msg;
1362 : }
1363 :
1364 : static str
1365 170 : do_analytical_sumprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
1366 : gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int, int))
1367 : {
1368 170 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1369 170 : int tp1, tp2, frame_type;
1370 170 : str msg = MAL_SUCCEED;
1371 170 : bat *res = NULL;
1372 :
1373 170 : (void) cntxt;
1374 170 : if (pci->argc != 7)
1375 0 : throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", op);
1376 170 : tp2 = getArgType(mb, pci, 0);
1377 170 : tp1 = getArgType(mb, pci, 1);
1378 170 : frame_type = *getArgReference_int(stk, pci, 4);
1379 170 : assert(frame_type >= 0 && frame_type <= 6);
1380 :
1381 170 : if (isaBatType(tp1)) {
1382 161 : tp1 = getBatType(tp1);
1383 161 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
1384 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1385 0 : goto bailout;
1386 : }
1387 : }
1388 170 : if (isaBatType(tp2))
1389 161 : tp2 = getBatType(tp2);
1390 :
1391 170 : if (b) {
1392 161 : res = getArgReference_bat(stk, pci, 0);
1393 161 : if (!(r = COLnew(b->hseqbase, tp2, BATcount(b), TRANSIENT))) {
1394 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1395 0 : goto bailout;
1396 : }
1397 161 : if (isaBatType(getArgType(mb, pci, 2)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
1398 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1399 0 : goto bailout;
1400 : }
1401 161 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 3)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
1402 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1403 0 : goto bailout;
1404 : }
1405 161 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 5)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 5)))) {
1406 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1407 0 : goto bailout;
1408 : }
1409 59 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
1410 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1411 0 : goto bailout;
1412 : }
1413 161 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o))) {
1414 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
1415 0 : goto bailout;
1416 : }
1417 161 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
1418 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
1419 0 : goto bailout;
1420 : }
1421 :
1422 161 : if (func(r, p, o, b, s, e, tp1, tp2, frame_type) != GDK_SUCCEED)
1423 0 : msg = createException(SQL, op, GDK_EXCEPTION);
1424 : } else {
1425 : /* the pointers here will always point from bte to dbl, so no strings are handled here */
1426 9 : ptr res = getArgReference(stk, pci, 0);
1427 9 : ptr in = getArgReference(stk, pci, 1);
1428 9 : int scale = 0;
1429 :
1430 9 : switch (tp2) {
1431 0 : case TYPE_bte:{
1432 0 : switch (tp1) {
1433 0 : case TYPE_bte:
1434 0 : msg = bte_dec2_bte((bte*)res, &scale, (bte*)in);
1435 0 : break;
1436 0 : default:
1437 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1438 : }
1439 : break;
1440 : }
1441 0 : case TYPE_sht:{
1442 0 : switch (tp1) {
1443 0 : case TYPE_bte:
1444 0 : msg = bte_dec2_sht((sht*)res, &scale, (bte*)in);
1445 0 : break;
1446 0 : case TYPE_sht:
1447 0 : msg = sht_dec2_sht((sht*)res, &scale, (sht*)in);
1448 0 : break;
1449 0 : default:
1450 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1451 : }
1452 : break;
1453 : }
1454 0 : case TYPE_int:{
1455 0 : switch (tp1) {
1456 0 : case TYPE_bte:
1457 0 : msg = bte_dec2_int((int*)res, &scale, (bte*)in);
1458 0 : break;
1459 0 : case TYPE_sht:
1460 0 : msg = sht_dec2_int((int*)res, &scale, (sht*)in);
1461 0 : break;
1462 0 : case TYPE_int:
1463 0 : msg = int_dec2_int((int*)res, &scale, (int*)in);
1464 0 : break;
1465 0 : default:
1466 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1467 : }
1468 : break;
1469 : }
1470 0 : case TYPE_lng:{
1471 0 : switch (tp1) {
1472 0 : case TYPE_bte:
1473 0 : msg = bte_dec2_lng((lng*)res, &scale, (bte*)in);
1474 0 : break;
1475 0 : case TYPE_sht:
1476 0 : msg = sht_dec2_lng((lng*)res, &scale, (sht*)in);
1477 0 : break;
1478 0 : case TYPE_int:
1479 0 : msg = int_dec2_lng((lng*)res, &scale, (int*)in);
1480 0 : break;
1481 0 : case TYPE_lng:
1482 0 : msg = lng_dec2_lng((lng*)res, &scale, (lng*)in);
1483 0 : break;
1484 0 : default:
1485 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1486 : }
1487 : break;
1488 : }
1489 : #ifdef HAVE_HGE
1490 6 : case TYPE_hge:{
1491 6 : switch (tp1) {
1492 3 : case TYPE_bte:
1493 3 : msg = bte_dec2_hge((hge*)res, &scale, (bte*)in);
1494 3 : break;
1495 0 : case TYPE_sht:
1496 0 : msg = sht_dec2_hge((hge*)res, &scale, (sht*)in);
1497 0 : break;
1498 3 : case TYPE_int:
1499 3 : msg = int_dec2_hge((hge*)res, &scale, (int*)in);
1500 3 : break;
1501 0 : case TYPE_lng:
1502 0 : msg = lng_dec2_hge((hge*)res, &scale, (lng*)in);
1503 0 : break;
1504 0 : case TYPE_hge:
1505 0 : msg = hge_dec2_hge((hge*)res, &scale, (hge*)in);
1506 0 : break;
1507 0 : default:
1508 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1509 : }
1510 : break;
1511 : }
1512 : #endif
1513 0 : case TYPE_flt:{
1514 0 : switch (tp1) {
1515 0 : case TYPE_flt:
1516 0 : *(flt*)res = *((flt*)in);
1517 0 : break;
1518 0 : default:
1519 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1520 : }
1521 : break;
1522 : }
1523 3 : case TYPE_dbl:{
1524 3 : switch (tp1) {
1525 0 : case TYPE_flt: {
1526 0 : flt fp = *((flt*)in);
1527 0 : *(dbl*)res = is_flt_nil(fp) ? dbl_nil : (dbl) fp;
1528 0 : } break;
1529 3 : case TYPE_dbl:
1530 3 : *(dbl*)res = *((dbl*)in);
1531 3 : break;
1532 0 : default:
1533 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1534 : }
1535 : break;
1536 : }
1537 0 : default:
1538 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1539 : }
1540 : }
1541 :
1542 170 : bailout:
1543 170 : unfix_inputs(5, b, p, o, s, e);
1544 170 : finalize_output(res, r, msg);
1545 170 : return msg;
1546 : }
1547 :
1548 : str
1549 139 : SQLsum(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1550 : {
1551 139 : return do_analytical_sumprod(cntxt, mb, stk, pci, "sql.sum", GDKanalyticalsum);
1552 : }
1553 :
1554 : str
1555 31 : SQLprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1556 : {
1557 31 : return do_analytical_sumprod(cntxt, mb, stk, pci, "sql.prod", GDKanalyticalprod);
1558 : }
1559 :
1560 : str
1561 88 : SQLavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1562 : {
1563 88 : int tpe = getArgType(mb, pci, 1), frame_type = 0;
1564 88 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1565 88 : str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, TYPE_dbl, "sql.avg");
1566 88 : bat *res = NULL;
1567 :
1568 88 : if (msg)
1569 0 : goto bailout;
1570 88 : if (isaBatType(tpe))
1571 72 : tpe = getBatType(tpe);
1572 :
1573 88 : if (b) {
1574 72 : res = getArgReference_bat(stk, pci, 0);
1575 :
1576 72 : if (GDKanalyticalavg(r, p, o, b, s, e, tpe, frame_type) != GDK_SUCCEED)
1577 0 : msg = createException(SQL, "sql.avg", GDK_EXCEPTION);
1578 : } else {
1579 : /* the pointers here will always point from bte to dbl, so no strings are handled here */
1580 16 : ptr res = getArgReference(stk, pci, 0);
1581 16 : ptr in = getArgReference(stk, pci, 1);
1582 16 : int scale = 0;
1583 :
1584 16 : switch (tpe) {
1585 3 : case TYPE_bte:
1586 3 : msg = bte_dec2_dbl((dbl*)res, &scale, (bte*)in);
1587 3 : break;
1588 2 : case TYPE_sht:
1589 2 : msg = sht_dec2_dbl((dbl*)res, &scale, (sht*)in);
1590 2 : break;
1591 8 : case TYPE_int:
1592 8 : msg = int_dec2_dbl((dbl*)res, &scale, (int*)in);
1593 8 : break;
1594 0 : case TYPE_lng:
1595 0 : msg = lng_dec2_dbl((dbl*)res, &scale, (lng*)in);
1596 0 : break;
1597 : #ifdef HAVE_HGE
1598 0 : case TYPE_hge:
1599 0 : msg = hge_dec2_dbl((dbl*)res, &scale, (hge*)in);
1600 0 : break;
1601 : #endif
1602 0 : case TYPE_flt: {
1603 0 : flt fp = *((flt*)in);
1604 0 : *(dbl*)res = is_flt_nil(fp) ? dbl_nil : (dbl) fp;
1605 0 : } break;
1606 3 : case TYPE_dbl:
1607 3 : *(dbl*)res = *((dbl*)in);
1608 3 : break;
1609 0 : default:
1610 0 : msg = createException(SQL, "sql.avg", SQLSTATE(42000) "sql.avg not available for %s to dbl", ATOMname(tpe));
1611 : }
1612 : }
1613 :
1614 88 : bailout:
1615 88 : unfix_inputs(5, b, p, o, s, e);
1616 88 : finalize_output(res, r, msg);
1617 88 : return msg;
1618 : }
1619 :
1620 : str
1621 48 : SQLavginteger(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1622 : {
1623 48 : int tpe = getArgType(mb, pci, 1), frame_type = 0;
1624 48 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1625 48 : str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, 0, "sql.avg");
1626 48 : bat *res = NULL;
1627 :
1628 48 : if (msg)
1629 0 : goto bailout;
1630 48 : if (isaBatType(tpe))
1631 48 : tpe = getBatType(tpe);
1632 :
1633 48 : if (b) {
1634 48 : res = getArgReference_bat(stk, pci, 0);
1635 :
1636 48 : if (GDKanalyticalavginteger(r, p, o, b, s, e, tpe, frame_type) != GDK_SUCCEED)
1637 0 : msg = createException(SQL, "sql.avg", GDK_EXCEPTION);
1638 : } else {
1639 0 : ValRecord *res = &(stk)->stk[(pci)->argv[0]];
1640 0 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
1641 :
1642 0 : switch (tpe) {
1643 0 : case TYPE_bte:
1644 : case TYPE_sht:
1645 : case TYPE_int:
1646 : case TYPE_lng:
1647 : #ifdef HAVE_HGE
1648 : case TYPE_hge:
1649 : #endif
1650 0 : if (!VALcopy(res, in))
1651 0 : msg = createException(SQL, "sql.avg", SQLSTATE(HY013) MAL_MALLOC_FAIL); /* malloc failure should never happen, but let it be here */
1652 : break;
1653 0 : default:
1654 0 : msg = createException(SQL, "sql.avg", SQLSTATE(42000) "sql.avg not available for %s to %s", ATOMname(tpe), ATOMname(tpe));
1655 : }
1656 : }
1657 :
1658 48 : bailout:
1659 48 : unfix_inputs(5, b, p, o, s, e);
1660 48 : finalize_output(res, r, msg);
1661 48 : return msg;
1662 : }
1663 :
1664 : static str
1665 57 : do_stddev_and_variance(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
1666 : gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int))
1667 : {
1668 57 : int tpe = getArgType(mb, pci, 1), frame_type = 0;
1669 57 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1670 57 : str msg = SQLanalytics_args(&r, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, TYPE_dbl, op);
1671 57 : bat *res = NULL;
1672 :
1673 57 : if (msg)
1674 0 : goto bailout;
1675 57 : if (isaBatType(tpe))
1676 56 : tpe = getBatType(tpe);
1677 :
1678 57 : if (b) {
1679 56 : res = getArgReference_bat(stk, pci, 0);
1680 :
1681 56 : if (func(r, p, o, b, s, e, tpe, frame_type) != GDK_SUCCEED)
1682 2 : msg = createException(SQL, op, GDK_EXCEPTION);
1683 : } else {
1684 1 : dbl *res = getArgReference_dbl(stk, pci, 0);
1685 1 : switch (tpe) {
1686 1 : case TYPE_bte:
1687 : case TYPE_sht:
1688 : case TYPE_int:
1689 : case TYPE_lng:
1690 : #ifdef HAVE_HGE
1691 : case TYPE_hge:
1692 : #endif
1693 : case TYPE_flt:
1694 : case TYPE_dbl:
1695 1 : *res = dbl_nil;
1696 1 : break;
1697 0 : default:
1698 0 : msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tpe));
1699 : }
1700 : }
1701 :
1702 57 : bailout:
1703 57 : unfix_inputs(5, b, p, o, s, e);
1704 57 : finalize_output(res, r, msg);
1705 57 : return msg;
1706 : }
1707 :
1708 : str
1709 17 : SQLstddev_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1710 : {
1711 17 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.stdev", GDKanalytical_stddev_samp);
1712 : }
1713 :
1714 : str
1715 12 : SQLstddev_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1716 : {
1717 12 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.stdevp", GDKanalytical_stddev_pop);
1718 : }
1719 :
1720 : str
1721 12 : SQLvar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1722 : {
1723 12 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.variance", GDKanalytical_variance_samp);
1724 : }
1725 :
1726 : str
1727 16 : SQLvar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1728 : {
1729 16 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.variancep", GDKanalytical_variance_pop);
1730 : }
1731 :
1732 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_UNBOUNDED_TILL_CURRENT_ROW(TPE) \
1733 : do { \
1734 : TPE *restrict bp = (TPE*)di.base; \
1735 : for (; k < i;) { \
1736 : j = k; \
1737 : do { \
1738 : n += !is_##TPE##_nil(bp[k]); \
1739 : k++; \
1740 : } while (k < i && !opp[k]); \
1741 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1742 : rr = val; \
1743 : } else { \
1744 : rr = dbl_nil; \
1745 : has_nils = true; \
1746 : } \
1747 : for (; j < k; j++) \
1748 : rb[j] = rr; \
1749 : } \
1750 : n = 0; \
1751 : k = i; \
1752 : } while (0)
1753 :
1754 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_CURRENT_ROW_TILL_UNBOUNDED(TPE) \
1755 : do { \
1756 : TPE *restrict bp = (TPE*)di.base; \
1757 : l = i - 1; \
1758 : for (j = l; ; j--) { \
1759 : n += !is_##TPE##_nil(bp[j]); \
1760 : if (opp[j] || j == k) { \
1761 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1762 : rr = val; \
1763 : } else { \
1764 : rr = dbl_nil; \
1765 : has_nils = true; \
1766 : } \
1767 : for (; ; l--) { \
1768 : rb[l] = rr; \
1769 : if (l == j) \
1770 : break; \
1771 : } \
1772 : if (j == k) \
1773 : break; \
1774 : l = j - 1; \
1775 : } \
1776 : } \
1777 : n = 0; \
1778 : k = i; \
1779 : } while (0)
1780 :
1781 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_ALL_ROWS(TPE) \
1782 : do { \
1783 : TPE *restrict bp = (TPE*)di.base; \
1784 : for (; j < i; j++) \
1785 : n += !is_##TPE##_nil(bp[j]); \
1786 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1787 : rr = val; \
1788 : } else { \
1789 : rr = dbl_nil; \
1790 : has_nils = true; \
1791 : } \
1792 : for (; k < i; k++) \
1793 : rb[k] = rr; \
1794 : n = 0; \
1795 : } while (0)
1796 :
1797 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_CURRENT_ROW(TPE) \
1798 : do { \
1799 : TPE *restrict bp = (TPE*)di.base; \
1800 : for (; k < i; k++) { \
1801 : n += !is_##TPE##_nil(bp[k]); \
1802 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1803 : rb[k] = val; \
1804 : } else { \
1805 : rb[k] = dbl_nil; \
1806 : has_nils = true; \
1807 : } \
1808 : n = 0; \
1809 : } \
1810 : } while (0)
1811 :
1812 : #define INIT_AGGREGATE_COUNT(TPE, NOTHING1, NOTHING2) \
1813 : do { \
1814 : computed = 0; \
1815 : } while (0)
1816 : #define COMPUTE_LEVEL0_COUNT_FIXED(X, TPE, NOTHING1, NOTHING2) \
1817 : do { \
1818 : computed = !is_##TPE##_nil(bp[j + X]); \
1819 : } while (0)
1820 : #define COMPUTE_LEVELN_COUNT(VAL, NOTHING1, NOTHING2, NOTHING3) \
1821 : do { \
1822 : computed += VAL; \
1823 : } while (0)
1824 : #define FINALIZE_AGGREGATE_COUNT(NOTHING1, NOTHING2, NOTHING3) \
1825 : do { \
1826 : if (computed > minimum) { /* covariance_samp requires at least one value */ \
1827 : rb[k] = val; \
1828 : } else { \
1829 : rb[k] = dbl_nil; \
1830 : has_nils = true; \
1831 : } \
1832 : } while (0)
1833 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_OTHERS(TPE) \
1834 : do { \
1835 : TPE *restrict bp = (TPE*)di.base; \
1836 : oid ncount = i - k; \
1837 : if (GDKrebuild_segment_tree(ncount, sizeof(lng), st, &segment_tree, &levels_offset, &nlevels) != GDK_SUCCEED) { \
1838 : msg = createException(SQL, op, GDK_EXCEPTION); \
1839 : goto bailout; \
1840 : } \
1841 : populate_segment_tree(lng, ncount, INIT_AGGREGATE_COUNT, COMPUTE_LEVEL0_COUNT_FIXED, COMPUTE_LEVELN_COUNT, TPE, NOTHING, NOTHING); \
1842 : for (; k < i; k++) \
1843 : compute_on_segment_tree(lng, start[k] - j, end[k] - j, INIT_AGGREGATE_COUNT, COMPUTE_LEVELN_COUNT, FINALIZE_AGGREGATE_COUNT, TPE, NOTHING, NOTHING); \
1844 : j = k; \
1845 : } while (0)
1846 :
1847 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(TPE, IMP) \
1848 : do { \
1849 : if (p) { \
1850 : for (; i < cnt; i++) { \
1851 : if (np[i]) { \
1852 : covariance##TPE##IMP: \
1853 : IMP(TPE); \
1854 : } \
1855 : } \
1856 : } \
1857 : if (!last) { /* hack to reduce code explosion, there's no need to duplicate the code to iterate each partition */ \
1858 : last = true; \
1859 : i = cnt; \
1860 : goto covariance##TPE##IMP; \
1861 : } \
1862 : } while (0)
1863 :
1864 : #ifdef HAVE_HGE
1865 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP) \
1866 : case TYPE_hge: \
1867 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(hge, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1868 : break;
1869 : #else
1870 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP)
1871 : #endif
1872 :
1873 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(IMP) \
1874 : do { \
1875 : switch (tp1) { \
1876 : case TYPE_bte: \
1877 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(bte, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1878 : break; \
1879 : case TYPE_sht: \
1880 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(sht, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1881 : break; \
1882 : case TYPE_int: \
1883 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(int, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1884 : break; \
1885 : case TYPE_lng: \
1886 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(lng, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1887 : break; \
1888 : case TYPE_flt: \
1889 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(flt, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1890 : break; \
1891 : case TYPE_dbl: \
1892 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(dbl, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1893 : break; \
1894 : COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP) \
1895 : default: { \
1896 : msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1)); \
1897 : goto bailout; \
1898 : } \
1899 : } \
1900 : } while (0)
1901 :
1902 : static str
1903 150 : do_covariance_and_correlation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
1904 : gdk_return (*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int), lng minimum, dbl defaultv, dbl single_case)
1905 : {
1906 150 : BAT *r = NULL, *b = NULL, *c = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL, *st = NULL;
1907 150 : int tp1, tp2, frame_type;
1908 150 : bool is_a_bat1, is_a_bat2;
1909 150 : str msg = MAL_SUCCEED;
1910 150 : bat *res = NULL;
1911 150 : void *segment_tree = NULL;
1912 150 : oid *levels_offset = NULL;
1913 :
1914 150 : (void)cntxt;
1915 150 : if (pci->argc != 8)
1916 0 : throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 8 arguments", op);
1917 :
1918 150 : tp1 = getArgType(mb, pci, 1);
1919 150 : tp2 = getArgType(mb, pci, 2);
1920 150 : frame_type = *getArgReference_int(stk, pci, 5);
1921 150 : assert(frame_type >= 0 && frame_type <= 6);
1922 150 : is_a_bat1 = isaBatType(tp1);
1923 150 : is_a_bat2 = isaBatType(tp2);
1924 :
1925 150 : if (is_a_bat1)
1926 143 : tp1 = getBatType(tp1);
1927 150 : if (is_a_bat2)
1928 121 : tp2 = getBatType(tp2);
1929 150 : if (tp1 != tp2)
1930 0 : throw(SQL, op, SQLSTATE(42000) "The input arguments for %s must be from the same type", op);
1931 :
1932 150 : if (is_a_bat1 || is_a_bat2) {
1933 143 : res = getArgReference_bat(stk, pci, 0);
1934 :
1935 143 : if (is_a_bat1 && !(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
1936 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1937 0 : goto bailout1;
1938 : }
1939 143 : if (is_a_bat2 && !(c = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
1940 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1941 0 : goto bailout1;
1942 : }
1943 143 : if (!(r = COLnew(b->hseqbase, TYPE_dbl, BATcount(b), TRANSIENT))) {
1944 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1945 0 : goto bailout1;
1946 : }
1947 143 : if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
1948 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1949 0 : goto bailout1;
1950 : }
1951 143 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 4)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 4)))) {
1952 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1953 0 : goto bailout1;
1954 : }
1955 143 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
1956 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1957 0 : goto bailout1;
1958 : }
1959 29 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 7)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
1960 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1961 0 : goto bailout1;
1962 : }
1963 143 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o)) || (c && BATcount(b) != BATcount(c))) {
1964 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
1965 0 : goto bailout1;
1966 : }
1967 143 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
1968 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
1969 0 : goto bailout1;
1970 : }
1971 :
1972 143 : if (is_a_bat1 && is_a_bat2) {
1973 121 : if (func(r, p, o, b, c, s, e, tp1, frame_type) != GDK_SUCCEED)
1974 2 : msg = createException(SQL, op, GDK_EXCEPTION);
1975 : } else {
1976 : /* corner case, second column is a constant, calculate it this way... */
1977 22 : BAT *d = b ? b : c;
1978 22 : BATiter di = bat_iterator(d);
1979 22 : ValRecord *input2 = &(stk)->stk[(pci)->argv[b ? 2 : 1]];
1980 22 : BATiter si = bat_iterator(s);
1981 22 : BATiter ei = bat_iterator(e);
1982 22 : oid i = 0, j = 0, k = 0, l = 0, cnt = BATcount(d), *restrict start = s ? (oid*)si.base : NULL, *restrict end = e ? (oid*)ei.base : NULL,
1983 22 : nlevels = 0;
1984 22 : lng n = 0;
1985 22 : BATiter pi = bat_iterator(p);
1986 22 : BATiter oi = bat_iterator(o);
1987 22 : bit *np = pi.base, *opp = oi.base;
1988 22 : dbl *restrict rb = (dbl *) Tloc(r, 0), val = VALisnil(input2) ? dbl_nil : defaultv, rr;
1989 22 : bool has_nils = is_dbl_nil(val), last = false;
1990 :
1991 22 : if (cnt > 0) {
1992 22 : switch (frame_type) {
1993 6 : case 3: /* unbounded until current row */ {
1994 172 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
1995 : } break;
1996 0 : case 4: /* current row until unbounded */ {
1997 0 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
1998 : } break;
1999 12 : case 5: /* all rows */ {
2000 266 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(ALL_ROWS);
2001 : } break;
2002 0 : case 6: /* current row */ {
2003 0 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(CURRENT_ROW);
2004 : } break;
2005 4 : default: {
2006 4 : if ((st = GDKinitialize_segment_tree())) {
2007 388 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(OTHERS);
2008 : } else {
2009 0 : msg = createException(SQL, op, GDK_EXCEPTION);
2010 : }
2011 : }
2012 : }
2013 : }
2014 22 : BATsetcount(r, cnt);
2015 22 : r->tnonil = !has_nils;
2016 22 : r->tnil = has_nils;
2017 :
2018 22 : bailout:
2019 22 : bat_iterator_end(&di);
2020 22 : bat_iterator_end(&ei);
2021 22 : bat_iterator_end(&si);
2022 22 : bat_iterator_end(&oi);
2023 22 : bat_iterator_end(&pi);
2024 : }
2025 : } else {
2026 7 : dbl *res = getArgReference_dbl(stk, pci, 0);
2027 7 : ValRecord *input1 = &(stk)->stk[(pci)->argv[1]];
2028 7 : ValRecord *input2 = &(stk)->stk[(pci)->argv[2]];
2029 :
2030 7 : switch (tp1) {
2031 7 : case TYPE_bte:
2032 : case TYPE_sht:
2033 : case TYPE_int:
2034 : case TYPE_lng:
2035 : #ifdef HAVE_HGE
2036 : case TYPE_hge:
2037 : #endif
2038 : case TYPE_flt:
2039 : case TYPE_dbl:
2040 7 : *res = (VALisnil(input1) || VALisnil(input2)) ? dbl_nil : single_case;
2041 7 : break;
2042 0 : default:
2043 0 : msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1));
2044 : }
2045 : }
2046 :
2047 150 : bailout1:
2048 150 : BBPreclaim(st);
2049 150 : unfix_inputs(6, b, c, p, o, s, e);
2050 150 : finalize_output(res, r, msg);
2051 150 : return msg;
2052 : }
2053 :
2054 : str
2055 46 : SQLcovar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2056 : {
2057 46 : return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.covariance", GDKanalytical_covariance_samp, 1, 0.0f, dbl_nil);
2058 : }
2059 :
2060 : str
2061 44 : SQLcovar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2062 : {
2063 44 : return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.covariancep", GDKanalytical_covariance_pop, 0, 0.0f, 0.0f);
2064 : }
2065 :
2066 : str
2067 60 : SQLcorr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2068 : {
2069 60 : return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.corr", GDKanalytical_correlation, 0, dbl_nil, dbl_nil);
2070 : }
2071 :
2072 : str
2073 57 : SQLstrgroup_concat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2074 : {
2075 57 : BAT *r = NULL, *b = NULL, *sep = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
2076 57 : int separator_offset = 0, tpe, frame_type;
2077 57 : str msg = MAL_SUCCEED, separator = NULL;
2078 57 : bat *res = NULL;
2079 :
2080 57 : (void)cntxt;
2081 57 : if (pci->argc != 7 && pci->argc != 8)
2082 0 : throw(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT "sql.strgroup_concat requires 7 or 8 arguments");
2083 :
2084 57 : tpe = getArgType(mb, pci, 2);
2085 57 : if (isaBatType(tpe))
2086 30 : tpe = getBatType(tpe);
2087 57 : if (tpe == TYPE_str) /* there's a separator */
2088 : separator_offset = 1;
2089 : else
2090 7 : assert(tpe == TYPE_bit); /* otherwise it must be the partition's type */
2091 :
2092 57 : frame_type = *getArgReference_int(stk, pci, 4 + separator_offset);
2093 57 : assert(frame_type >= 0 && frame_type <= 6);
2094 :
2095 57 : if (isaBatType(getArgType(mb, pci, 1))) {
2096 53 : res = getArgReference_bat(stk, pci, 0);
2097 :
2098 53 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
2099 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2100 0 : goto bailout;
2101 : }
2102 53 : if (!(r = COLnew(b->hseqbase, TYPE_str, BATcount(b), TRANSIENT))) {
2103 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2104 0 : goto bailout;
2105 : }
2106 53 : if (separator_offset) {
2107 48 : if (isaBatType(getArgType(mb, pci, 2))) {
2108 30 : if (!(sep = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
2109 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2110 0 : goto bailout;
2111 : }
2112 : } else
2113 18 : separator = *getArgReference_str(stk, pci, 2);
2114 : } else
2115 : separator = ",";
2116 :
2117 53 : if (isaBatType(getArgType(mb, pci, 2 + separator_offset)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 2 + separator_offset)))) {
2118 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2119 0 : goto bailout;
2120 : }
2121 53 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 3 + separator_offset)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3 + separator_offset)))) {
2122 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2123 0 : goto bailout;
2124 : }
2125 53 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 5 + separator_offset)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 5 + separator_offset)))) {
2126 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2127 0 : goto bailout;
2128 : }
2129 0 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6 + separator_offset)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 6 + separator_offset)))) {
2130 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2131 0 : goto bailout;
2132 : }
2133 53 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o)) || (sep && BATcount(b) != BATcount(sep))) {
2134 0 : msg = createException(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT " Requires bats of identical size");
2135 0 : goto bailout;
2136 : }
2137 53 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
2138 0 : msg = createException(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
2139 0 : goto bailout;
2140 : }
2141 :
2142 53 : assert((separator && !sep) || (!separator && sep)); /* only one of them must be set */
2143 53 : if (GDKanalytical_str_group_concat(r, p, o, b, sep, s, e, separator, frame_type) != GDK_SUCCEED)
2144 0 : msg = createException(SQL, "sql.strgroup_concat", GDK_EXCEPTION);
2145 : } else {
2146 4 : str *res = getArgReference_str(stk, pci, 0);
2147 4 : str in = *getArgReference_str(stk, pci, 1);
2148 :
2149 4 : if (strNil(in)) {
2150 3 : *res = GDKstrdup(str_nil);
2151 1 : } else if (separator_offset) {
2152 1 : str sep = *getArgReference_str(stk, pci, 2);
2153 1 : size_t l1 = strlen(in), l2 = strNil(sep) ? 0 : strlen(sep);
2154 :
2155 1 : if ((*res = GDKmalloc(l1+l2+1))) {
2156 1 : if (l1)
2157 1 : memcpy(*res, in, l1);
2158 1 : if (l2)
2159 0 : memcpy((*res)+l1, sep, l2);
2160 1 : (*res)[l1+l2] = '\0';
2161 : }
2162 : } else {
2163 0 : *res = GDKstrdup(in);
2164 : }
2165 4 : if (!*res)
2166 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2167 : }
2168 :
2169 4 : bailout:
2170 57 : unfix_inputs(6, b, sep, p, o, s, e);
2171 57 : finalize_output(res, r, msg);
2172 57 : return msg;
2173 : }
|