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 4314 : unfix_inputs(int nargs, ...)
19 : {
20 4314 : va_list valist;
21 :
22 4314 : va_start(valist, nargs);
23 17740 : for (int i = 0; i < nargs; i++) {
24 13426 : BAT *b = va_arg(valist, BAT *);
25 20734 : BBPreclaim(b);
26 : }
27 4314 : va_end(valist);
28 4314 : }
29 :
30 : static void
31 4082 : finalize_output(bat *res, BAT *r, str msg)
32 : {
33 4082 : if (res && r && !msg) {
34 3925 : r->tsorted = BATcount(r) <= 1;
35 3925 : r->trevsorted = BATcount(r) <= 1;
36 3925 : r->tkey = BATcount(r) <= 1;
37 3925 : *res = r->batCacheid;
38 3925 : BBPkeepref(r);
39 157 : } else if (r)
40 0 : BBPreclaim(r);
41 4082 : }
42 :
43 : str
44 1947 : SQLdiff(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
45 : {
46 1947 : BAT *r = NULL, *b = NULL, *c = NULL;
47 1947 : bat *res = NULL;
48 1947 : str msg = MAL_SUCCEED;
49 :
50 1947 : (void)cntxt;
51 1947 : if (isaBatType(getArgType(mb, pci, 1))) {
52 1914 : gdk_return gdk_code = GDK_SUCCEED;
53 :
54 1914 : res = getArgReference_bat(stk, pci, 0);
55 1914 : if (pci->argc > 2) {
56 592 : if (isaBatType(getArgType(mb, pci, 2))) {
57 592 : 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 592 : 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 592 : 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 1322 : 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 1322 : 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 1947 : bailout:
103 1947 : unfix_inputs(2, b, c);
104 1947 : finalize_output(res, r, msg);
105 1947 : return msg;
106 : }
107 :
108 : str
109 799 : SQLwindow_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
110 : {
111 799 : str msg = MAL_SUCCEED;
112 799 : bool preceding;
113 799 : oid second_half;
114 799 : int unit, bound, excl, part_offset = (pci->argc > 6);
115 799 : bat *res = NULL;
116 799 : BAT *r = NULL, *b = NULL, *p = NULL, *l = NULL;
117 :
118 799 : 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 799 : unit = *getArgReference_int(stk, pci, part_offset + 2);
124 799 : bound = *getArgReference_int(stk, pci, part_offset + 3);
125 799 : excl = *getArgReference_int(stk, pci, part_offset + 4);
126 :
127 799 : assert(unit >= 0 && unit <= 3);
128 799 : assert(bound >= 0 && bound <= 5);
129 799 : assert(excl >= 0 && excl <= 2);
130 799 : preceding = (bound % 2 == 0);
131 799 : second_half = !(bound < 2 || bound == 4);
132 :
133 799 : (void)cntxt;
134 799 : if (isaBatType(getArgType(mb, pci, 1))) {
135 765 : int tp1, tp2 = getArgType(mb, pci, part_offset + 5);
136 765 : ptr limit = NULL;
137 765 : bool is_a_bat;
138 :
139 765 : res = getArgReference_bat(stk, pci, 0);
140 765 : 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 765 : tp1 = b->ttype;
145 :
146 765 : 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 765 : is_a_bat = isaBatType(tp2);
152 765 : 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 751 : limit = getArgReference(stk, pci, part_offset + 5);
162 : }
163 765 : 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 799 : bailout:
180 799 : unfix_inputs(3, b, p, l);
181 799 : finalize_output(res, r, msg);
182 799 : return msg;
183 : }
184 :
185 : str
186 65 : SQLrow_number(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
187 : {
188 65 : BAT *r = NULL, *b = NULL, *p = NULL;
189 65 : bat *res = NULL;
190 65 : str msg = MAL_SUCCEED;
191 :
192 65 : if (pci->argc != 4 ||
193 65 : (getArgType(mb, pci, 2) != TYPE_bit && getBatType(getArgType(mb, pci, 2)) != TYPE_bit) ||
194 65 : (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 65 : (void)cntxt;
198 65 : if (isaBatType(getArgType(mb, pci, 1))) {
199 63 : BUN cnt;
200 63 : int j, *rp, *end;
201 63 : bit *np;
202 :
203 63 : res = getArgReference_bat(stk, pci, 0);
204 63 : 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 63 : 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 63 : r->tsorted = r->trevsorted = r->tkey = BATcount(b) <= 1;
213 :
214 63 : cnt = BATcount(b);
215 63 : rp = (int*)Tloc(r, 0);
216 63 : if (isaBatType(getArgType(mb, pci, 2))) {
217 : /* order info not used */
218 23 : 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 23 : BATiter pi = bat_iterator(p);
223 23 : np = (bit*)pi.base;
224 23 : end = rp + cnt;
225 1248578 : for(j=1; rp<end; j++, np++, rp++) {
226 1248555 : if (*np)
227 29153 : j=1;
228 1248555 : *rp = j;
229 : }
230 23 : 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 63 : BATsetcount(r, cnt);
239 63 : r->tnonil = true;
240 63 : r->tnil = false;
241 : } else {
242 2 : int *res = getArgReference_int(stk, pci, 0);
243 :
244 2 : *res = 1;
245 : }
246 :
247 65 : bailout:
248 65 : unfix_inputs(2, b, p);
249 65 : if (res && r && !msg) {
250 63 : r->tkey = BATcount(r) <= 1;
251 63 : *res = r->batCacheid;
252 63 : 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 601919 : for(; rp<end; rp++)
339 601873 : *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 548 : 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 548 : (void) cntxt;
829 548 : if (pci->argc != 7)
830 0 : throw(SQL, mod, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", mod);
831 :
832 548 : *frame_type = *getArgReference_int(stk, pci, 4);
833 548 : assert(*frame_type >= 0 && *frame_type <= 6);
834 :
835 548 : 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 591 : c = ol_first_node(t->columns)->data;
1262 591 : sqlstore *store = m->session->tr->store;
1263 :
1264 591 : *res = store->storage_api.count_col(m->session->tr, c, 10);
1265 591 : return msg;
1266 : }
1267 :
1268 : str
1269 174 : SQLcount(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1270 : {
1271 174 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1272 174 : int tpe, frame_type;
1273 174 : bit ignore_nils;
1274 174 : bat *res = NULL;
1275 174 : str msg = MAL_SUCCEED;
1276 :
1277 174 : (void) cntxt;
1278 174 : if (pci->argc != 8)
1279 0 : throw(SQL, "sql.count", ILLEGAL_ARGUMENT "sql.count requires exactly 8 arguments");
1280 174 : tpe = getArgType(mb, pci, 1);
1281 174 : ignore_nils = *getArgReference_bit(stk, pci, 2);
1282 174 : frame_type = *getArgReference_int(stk, pci, 5);
1283 174 : assert(frame_type >= 0 && frame_type <= 6);
1284 :
1285 174 : if (isaBatType(tpe))
1286 159 : tpe = getBatType(tpe);
1287 174 : if (isaBatType(getArgType(mb, pci, 1)) && (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1))))) {
1288 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1289 0 : goto bailout;
1290 : }
1291 174 : if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
1292 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1293 0 : goto bailout;
1294 : }
1295 174 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 4)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 4)))) {
1296 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1297 0 : goto bailout;
1298 : }
1299 174 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
1300 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1301 0 : goto bailout;
1302 : }
1303 81 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 7)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
1304 0 : msg = createException(SQL, "sql.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1305 0 : goto bailout;
1306 : }
1307 174 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o))) {
1308 0 : msg = createException(SQL, "sql.count", ILLEGAL_ARGUMENT " Requires bats of identical size");
1309 0 : goto bailout;
1310 : }
1311 174 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
1312 0 : msg = createException(SQL, "sql.count", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
1313 0 : goto bailout;
1314 : }
1315 :
1316 174 : if (b) {
1317 159 : res = getArgReference_bat(stk, pci, 0);
1318 :
1319 159 : if ((r = GDKanalyticalcount(p, o, b, s, e, ignore_nils, tpe, frame_type)) == NULL)
1320 0 : msg = createException(SQL, "sql.count", GDK_EXCEPTION);
1321 : } else {
1322 15 : lng *res = getArgReference_lng(stk, pci, 0);
1323 15 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
1324 :
1325 30 : *res = (VALisnil(in) && ignore_nils) ? 0 : 1;
1326 : }
1327 :
1328 174 : bailout:
1329 174 : unfix_inputs(5, b, p, o, s, e);
1330 174 : finalize_output(res, r, msg);
1331 174 : return msg;
1332 : }
1333 :
1334 : static str
1335 171 : do_analytical_sumprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
1336 : BAT *(*func)(BAT *, BAT *, BAT *, BAT *, BAT *, int, int, int))
1337 : {
1338 171 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1339 171 : int tp1, tp2, frame_type;
1340 171 : str msg = MAL_SUCCEED;
1341 171 : bat *res = NULL;
1342 :
1343 171 : (void) cntxt;
1344 171 : if (pci->argc != 7)
1345 0 : throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 7 arguments", op);
1346 171 : tp2 = getArgType(mb, pci, 0);
1347 171 : tp1 = getArgType(mb, pci, 1);
1348 171 : frame_type = *getArgReference_int(stk, pci, 4);
1349 171 : assert(frame_type >= 0 && frame_type <= 6);
1350 :
1351 171 : if (isaBatType(tp1)) {
1352 162 : tp1 = getBatType(tp1);
1353 162 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
1354 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1355 0 : goto bailout;
1356 : }
1357 : }
1358 171 : if (isaBatType(tp2))
1359 162 : tp2 = getBatType(tp2);
1360 :
1361 171 : if (b) {
1362 162 : res = getArgReference_bat(stk, pci, 0);
1363 162 : if (isaBatType(getArgType(mb, pci, 2)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
1364 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1365 0 : goto bailout;
1366 : }
1367 162 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 3)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
1368 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1369 0 : goto bailout;
1370 : }
1371 162 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 5)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 5)))) {
1372 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1373 0 : goto bailout;
1374 : }
1375 59 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
1376 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1377 0 : goto bailout;
1378 : }
1379 162 : if ((s && BATcount(b) != BATcount(s)) || (e && BATcount(b) != BATcount(e)) || (p && BATcount(b) != BATcount(p)) || (o && BATcount(b) != BATcount(o))) {
1380 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
1381 0 : goto bailout;
1382 : }
1383 162 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
1384 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
1385 0 : goto bailout;
1386 : }
1387 :
1388 162 : if ((r = func(p, o, b, s, e, tp1, tp2, frame_type)) == NULL)
1389 0 : msg = createException(SQL, op, GDK_EXCEPTION);
1390 : } else {
1391 : /* the pointers here will always point from bte to dbl, so no strings are handled here */
1392 9 : ptr res = getArgReference(stk, pci, 0);
1393 9 : ptr in = getArgReference(stk, pci, 1);
1394 9 : int scale = 0;
1395 :
1396 9 : switch (tp2) {
1397 0 : case TYPE_bte:
1398 0 : switch (tp1) {
1399 0 : case TYPE_bte:
1400 0 : msg = bte_dec2_bte((bte*)res, &scale, (bte*)in);
1401 0 : break;
1402 0 : default:
1403 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1404 : }
1405 : break;
1406 0 : case TYPE_sht:
1407 0 : switch (tp1) {
1408 0 : case TYPE_bte:
1409 0 : msg = bte_dec2_sht((sht*)res, &scale, (bte*)in);
1410 0 : break;
1411 0 : case TYPE_sht:
1412 0 : msg = sht_dec2_sht((sht*)res, &scale, (sht*)in);
1413 0 : break;
1414 0 : default:
1415 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1416 : }
1417 : break;
1418 0 : case TYPE_int:
1419 0 : switch (tp1) {
1420 0 : case TYPE_bte:
1421 0 : msg = bte_dec2_int((int*)res, &scale, (bte*)in);
1422 0 : break;
1423 0 : case TYPE_sht:
1424 0 : msg = sht_dec2_int((int*)res, &scale, (sht*)in);
1425 0 : break;
1426 0 : case TYPE_int:
1427 0 : msg = int_dec2_int((int*)res, &scale, (int*)in);
1428 0 : break;
1429 0 : default:
1430 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1431 : }
1432 : break;
1433 0 : case TYPE_lng:
1434 0 : switch (tp1) {
1435 0 : case TYPE_bte:
1436 0 : msg = bte_dec2_lng((lng*)res, &scale, (bte*)in);
1437 0 : break;
1438 0 : case TYPE_sht:
1439 0 : msg = sht_dec2_lng((lng*)res, &scale, (sht*)in);
1440 0 : break;
1441 0 : case TYPE_int:
1442 0 : msg = int_dec2_lng((lng*)res, &scale, (int*)in);
1443 0 : break;
1444 0 : case TYPE_lng:
1445 0 : msg = lng_dec2_lng((lng*)res, &scale, (lng*)in);
1446 0 : break;
1447 0 : default:
1448 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1449 : }
1450 : break;
1451 : #ifdef HAVE_HGE
1452 6 : case TYPE_hge:
1453 6 : switch (tp1) {
1454 3 : case TYPE_bte:
1455 3 : msg = bte_dec2_hge((hge*)res, &scale, (bte*)in);
1456 3 : break;
1457 0 : case TYPE_sht:
1458 0 : msg = sht_dec2_hge((hge*)res, &scale, (sht*)in);
1459 0 : break;
1460 3 : case TYPE_int:
1461 3 : msg = int_dec2_hge((hge*)res, &scale, (int*)in);
1462 3 : break;
1463 0 : case TYPE_lng:
1464 0 : msg = lng_dec2_hge((hge*)res, &scale, (lng*)in);
1465 0 : break;
1466 0 : case TYPE_hge:
1467 0 : msg = hge_dec2_hge((hge*)res, &scale, (hge*)in);
1468 0 : break;
1469 0 : default:
1470 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1471 : }
1472 : break;
1473 : #endif
1474 0 : case TYPE_flt:
1475 0 : switch (tp1) {
1476 0 : case TYPE_flt:
1477 0 : *(flt*)res = *((flt*)in);
1478 0 : break;
1479 0 : default:
1480 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1481 : }
1482 : break;
1483 3 : case TYPE_dbl:
1484 3 : switch (tp1) {
1485 0 : case TYPE_flt: {
1486 0 : flt fp = *((flt*)in);
1487 0 : *(dbl*)res = is_flt_nil(fp) ? dbl_nil : (dbl) fp;
1488 0 : } break;
1489 3 : case TYPE_dbl:
1490 3 : *(dbl*)res = *((dbl*)in);
1491 3 : break;
1492 0 : default:
1493 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1494 : }
1495 : break;
1496 0 : default:
1497 0 : msg = createException(SQL, op, SQLSTATE(42000) "type combination (%s(%s)->%s) not supported", op, ATOMname(tp1), ATOMname(tp2));
1498 : }
1499 : }
1500 :
1501 170 : bailout:
1502 170 : unfix_inputs(5, b, p, o, s, e);
1503 171 : finalize_output(res, r, msg);
1504 171 : return msg;
1505 : }
1506 :
1507 : str
1508 140 : SQLsum(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1509 : {
1510 140 : return do_analytical_sumprod(cntxt, mb, stk, pci, "sql.sum", GDKanalyticalsum);
1511 : }
1512 :
1513 : str
1514 31 : SQLprod(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1515 : {
1516 31 : return do_analytical_sumprod(cntxt, mb, stk, pci, "sql.prod", GDKanalyticalprod);
1517 : }
1518 :
1519 : str
1520 88 : SQLavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1521 : {
1522 88 : int tpe = getArgType(mb, pci, 1), frame_type = 0;
1523 88 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1524 88 : str msg = SQLanalytics_args(NULL, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, TYPE_dbl, "sql.avg");
1525 88 : bat *res = NULL;
1526 :
1527 88 : if (msg)
1528 0 : goto bailout;
1529 88 : if (isaBatType(tpe))
1530 72 : tpe = getBatType(tpe);
1531 :
1532 88 : if (b) {
1533 72 : res = getArgReference_bat(stk, pci, 0);
1534 :
1535 72 : if ((r = GDKanalyticalavg(p, o, b, s, e, tpe, frame_type)) == NULL)
1536 0 : msg = createException(SQL, "sql.avg", GDK_EXCEPTION);
1537 : } else {
1538 : /* the pointers here will always point from bte to dbl, so no strings are handled here */
1539 16 : ptr res = getArgReference(stk, pci, 0);
1540 16 : ptr in = getArgReference(stk, pci, 1);
1541 16 : int scale = 0;
1542 :
1543 16 : switch (tpe) {
1544 3 : case TYPE_bte:
1545 3 : msg = bte_dec2_dbl((dbl*)res, &scale, (bte*)in);
1546 3 : break;
1547 2 : case TYPE_sht:
1548 2 : msg = sht_dec2_dbl((dbl*)res, &scale, (sht*)in);
1549 2 : break;
1550 8 : case TYPE_int:
1551 8 : msg = int_dec2_dbl((dbl*)res, &scale, (int*)in);
1552 8 : break;
1553 0 : case TYPE_lng:
1554 0 : msg = lng_dec2_dbl((dbl*)res, &scale, (lng*)in);
1555 0 : break;
1556 : #ifdef HAVE_HGE
1557 0 : case TYPE_hge:
1558 0 : msg = hge_dec2_dbl((dbl*)res, &scale, (hge*)in);
1559 0 : break;
1560 : #endif
1561 0 : case TYPE_flt: {
1562 0 : flt fp = *((flt*)in);
1563 0 : *(dbl*)res = is_flt_nil(fp) ? dbl_nil : (dbl) fp;
1564 0 : break;
1565 : }
1566 3 : case TYPE_dbl:
1567 3 : *(dbl*)res = *((dbl*)in);
1568 3 : break;
1569 0 : default:
1570 0 : msg = createException(SQL, "sql.avg", SQLSTATE(42000) "sql.avg not available for %s to dbl", ATOMname(tpe));
1571 : }
1572 : }
1573 :
1574 88 : bailout:
1575 88 : unfix_inputs(5, b, p, o, s, e);
1576 88 : finalize_output(res, r, msg);
1577 88 : return msg;
1578 : }
1579 :
1580 : str
1581 48 : SQLavginteger(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1582 : {
1583 48 : int tpe = getArgType(mb, pci, 1), frame_type = 0;
1584 48 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1585 48 : str msg = SQLanalytics_args(NULL, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, 0, "sql.avg");
1586 48 : bat *res = NULL;
1587 :
1588 48 : if (msg)
1589 0 : goto bailout;
1590 48 : if (isaBatType(tpe))
1591 48 : tpe = getBatType(tpe);
1592 :
1593 48 : if (b) {
1594 48 : res = getArgReference_bat(stk, pci, 0);
1595 :
1596 48 : if ((r = GDKanalyticalavginteger(p, o, b, s, e, tpe, frame_type)) == NULL)
1597 0 : msg = createException(SQL, "sql.avg", GDK_EXCEPTION);
1598 : } else {
1599 0 : ValRecord *res = &(stk)->stk[(pci)->argv[0]];
1600 0 : ValRecord *in = &(stk)->stk[(pci)->argv[1]];
1601 :
1602 0 : switch (tpe) {
1603 0 : case TYPE_bte:
1604 : case TYPE_sht:
1605 : case TYPE_int:
1606 : case TYPE_lng:
1607 : #ifdef HAVE_HGE
1608 : case TYPE_hge:
1609 : #endif
1610 0 : if (!VALcopy(res, in))
1611 0 : msg = createException(SQL, "sql.avg", SQLSTATE(HY013) MAL_MALLOC_FAIL); /* malloc failure should never happen, but let it be here */
1612 : break;
1613 0 : default:
1614 0 : msg = createException(SQL, "sql.avg", SQLSTATE(42000) "sql.avg not available for %s to %s", ATOMname(tpe), ATOMname(tpe));
1615 : }
1616 : }
1617 :
1618 48 : bailout:
1619 48 : unfix_inputs(5, b, p, o, s, e);
1620 48 : finalize_output(res, r, msg);
1621 48 : return msg;
1622 : }
1623 :
1624 : static str
1625 57 : do_stddev_and_variance(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
1626 : BAT *(*func)(BAT *, BAT *, BAT *, BAT *, BAT *, int, int))
1627 : {
1628 57 : int tpe = getArgType(mb, pci, 1), frame_type = 0;
1629 57 : BAT *r = NULL, *b = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
1630 57 : str msg = SQLanalytics_args(NULL, &b, &frame_type, &p, &o, &s, &e, cntxt, mb, stk, pci, TYPE_dbl, op);
1631 57 : bat *res = NULL;
1632 :
1633 57 : if (msg)
1634 0 : goto bailout;
1635 57 : if (isaBatType(tpe))
1636 56 : tpe = getBatType(tpe);
1637 :
1638 57 : if (b) {
1639 56 : res = getArgReference_bat(stk, pci, 0);
1640 :
1641 56 : if ((r = func(p, o, b, s, e, tpe, frame_type)) == NULL)
1642 2 : msg = createException(SQL, op, GDK_EXCEPTION);
1643 : } else {
1644 1 : dbl *res = getArgReference_dbl(stk, pci, 0);
1645 1 : switch (tpe) {
1646 1 : case TYPE_bte:
1647 : case TYPE_sht:
1648 : case TYPE_int:
1649 : case TYPE_lng:
1650 : #ifdef HAVE_HGE
1651 : case TYPE_hge:
1652 : #endif
1653 : case TYPE_flt:
1654 : case TYPE_dbl:
1655 1 : *res = dbl_nil;
1656 1 : break;
1657 0 : default:
1658 0 : msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tpe));
1659 : }
1660 : }
1661 :
1662 57 : bailout:
1663 57 : unfix_inputs(5, b, p, o, s, e);
1664 57 : finalize_output(res, r, msg);
1665 57 : return msg;
1666 : }
1667 :
1668 : str
1669 17 : SQLstddev_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1670 : {
1671 17 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.stdev", GDKanalytical_stddev_samp);
1672 : }
1673 :
1674 : str
1675 12 : SQLstddev_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1676 : {
1677 12 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.stdevp", GDKanalytical_stddev_pop);
1678 : }
1679 :
1680 : str
1681 12 : SQLvar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1682 : {
1683 12 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.variance", GDKanalytical_variance_samp);
1684 : }
1685 :
1686 : str
1687 16 : SQLvar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1688 : {
1689 16 : return do_stddev_and_variance(cntxt, mb, stk, pci, "sql.variancep", GDKanalytical_variance_pop);
1690 : }
1691 :
1692 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_UNBOUNDED_TILL_CURRENT_ROW(TPE) \
1693 : do { \
1694 : TPE *restrict bp = (TPE*)di.base; \
1695 : for (; k < i;) { \
1696 : j = k; \
1697 : do { \
1698 : n += !is_##TPE##_nil(bp[k]); \
1699 : k++; \
1700 : } while (k < i && !opp[k]); \
1701 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1702 : rr = val; \
1703 : } else { \
1704 : rr = dbl_nil; \
1705 : has_nils = true; \
1706 : } \
1707 : for (; j < k; j++) \
1708 : rb[j] = rr; \
1709 : } \
1710 : n = 0; \
1711 : k = i; \
1712 : } while (0)
1713 :
1714 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_CURRENT_ROW_TILL_UNBOUNDED(TPE) \
1715 : do { \
1716 : TPE *restrict bp = (TPE*)di.base; \
1717 : l = i - 1; \
1718 : for (j = l; ; j--) { \
1719 : n += !is_##TPE##_nil(bp[j]); \
1720 : if (opp[j] || j == k) { \
1721 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1722 : rr = val; \
1723 : } else { \
1724 : rr = dbl_nil; \
1725 : has_nils = true; \
1726 : } \
1727 : for (; ; l--) { \
1728 : rb[l] = rr; \
1729 : if (l == j) \
1730 : break; \
1731 : } \
1732 : if (j == k) \
1733 : break; \
1734 : l = j - 1; \
1735 : } \
1736 : } \
1737 : n = 0; \
1738 : k = i; \
1739 : } while (0)
1740 :
1741 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_ALL_ROWS(TPE) \
1742 : do { \
1743 : TPE *restrict bp = (TPE*)di.base; \
1744 : for (; j < i; j++) \
1745 : n += !is_##TPE##_nil(bp[j]); \
1746 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1747 : rr = val; \
1748 : } else { \
1749 : rr = dbl_nil; \
1750 : has_nils = true; \
1751 : } \
1752 : for (; k < i; k++) \
1753 : rb[k] = rr; \
1754 : n = 0; \
1755 : } while (0)
1756 :
1757 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_CURRENT_ROW(TPE) \
1758 : do { \
1759 : TPE *restrict bp = (TPE*)di.base; \
1760 : for (; k < i; k++) { \
1761 : n += !is_##TPE##_nil(bp[k]); \
1762 : if (n > minimum) { /* covariance_samp requires at least one value */ \
1763 : rb[k] = val; \
1764 : } else { \
1765 : rb[k] = dbl_nil; \
1766 : has_nils = true; \
1767 : } \
1768 : n = 0; \
1769 : } \
1770 : } while (0)
1771 :
1772 : #define INIT_AGGREGATE_COUNT(TPE, NOTHING1, NOTHING2) \
1773 : do { \
1774 : computed = 0; \
1775 : } while (0)
1776 : #define COMPUTE_LEVEL0_COUNT_FIXED(X, TPE, NOTHING1, NOTHING2) \
1777 : do { \
1778 : computed = !is_##TPE##_nil(bp[j + X]); \
1779 : } while (0)
1780 : #define COMPUTE_LEVELN_COUNT(VAL, NOTHING1, NOTHING2, NOTHING3) \
1781 : do { \
1782 : computed += VAL; \
1783 : } while (0)
1784 : #define FINALIZE_AGGREGATE_COUNT(NOTHING1, NOTHING2, NOTHING3) \
1785 : do { \
1786 : if (computed > minimum) { /* covariance_samp requires at least one value */ \
1787 : rb[k] = val; \
1788 : } else { \
1789 : rb[k] = dbl_nil; \
1790 : has_nils = true; \
1791 : } \
1792 : } while (0)
1793 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_OTHERS(TPE) \
1794 : do { \
1795 : TPE *restrict bp = (TPE*)di.base; \
1796 : oid ncount = i - k; \
1797 : if (GDKrebuild_segment_tree(ncount, sizeof(lng), st, &segment_tree, &levels_offset, &nlevels) != GDK_SUCCEED) { \
1798 : msg = createException(SQL, op, GDK_EXCEPTION); \
1799 : goto bailout; \
1800 : } \
1801 : populate_segment_tree(lng, ncount, INIT_AGGREGATE_COUNT, COMPUTE_LEVEL0_COUNT_FIXED, COMPUTE_LEVELN_COUNT, TPE, NOTHING, NOTHING); \
1802 : for (; k < i; k++) \
1803 : compute_on_segment_tree(lng, start[k] - j, end[k] - j, INIT_AGGREGATE_COUNT, COMPUTE_LEVELN_COUNT, FINALIZE_AGGREGATE_COUNT, TPE, NOTHING, NOTHING); \
1804 : j = k; \
1805 : } while (0)
1806 :
1807 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(TPE, IMP) \
1808 : do { \
1809 : if (p) { \
1810 : for (; i < cnt; i++) { \
1811 : if (np[i]) { \
1812 : covariance##TPE##IMP: \
1813 : IMP(TPE); \
1814 : } \
1815 : } \
1816 : } \
1817 : if (!last) { /* hack to reduce code explosion, there's no need to duplicate the code to iterate each partition */ \
1818 : last = true; \
1819 : i = cnt; \
1820 : goto covariance##TPE##IMP; \
1821 : } \
1822 : } while (0)
1823 :
1824 : #ifdef HAVE_HGE
1825 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP) \
1826 : case TYPE_hge: \
1827 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(hge, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1828 : break;
1829 : #else
1830 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP)
1831 : #endif
1832 :
1833 : #define COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(IMP) \
1834 : do { \
1835 : switch (tp1) { \
1836 : case TYPE_bte: \
1837 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(bte, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1838 : break; \
1839 : case TYPE_sht: \
1840 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(sht, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1841 : break; \
1842 : case TYPE_int: \
1843 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(int, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1844 : break; \
1845 : case TYPE_lng: \
1846 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(lng, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1847 : break; \
1848 : case TYPE_flt: \
1849 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(flt, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1850 : break; \
1851 : case TYPE_dbl: \
1852 : COVARIANCE_AND_CORRELATION_ONE_SIDE_PARTITIONS(dbl, COVARIANCE_AND_CORRELATION_ONE_SIDE_##IMP); \
1853 : break; \
1854 : COVARIANCE_AND_CORRELATION_ONE_SIDE_LIMIT(IMP) \
1855 : default: \
1856 : msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1)); \
1857 : goto bailout; \
1858 : } \
1859 : } while (0)
1860 :
1861 : static str
1862 150 : do_covariance_and_correlation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, const char *op,
1863 : BAT *(*func)(BAT *, BAT *, BAT *, BAT *, BAT *, BAT *, int, int), lng minimum, dbl defaultv, dbl single_case)
1864 : {
1865 150 : BAT *r = NULL, *b = NULL, *c = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL, *st = NULL;
1866 150 : int tp1, tp2, frame_type;
1867 150 : bool is_a_bat1, is_a_bat2;
1868 150 : str msg = MAL_SUCCEED;
1869 150 : bat *res = NULL;
1870 150 : void *segment_tree = NULL;
1871 150 : oid *levels_offset = NULL;
1872 :
1873 150 : (void)cntxt;
1874 150 : if (pci->argc != 8)
1875 0 : throw(SQL, op, ILLEGAL_ARGUMENT "%s requires exactly 8 arguments", op);
1876 :
1877 150 : tp1 = getArgType(mb, pci, 1);
1878 150 : tp2 = getArgType(mb, pci, 2);
1879 150 : frame_type = *getArgReference_int(stk, pci, 5);
1880 150 : assert(frame_type >= 0 && frame_type <= 6);
1881 150 : is_a_bat1 = isaBatType(tp1);
1882 150 : is_a_bat2 = isaBatType(tp2);
1883 :
1884 150 : if (is_a_bat1)
1885 143 : tp1 = getBatType(tp1);
1886 150 : if (is_a_bat2)
1887 121 : tp2 = getBatType(tp2);
1888 150 : if (tp1 != tp2)
1889 0 : throw(SQL, op, SQLSTATE(42000) "The input arguments for %s must be from the same type", op);
1890 :
1891 150 : if (is_a_bat1 || is_a_bat2) {
1892 143 : res = getArgReference_bat(stk, pci, 0);
1893 :
1894 143 : if (is_a_bat1 && !(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
1895 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1896 0 : goto bailout1;
1897 : }
1898 143 : if (is_a_bat2 && !(c = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
1899 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1900 0 : goto bailout1;
1901 : }
1902 143 : if (isaBatType(getArgType(mb, pci, 3)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 3)))) {
1903 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1904 0 : goto bailout1;
1905 : }
1906 143 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 4)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 4)))) {
1907 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1908 0 : goto bailout1;
1909 : }
1910 143 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 6)))) {
1911 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1912 0 : goto bailout1;
1913 : }
1914 29 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 7)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 7)))) {
1915 0 : msg = createException(SQL, op, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1916 0 : goto bailout1;
1917 : }
1918 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))) {
1919 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " Requires bats of identical size");
1920 0 : goto bailout1;
1921 : }
1922 143 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
1923 0 : msg = createException(SQL, op, ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
1924 0 : goto bailout1;
1925 : }
1926 :
1927 143 : if (is_a_bat1 && is_a_bat2) {
1928 121 : if ((r = func(p, o, b, c, s, e, tp1, frame_type)) == NULL)
1929 2 : msg = createException(SQL, op, GDK_EXCEPTION);
1930 : } else {
1931 : /* corner case, second column is a constant, calculate it this way... */
1932 22 : if (!(r = COLnew(b->hseqbase, TYPE_dbl, BATcount(b), TRANSIENT))) {
1933 0 : msg = createException(SQL, op, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1934 0 : goto bailout1;
1935 : }
1936 22 : BAT *d = b ? b : c;
1937 22 : BATiter di = bat_iterator(d);
1938 22 : ValRecord *input2 = &(stk)->stk[(pci)->argv[b ? 2 : 1]];
1939 22 : BATiter si = bat_iterator(s);
1940 22 : BATiter ei = bat_iterator(e);
1941 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,
1942 22 : nlevels = 0;
1943 22 : lng n = 0;
1944 22 : BATiter pi = bat_iterator(p);
1945 22 : BATiter oi = bat_iterator(o);
1946 22 : bit *np = pi.base, *opp = oi.base;
1947 22 : dbl *restrict rb = (dbl *) Tloc(r, 0), val = VALisnil(input2) ? dbl_nil : defaultv, rr;
1948 22 : bool has_nils = is_dbl_nil(val), last = false;
1949 :
1950 22 : if (cnt > 0) {
1951 22 : switch (frame_type) {
1952 6 : case 3: /* unbounded until current row */
1953 172 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(UNBOUNDED_TILL_CURRENT_ROW);
1954 : break;
1955 0 : case 4: /* current row until unbounded */
1956 0 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(CURRENT_ROW_TILL_UNBOUNDED);
1957 : break;
1958 12 : case 5: /* all rows */
1959 266 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(ALL_ROWS);
1960 : break;
1961 0 : case 6: /* current row */
1962 0 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(CURRENT_ROW);
1963 : break;
1964 4 : default:
1965 4 : if ((st = GDKinitialize_segment_tree())) {
1966 388 : COVARIANCE_AND_CORRELATION_ONE_SIDE_BRANCHES(OTHERS);
1967 : } else {
1968 0 : msg = createException(SQL, op, GDK_EXCEPTION);
1969 : }
1970 : }
1971 : }
1972 22 : BATsetcount(r, cnt);
1973 22 : r->tnonil = !has_nils;
1974 22 : r->tnil = has_nils;
1975 :
1976 22 : bailout:
1977 22 : bat_iterator_end(&di);
1978 22 : bat_iterator_end(&ei);
1979 22 : bat_iterator_end(&si);
1980 22 : bat_iterator_end(&oi);
1981 22 : bat_iterator_end(&pi);
1982 : }
1983 : } else {
1984 7 : dbl *res = getArgReference_dbl(stk, pci, 0);
1985 7 : ValRecord *input1 = &(stk)->stk[(pci)->argv[1]];
1986 7 : ValRecord *input2 = &(stk)->stk[(pci)->argv[2]];
1987 :
1988 7 : switch (tp1) {
1989 7 : case TYPE_bte:
1990 : case TYPE_sht:
1991 : case TYPE_int:
1992 : case TYPE_lng:
1993 : #ifdef HAVE_HGE
1994 : case TYPE_hge:
1995 : #endif
1996 : case TYPE_flt:
1997 : case TYPE_dbl:
1998 7 : *res = (VALisnil(input1) || VALisnil(input2)) ? dbl_nil : single_case;
1999 7 : break;
2000 0 : default:
2001 0 : msg = createException(SQL, op, SQLSTATE(42000) "%s not available for %s", op, ATOMname(tp1));
2002 : }
2003 : }
2004 :
2005 150 : bailout1:
2006 150 : BBPreclaim(st);
2007 150 : unfix_inputs(6, b, c, p, o, s, e);
2008 150 : finalize_output(res, r, msg);
2009 150 : return msg;
2010 : }
2011 :
2012 : str
2013 46 : SQLcovar_samp(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2014 : {
2015 46 : return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.covariance", GDKanalytical_covariance_samp, 1, 0.0f, dbl_nil);
2016 : }
2017 :
2018 : str
2019 44 : SQLcovar_pop(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2020 : {
2021 44 : return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.covariancep", GDKanalytical_covariance_pop, 0, 0.0f, 0.0f);
2022 : }
2023 :
2024 : str
2025 60 : SQLcorr(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2026 : {
2027 60 : return do_covariance_and_correlation(cntxt, mb, stk, pci, "sql.corr", GDKanalytical_correlation, 0, dbl_nil, dbl_nil);
2028 : }
2029 :
2030 : str
2031 49 : SQLstrgroup_concat(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
2032 : {
2033 49 : BAT *r = NULL, *b = NULL, *sep = NULL, *p = NULL, *o = NULL, *s = NULL, *e = NULL;
2034 49 : int separator_offset = 0, tpe, frame_type;
2035 49 : str msg = MAL_SUCCEED, separator = NULL;
2036 49 : bat *res = NULL;
2037 :
2038 49 : (void)cntxt;
2039 49 : if (pci->argc != 7 && pci->argc != 8)
2040 0 : throw(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT "sql.strgroup_concat requires 7 or 8 arguments");
2041 :
2042 49 : tpe = getArgType(mb, pci, 2);
2043 49 : if (isaBatType(tpe))
2044 30 : tpe = getBatType(tpe);
2045 49 : if (tpe == TYPE_str) /* there's a separator */
2046 : separator_offset = 1;
2047 : else
2048 7 : assert(tpe == TYPE_bit); /* otherwise it must be the partition's type */
2049 :
2050 49 : frame_type = *getArgReference_int(stk, pci, 4 + separator_offset);
2051 49 : assert(frame_type >= 0 && frame_type <= 6);
2052 :
2053 49 : if (isaBatType(getArgType(mb, pci, 1))) {
2054 45 : res = getArgReference_bat(stk, pci, 0);
2055 :
2056 45 : if (!(b = BATdescriptor(*getArgReference_bat(stk, pci, 1)))) {
2057 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2058 0 : goto bailout;
2059 : }
2060 45 : if (!(r = COLnew(b->hseqbase, TYPE_str, BATcount(b), TRANSIENT))) {
2061 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2062 0 : goto bailout;
2063 : }
2064 45 : if (separator_offset) {
2065 40 : if (isaBatType(getArgType(mb, pci, 2))) {
2066 30 : if (!(sep = BATdescriptor(*getArgReference_bat(stk, pci, 2)))) {
2067 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2068 0 : goto bailout;
2069 : }
2070 : } else
2071 10 : separator = *getArgReference_str(stk, pci, 2);
2072 : } else
2073 : separator = ",";
2074 :
2075 45 : if (isaBatType(getArgType(mb, pci, 2 + separator_offset)) && !(p = BATdescriptor(*getArgReference_bat(stk, pci, 2 + separator_offset)))) {
2076 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2077 0 : goto bailout;
2078 : }
2079 45 : if ((frame_type == 3 || frame_type == 4) && isaBatType(getArgType(mb, pci, 3 + separator_offset)) && !(o = BATdescriptor(*getArgReference_bat(stk, pci, 3 + separator_offset)))) {
2080 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2081 0 : goto bailout;
2082 : }
2083 45 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 5 + separator_offset)) && !(s = BATdescriptor(*getArgReference_bat(stk, pci, 5 + separator_offset)))) {
2084 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2085 0 : goto bailout;
2086 : }
2087 0 : if (frame_type < 3 && isaBatType(getArgType(mb, pci, 6 + separator_offset)) && !(e = BATdescriptor(*getArgReference_bat(stk, pci, 6 + separator_offset)))) {
2088 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2089 0 : goto bailout;
2090 : }
2091 45 : 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))) {
2092 0 : msg = createException(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT " Requires bats of identical size");
2093 0 : goto bailout;
2094 : }
2095 45 : if ((p && p->ttype != TYPE_bit) || (o && o->ttype != TYPE_bit) || (s && s->ttype != TYPE_oid) || (e && e->ttype != TYPE_oid)) {
2096 0 : msg = createException(SQL, "sql.strgroup_concat", ILLEGAL_ARGUMENT " p and o must be bit type and s and e must be oid");
2097 0 : goto bailout;
2098 : }
2099 :
2100 45 : assert((separator && !sep) || (!separator && sep)); /* only one of them must be set */
2101 45 : if (GDKanalytical_str_group_concat(r, p, o, b, sep, s, e, separator, frame_type) != GDK_SUCCEED)
2102 0 : msg = createException(SQL, "sql.strgroup_concat", GDK_EXCEPTION);
2103 : } else {
2104 4 : str *res = getArgReference_str(stk, pci, 0);
2105 4 : str in = *getArgReference_str(stk, pci, 1);
2106 :
2107 4 : if (strNil(in)) {
2108 3 : *res = GDKstrdup(str_nil);
2109 1 : } else if (separator_offset) {
2110 1 : str sep = *getArgReference_str(stk, pci, 2);
2111 1 : size_t l1 = strlen(in), l2 = strNil(sep) ? 0 : strlen(sep);
2112 :
2113 1 : if ((*res = GDKmalloc(l1+l2+1))) {
2114 1 : if (l1)
2115 1 : memcpy(*res, in, l1);
2116 1 : if (l2)
2117 0 : memcpy((*res)+l1, sep, l2);
2118 1 : (*res)[l1+l2] = '\0';
2119 : }
2120 : } else {
2121 0 : *res = GDKstrdup(in);
2122 : }
2123 4 : if (!*res)
2124 0 : msg = createException(SQL, "sql.strgroup_concat", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2125 : }
2126 :
2127 4 : bailout:
2128 49 : unfix_inputs(6, b, sep, p, o, s, e);
2129 49 : finalize_output(res, r, msg);
2130 49 : return msg;
2131 : }
|