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