Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * (c) Peter Boncz, Martin Kersten, Niels Nes, Sjoerd Mullender
15 : * BAT Algebra
16 : * This modules contains the most common algebraic BAT manipulation
17 : * commands. We call them algebra, because all operations take
18 : * values as parameters, and produce new result values, but
19 : * do not modify their parameters.
20 : *
21 : * Unlike the previous Monet versions, we reduce the number
22 : * of functions returning a BAT reference. This was previously needed
23 : * to simplify recursive bat-expression and manage reference counts.
24 : * In the current version we return only a BAT identifier when a new
25 : * bat is being created.
26 : *
27 : * All parameters to the modules are passed by reference.
28 : * In particular, this means that
29 : * string values are passed to the module layer as (str *)
30 : * and we have to de-reference them before entering the gdk library.
31 : * This calls for knowledge on the underlying BAT typs`s
32 : */
33 : #define derefStr(b, v) \
34 : do { \
35 : int _tpe= ATOMstorage((b)->ttype); \
36 : if (_tpe >= TYPE_str) { \
37 : if ((v) == 0 || *(str*) (v) == 0) \
38 : (v) = (str) str_nil; \
39 : else \
40 : (v) = *(str *) (v); \
41 : } \
42 : } while (0)
43 :
44 : #include "monetdb_config.h"
45 : #include "algebra.h"
46 :
47 : /*
48 : * Command Implementations in C
49 : * This module contains just a wrapper implementations; since all described
50 : * operations are part of the GDK kernel.
51 : *
52 : * BAT sum operation
53 : * The sum aggregate only works for int and float fields.
54 : * The routines below assumes that the caller knows what type
55 : * is large enough to prevent overflow.
56 : */
57 :
58 : static gdk_return
59 2393 : CMDgen_group(BAT **result, BAT *gids, BAT *cnts)
60 : {
61 2393 : BUN j;
62 2393 : BATiter gi = bat_iterator(gids);
63 2393 : BAT *r = COLnew(0, TYPE_oid, gi.count * 2, TRANSIENT);
64 :
65 2393 : if (r == NULL) {
66 0 : bat_iterator_end(&gi);
67 0 : return GDK_FAIL;
68 : }
69 2393 : BATiter ci = bat_iterator(cnts);
70 2393 : if (gi.type == TYPE_void) {
71 1054 : oid id = gi.tseq;
72 1054 : lng *cnt = (lng *) ci.base;
73 96216 : for (j = 0; j < gi.count; j++) {
74 95162 : lng i, sz = cnt[j];
75 190261 : for (i = 0; i < sz; i++) {
76 95099 : if (BUNappend(r, &id, false) != GDK_SUCCEED) {
77 0 : BBPreclaim(r);
78 0 : bat_iterator_end(&ci);
79 0 : bat_iterator_end(&gi);
80 0 : return GDK_FAIL;
81 : }
82 : }
83 95162 : id ++;
84 : }
85 : } else {
86 1339 : oid *id = (oid *) gi.base;
87 1339 : lng *cnt = (lng *) ci.base;
88 140494 : for (j = 0; j < gi.count; j++) {
89 139155 : lng i, sz = cnt[j];
90 274814 : for (i = 0; i < sz; i++) {
91 135659 : if (BUNappend(r, id, false) != GDK_SUCCEED) {
92 0 : BBPreclaim(r);
93 0 : bat_iterator_end(&ci);
94 0 : bat_iterator_end(&gi);
95 0 : return GDK_FAIL;
96 : }
97 : }
98 139155 : id ++;
99 : }
100 : }
101 2393 : bat_iterator_end(&ci);
102 2393 : r->tkey = false;
103 2393 : r->tseqbase = oid_nil;
104 2393 : r->tsorted = gi.sorted;
105 2393 : r->trevsorted = gi.revsorted;
106 2393 : r->tnonil = gi.nonil;
107 2393 : bat_iterator_end(&gi);
108 2393 : *result = r;
109 2393 : return GDK_SUCCEED;
110 : }
111 :
112 :
113 : static gdk_return
114 6 : slice(BAT **retval, BAT *b, lng start, lng end)
115 : {
116 : /* the internal BATslice requires exclusive end */
117 6 : if (start < 0) {
118 0 : GDKerror("start position of slice should >= 0\n");
119 0 : return GDK_FAIL;
120 : }
121 6 : if (is_lng_nil(end))
122 3 : end = BATcount(b);
123 :
124 6 : return (*retval = BATslice(b, (BUN) start, (BUN) end + 1)) ? GDK_SUCCEED : GDK_FAIL;
125 : }
126 :
127 : /*
128 : *
129 : * The remainder of this file contains the wrapper around the V4 code base
130 : * The BAT identifiers passed through this module may indicate
131 : * that the 'reverse' view applies. This should be taken into
132 : * account while resolving them.
133 : *
134 : * The sum aggregate only works for int and float fields.
135 : * The routines below assumes that the caller knows what type
136 : * is large enough to prevent overflow.
137 : */
138 :
139 : static str
140 779 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 779 : BAT *b;
143 779 : ptr p;
144 779 : str msg = MAL_SUCCEED;
145 :
146 779 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
147 0 : throw(MAL, "algebra.min", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 :
149 780 : if (!ATOMlinear(b->ttype)) {
150 0 : msg = createException(MAL, "algebra.min",
151 : "atom '%s' cannot be ordered linearly",
152 : ATOMname(b->ttype));
153 : } else {
154 780 : if (ATOMextern(b->ttype)) {
155 42 : *(ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil);
156 : } else {
157 738 : p = BATmin_skipnil(b, result, *skipnil);
158 739 : if (p != result)
159 0 : msg = createException(MAL, "algebra.min",
160 : SQLSTATE(HY002) "INTERNAL ERROR");
161 : }
162 781 : if (msg == MAL_SUCCEED && p == NULL)
163 0 : msg = createException(MAL, "algebra.min", GDK_EXCEPTION);
164 : }
165 781 : BBPunfix(b->batCacheid);
166 781 : return msg;
167 : }
168 :
169 : static str
170 779 : ALGminany(ptr result, const bat *bid)
171 : {
172 779 : bit skipnil = TRUE;
173 779 : return ALGminany_skipnil(result, bid, &skipnil);
174 : }
175 :
176 : static str
177 550 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 550 : BAT *b;
180 550 : ptr p;
181 550 : str msg = MAL_SUCCEED;
182 :
183 550 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 552 : if (!ATOMlinear(b->ttype)) {
187 0 : msg = createException(MAL, "algebra.max",
188 : "atom '%s' cannot be ordered linearly",
189 : ATOMname(b->ttype));
190 : } else {
191 552 : if (ATOMextern(b->ttype)) {
192 68 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 484 : p = BATmax_skipnil(b, result, *skipnil);
195 484 : if (p != result)
196 0 : msg = createException(MAL, "algebra.max",
197 : SQLSTATE(HY002) "INTERNAL ERROR");
198 : }
199 551 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 551 : BBPunfix(b->batCacheid);
203 551 : return msg;
204 : }
205 :
206 : static str
207 550 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 550 : bit skipnil = TRUE;
210 550 : return ALGmaxany_skipnil(result, bid, &skipnil);
211 : }
212 :
213 : static str
214 2393 : ALGgroupby(bat *res, const bat *gids, const bat *cnts)
215 : {
216 2393 : BAT *bn, *g, *c;
217 :
218 2393 : g = BATdescriptor(*gids);
219 2393 : if (g == NULL) {
220 0 : throw(MAL, "algebra.groupby", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
221 : }
222 2393 : c = BATdescriptor(*cnts);
223 2393 : if (c == NULL) {
224 0 : BBPunfix(g->batCacheid);
225 0 : throw(MAL, "algebra.groupby", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
226 : }
227 2393 : if (CMDgen_group(&bn, g, c) != GDK_SUCCEED) {
228 0 : BBPunfix(g->batCacheid);
229 0 : BBPunfix(c->batCacheid);
230 0 : throw(MAL, "algebra.groupby", GDK_EXCEPTION);
231 : }
232 2393 : *res = bn->batCacheid;
233 2393 : BBPkeepref(bn);
234 2393 : BBPunfix(g->batCacheid);
235 2393 : BBPunfix(c->batCacheid);
236 2393 : return MAL_SUCCEED;
237 : }
238 :
239 : static str
240 1 : ALGcard(lng *result, const bat *bid)
241 : {
242 1 : BAT *b, *en;
243 :
244 1 : if ((b = BATdescriptor(*bid)) == NULL) {
245 0 : throw(MAL, "algebra.card", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
246 : }
247 1 : en = BATunique(b, NULL);
248 1 : BBPunfix(b->batCacheid);
249 1 : if (en == NULL) {
250 0 : throw(MAL, "algebra.card", GDK_EXCEPTION);
251 : }
252 1 : struct canditer ci;
253 1 : canditer_init(&ci, NULL, en);
254 1 : *result = (lng) ci.ncand;
255 1 : BBPunfix(en->batCacheid);
256 1 : return MAL_SUCCEED;
257 : }
258 :
259 : static str
260 137252 : ALGselect2nil(bat *result, const bat *bid, const bat *sid, const void *low,
261 : const void *high, const bit *li, const bit *hi, const bit *anti,
262 : const bit *unknown)
263 : {
264 137252 : BAT *b, *s = NULL, *bn;
265 :
266 137252 : if ((*li != 0 && *li != 1) ||
267 137252 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 :
271 137468 : if ((b = BATdescriptor(*bid)) == NULL) {
272 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
273 : }
274 138172 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
275 0 : BBPunfix(b->batCacheid);
276 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
277 : }
278 138195 : derefStr(b, low);
279 138195 : derefStr(b, high);
280 :
281 138195 : bool nanti = *anti, nli = *li, nhi = *hi;
282 :
283 : /* here we don't need open ended parts with nil */
284 138195 : if (!nanti && *unknown) {
285 1579 : const void *nilptr = ATOMnilptr(b->ttype);
286 1579 : if (nilptr) {
287 1579 : if (nli && ATOMcmp(b->ttype, low, nilptr) == 0) {
288 22 : low = high;
289 22 : nli = false;
290 : }
291 1576 : if (nhi && ATOMcmp(b->ttype, high, nilptr) == 0) {
292 24 : high = low;
293 24 : nhi = false;
294 : }
295 1577 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
296 14 : nanti = true;
297 : }
298 136616 : } else if (!*unknown) {
299 130337 : const void *nilptr = ATOMnilptr(b->ttype);
300 260380 : if (nli && nhi && nilptr != NULL &&
301 130399 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
302 24 : ATOMcmp(b->ttype, high, nilptr) == 0) {
303 : /* special case: equi-select for NIL */
304 137866 : high = NULL;
305 : }
306 : }
307 :
308 137866 : bn = BATselect(b, s, low, high, nli, nhi, nanti, false);
309 136818 : BBPunfix(b->batCacheid);
310 138151 : BBPreclaim(s);
311 138054 : if (bn == NULL)
312 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
313 138054 : *result = bn->batCacheid;
314 138054 : BBPkeepref(bn);
315 138054 : return MAL_SUCCEED;
316 : }
317 :
318 : static str
319 40846 : ALGselect2(bat *result, const bat *bid, const bat *sid, const void *low,
320 : const void *high, const bit *li, const bit *hi, const bit *anti)
321 : {
322 40846 : return ALGselect2nil(result, bid, sid, low, high, li, hi, anti, &(bit){0});
323 : }
324 :
325 : static str
326 88964 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
327 : const bit *li, const bit *hi, const bit *anti)
328 : {
329 88964 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, &(bit){0});
330 : }
331 :
332 : static str
333 309 : ALGselect1nil(bat *result, const bat *bid, const void *low, const void *high,
334 : const bit *li, const bit *hi, const bit *anti, const bit *unknown)
335 : {
336 309 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown);
337 : }
338 :
339 : static str
340 526443 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
341 : const char **op)
342 : {
343 526443 : BAT *b, *s = NULL, *bn;
344 :
345 526443 : if ((b = BATdescriptor(*bid)) == NULL) {
346 0 : throw(MAL, "algebra.thetaselect",
347 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
348 : }
349 528682 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
350 0 : BBPunfix(b->batCacheid);
351 0 : throw(MAL, "algebra.thetaselect",
352 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
353 : }
354 528947 : derefStr(b, val);
355 528947 : bn = BATthetaselect(b, s, val, *op);
356 526336 : BBPunfix(b->batCacheid);
357 528565 : BBPreclaim(s);
358 528602 : if (bn == NULL)
359 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
360 528602 : *result = bn->batCacheid;
361 528602 : BBPkeepref(bn);
362 528602 : return MAL_SUCCEED;
363 : }
364 :
365 : static str
366 396 : ALGmarkselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
367 : {
368 396 : BAT *g = BATdescriptor(*gid); /* oid */
369 396 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
370 396 : BAT *p = BATdescriptor(*pid); /* bit */
371 396 : BAT *res1 = NULL, *res2 = NULL;
372 396 : bit any = *Any; /* any or normal comparison semantics */
373 :
374 396 : if (!g || !m || !p) {
375 0 : if (g) BBPreclaim(g);
376 0 : if (m) BBPreclaim(m);
377 0 : if (p) BBPreclaim(p);
378 0 : throw(MAL, "algebra.markselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
379 : }
380 396 : BUN nr = BATcount(g), q = 0;
381 :
382 396 : if ((res1 = COLnew(0, TYPE_oid, nr, TRANSIENT)) == NULL || (res2 = COLnew(0, TYPE_bit, nr, TRANSIENT)) == NULL) {
383 : BBPreclaim(g);
384 0 : BBPreclaim(m);
385 0 : BBPreclaim(p);
386 0 : if (res1) BBPreclaim(res1);
387 0 : throw(MAL, "algebra.markselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
388 : }
389 396 : assert(g->tsorted);
390 396 : oid *ri1 = Tloc(res1, 0);
391 396 : bit *ri2 = Tloc(res2, 0);
392 396 : bit *mi = Tloc(m, 0);
393 396 : bit *pi = Tloc(p, 0);
394 396 : oid cur = oid_nil;
395 :
396 396 : if (g->ttype == TYPE_void) { /* void case ? */
397 31 : oid c = g->hseqbase;
398 127 : for (BUN n = 0; n < nr; n++, c++) {
399 96 : ri1[q] = c;
400 96 : ri2[q] = FALSE;
401 96 : if (pi[n] == TRUE && mi[n] == TRUE)
402 7 : ri2[q] = TRUE;
403 89 : else if ((mi[n] == bit_nil && pi[n] != bit_nil && !any) || (mi[n] != FALSE && pi[n] == bit_nil && any))
404 7 : ri2[q] = bit_nil;
405 96 : q++;
406 : }
407 : } else {
408 365 : oid *gi = Tloc(g, 0);
409 365 : oid c = g->hseqbase;
410 365 : if (nr)
411 365 : cur = gi[0];
412 : bit m = FALSE;
413 : bool has_nil = false;
414 332661 : for (BUN n = 0; n < nr; n++, c++) {
415 332296 : if (c && cur != gi[n]) {
416 57735 : ri1[q] = c-1;
417 57735 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
418 57735 : q++;
419 57735 : cur = gi[n];
420 57735 : m = FALSE;
421 57735 : has_nil = false;
422 : }
423 332296 : if (m == TRUE)
424 191843 : continue;
425 :
426 140453 : if (pi[n] == TRUE && mi[n] == TRUE)
427 : m = TRUE;
428 133526 : else if ((mi[n] == bit_nil && pi[n] != bit_nil && !any) || (mi[n] != FALSE && pi[n] == bit_nil && any))
429 332296 : has_nil = true;
430 : }
431 365 : if (nr) {
432 365 : ri1[q] = c-1;
433 365 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
434 : }
435 365 : q++;
436 : }
437 396 : BATsetcount(res1, q);
438 396 : BATsetcount(res2, q);
439 396 : res1->tsorted = true;
440 396 : res1->tkey = true;
441 396 : res1->trevsorted = false;
442 396 : res2->tsorted = false;
443 396 : res2->trevsorted = false;
444 396 : res1->tnil = false;
445 396 : res1->tnonil = true;
446 396 : res2->tnonil = false;
447 396 : res2->tkey = false;
448 :
449 396 : BBPreclaim(g);
450 396 : BBPreclaim(m);
451 396 : BBPreclaim(p);
452 :
453 396 : BBPkeepref(res1);
454 396 : BBPkeepref(res2);
455 396 : *r1 = res1->batCacheid;
456 396 : *r2 = res2->batCacheid;
457 396 : return MAL_SUCCEED;
458 : }
459 :
460 : static str
461 38 : ALGouterselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
462 : {
463 38 : BAT *g = BATdescriptor(*gid); /* oid */
464 38 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
465 38 : BAT *p = BATdescriptor(*pid); /* bit */
466 38 : BAT *res1 = NULL, *res2 = NULL;
467 38 : bit any = *Any; /* any or normal comparison semantics */
468 :
469 38 : if (!g || !m || !p) {
470 0 : if (g) BBPreclaim(g);
471 0 : if (m) BBPreclaim(m);
472 0 : if (p) BBPreclaim(p);
473 0 : throw(MAL, "algebra.outerselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
474 : }
475 38 : BUN nr = BATcount(g), q = 0;
476 :
477 38 : if ((res1 = COLnew(0, TYPE_oid, nr, TRANSIENT)) == NULL || (res2 = COLnew(0, TYPE_bit, nr, TRANSIENT)) == NULL) {
478 : BBPreclaim(g);
479 0 : BBPreclaim(m);
480 0 : BBPreclaim(p);
481 0 : if (res1) BBPreclaim(res1);
482 0 : throw(MAL, "algebra.outerselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
483 : }
484 38 : assert(g->tsorted);
485 38 : oid *ri1 = Tloc(res1, 0);
486 38 : bit *ri2 = Tloc(res2, 0);
487 38 : bit *mi = Tloc(m, 0);
488 38 : bit *pi = Tloc(p, 0);
489 38 : oid cur = oid_nil;
490 :
491 38 : if (g->ttype == TYPE_void) { /* void case ? */
492 12 : oid c = g->hseqbase;
493 101 : for (BUN n = 0; n < nr; n++, c++) {
494 89 : ri1[q] = c;
495 161 : ri2[q] = (any && (mi[n] == bit_nil || pi[n] == bit_nil))?bit_nil:(mi[n] == TRUE && pi[n] == TRUE)?TRUE:FALSE;
496 89 : q++;
497 : }
498 : } else {
499 26 : oid *gi = Tloc(g, 0);
500 26 : oid c = g->hseqbase;
501 26 : if (nr)
502 26 : cur = gi[0];
503 : bool used = false;
504 602 : for (BUN n = 0; n < nr; n++, c++) {
505 576 : if (c && cur != gi[n]) {
506 159 : if (!used) {
507 3 : ri1[q] = c-1;
508 3 : ri2[q] = false;
509 3 : q++;
510 : }
511 159 : used = false;
512 159 : cur = gi[n];
513 : }
514 576 : if (mi[n] == TRUE && pi[n] == TRUE) {
515 322 : ri1[q] = c;
516 322 : ri2[q] = TRUE;
517 322 : used = true;
518 322 : q++;
519 254 : } else if (mi[n] == FALSE) { /* empty */
520 55 : ri1[q] = c;
521 55 : ri2[q] = FALSE;
522 55 : used = true;
523 55 : q++;
524 199 : } else if (any && (mi[n] == bit_nil /* ie has nil */ || pi[n] == bit_nil)) {
525 6 : ri1[q] = c;
526 6 : ri2[q] = bit_nil;
527 6 : used = true;
528 6 : q++;
529 : }
530 : }
531 26 : if (nr && !used) {
532 1 : ri1[q] = c-1;
533 1 : ri2[q] = FALSE;
534 1 : q++;
535 : }
536 : }
537 38 : BATsetcount(res1, q);
538 38 : BATsetcount(res2, q);
539 38 : res1->tsorted = true;
540 38 : res1->tkey = true;
541 38 : res1->trevsorted = false;
542 38 : res2->tsorted = false;
543 38 : res2->trevsorted = false;
544 38 : res1->tnil = false;
545 38 : res1->tnonil = true;
546 38 : res2->tnonil = false;
547 38 : res2->tkey = false;
548 :
549 38 : BBPreclaim(g);
550 38 : BBPreclaim(m);
551 38 : BBPreclaim(p);
552 :
553 38 : BBPkeepref(res1);
554 38 : BBPkeepref(res2);
555 38 : *r1 = res1->batCacheid;
556 38 : *r2 = res2->batCacheid;
557 38 : return MAL_SUCCEED;
558 : }
559 :
560 :
561 : static str
562 1583 : ALGselectNotNil(bat *result, const bat *bid)
563 : {
564 1583 : BAT *b;
565 :
566 1583 : if ((b = BATdescriptor(*bid)) == NULL)
567 0 : throw(MAL, "algebra.selectNotNil",
568 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
569 :
570 1584 : MT_lock_set(&b->theaplock);
571 1584 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
572 1584 : MT_lock_unset(&b->theaplock);
573 1584 : if (!bnonil) {
574 123 : BAT *s;
575 123 : s = BATselect(b, NULL, ATOMnilptr(b->ttype), NULL, true, true, true, false);
576 123 : if (s) {
577 123 : BAT *bn = BATproject(s, b);
578 123 : BBPunfix(s->batCacheid);
579 123 : if (bn) {
580 123 : BBPunfix(b->batCacheid);
581 123 : *result = bn->batCacheid;
582 123 : BBPkeepref(bn);
583 123 : return MAL_SUCCEED;
584 : }
585 : }
586 0 : BBPunfix(b->batCacheid);
587 0 : throw(MAL, "algebra.selectNotNil", GDK_EXCEPTION);
588 : }
589 : /* just pass on the result */
590 1461 : *result = b->batCacheid;
591 1461 : BBPkeepref(b);
592 1461 : return MAL_SUCCEED;
593 : }
594 :
595 : static str
596 647738 : do_join(bat *r1, bat *r2, bat *r3, const bat *lid, const bat *rid, const bat *r2id, const bat *slid, const bat *srid, int op, const void *c1, const void *c2, bool li, bool hi, bool anti, bool symmetric, /* these two only for rangejoin */
597 : const bit *nil_matches, const bit *not_in, const bit *max_one,
598 : const lng *estimate,
599 : gdk_return (*joinfunc)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *,
600 : bool, BUN),
601 : gdk_return (*semifunc)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *,
602 : bool, bool, BUN),
603 : gdk_return (*markfunc)(BAT **, BAT **, BAT **,
604 : BAT *, BAT *, BAT *, BAT *, BUN),
605 : gdk_return (*thetafunc)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *,
606 : int, bool, BUN),
607 : gdk_return (*bandfunc)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *,
608 : const void *, const void *, bool, bool, BUN),
609 : gdk_return (*rangefunc)(BAT **, BAT **, BAT *, BAT *, BAT *,
610 : BAT *, BAT *, bool, bool, bool, bool, BUN),
611 : BAT * (*difffunc)(BAT *, BAT *, BAT *, BAT *, bool, bool, BUN),
612 : BAT * (*interfunc)(BAT *, BAT *, BAT *, BAT *, bool, bool, BUN),
613 : const char *funcname)
614 : {
615 647738 : BAT *left = NULL, *right = NULL, *right2 = NULL;
616 647738 : BAT *candleft = NULL, *candright = NULL;
617 647738 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
618 647738 : BUN est;
619 647738 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
620 :
621 647738 : assert(r2id == NULL || rangefunc != NULL);
622 :
623 647738 : if ((left = BATdescriptor(*lid)) == NULL)
624 0 : goto fail;
625 654558 : if ((right = BATdescriptor(*rid)) == NULL)
626 0 : goto fail;
627 654487 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
628 0 : goto fail;
629 654494 : if (srid && !is_bat_nil(*srid)
630 0 : && (candright = BATdescriptor(*srid)) == NULL)
631 0 : goto fail;
632 654494 : if (estimate == NULL || *estimate < 0 || is_lng_nil(*estimate)
633 0 : || *estimate > (lng) BUN_MAX)
634 : est = BUN_NONE;
635 : else
636 0 : est = (BUN) *estimate;
637 :
638 654494 : err = NULL; /* most likely error now is GDK_EXCEPTION */
639 :
640 654494 : if (thetafunc) {
641 51324 : assert(joinfunc == NULL);
642 51324 : assert(semifunc == NULL);
643 51324 : assert(markfunc == NULL);
644 51324 : assert(bandfunc == NULL);
645 51324 : assert(rangefunc == NULL);
646 51324 : assert(difffunc == NULL);
647 51324 : assert(interfunc == NULL);
648 51324 : if ((*thetafunc)
649 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
650 51324 : op, *nil_matches, est) != GDK_SUCCEED)
651 0 : goto fail;
652 603170 : } else if (joinfunc) {
653 413132 : assert(semifunc == NULL);
654 413132 : assert(markfunc == NULL);
655 413132 : assert(bandfunc == NULL);
656 413132 : assert(rangefunc == NULL);
657 413132 : assert(difffunc == NULL);
658 413132 : assert(interfunc == NULL);
659 413132 : if ((*joinfunc)
660 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
661 413132 : *nil_matches, est) != GDK_SUCCEED)
662 1 : goto fail;
663 190038 : } else if (semifunc) {
664 332 : assert(markfunc == NULL);
665 332 : assert(bandfunc == NULL);
666 332 : assert(rangefunc == NULL);
667 332 : assert(difffunc == NULL);
668 332 : assert(interfunc == NULL);
669 332 : if ((*semifunc)
670 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
671 332 : *nil_matches, *max_one, est) != GDK_SUCCEED)
672 42 : goto fail;
673 189706 : } else if (markfunc) {
674 19366 : assert(bandfunc == NULL);
675 19366 : assert(rangefunc == NULL);
676 19366 : assert(difffunc == NULL);
677 19366 : assert(interfunc == NULL);
678 38727 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
679 : left, right, candleft, candright, est) != GDK_SUCCEED)
680 0 : goto fail;
681 170340 : } else if (bandfunc) {
682 0 : assert(rangefunc == NULL);
683 0 : assert(difffunc == NULL);
684 0 : assert(interfunc == NULL);
685 0 : if ((*bandfunc)
686 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
687 : c1, c2, li, hi, est) != GDK_SUCCEED)
688 0 : goto fail;
689 170340 : } else if (rangefunc) {
690 147 : assert(difffunc == NULL);
691 147 : assert(interfunc == NULL);
692 147 : if ((right2 = BATdescriptor(*r2id)) == NULL) {
693 0 : err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
694 0 : goto fail;
695 : }
696 172 : if ((*rangefunc)
697 : (&result1, r2 ? &result2 : NULL, left, right, right2, candleft,
698 : candright, li, hi, anti, symmetric, est) != GDK_SUCCEED)
699 0 : goto fail;
700 144 : BBPunfix(right2->batCacheid);
701 170193 : } else if (difffunc) {
702 160548 : assert(r2 == NULL);
703 160548 : assert(interfunc == NULL);
704 160253 : if ((result1 = (*difffunc) (left, right, candleft, candright,
705 160548 : *nil_matches, *not_in, est)) == NULL)
706 0 : goto fail;
707 : } else {
708 9645 : assert(r2 == NULL);
709 9619 : if ((result1 = (*interfunc) (left, right, candleft, candright,
710 9645 : *nil_matches, *max_one, est)) == NULL)
711 1 : goto fail;
712 : }
713 650159 : *r1 = result1->batCacheid;
714 650159 : BBPkeepref(result1);
715 652538 : if (r2) {
716 376927 : *r2 = result2->batCacheid;
717 376927 : BBPkeepref(result2);
718 : }
719 653361 : if (r3) {
720 19317 : *r3 = result3->batCacheid;
721 19317 : BBPkeepref(result3);
722 : }
723 653391 : BBPunfix(left->batCacheid);
724 654028 : BBPunfix(right->batCacheid);
725 654494 : BBPreclaim(candleft);
726 654515 : BBPreclaim(candright);
727 : return MAL_SUCCEED;
728 :
729 44 : fail:
730 44 : BBPreclaim(left);
731 44 : BBPreclaim(right);
732 44 : BBPreclaim(right2);
733 44 : BBPreclaim(candleft);
734 44 : BBPreclaim(candright);
735 44 : if (err == NULL)
736 44 : throw(MAL, funcname, GDK_EXCEPTION);
737 0 : throw(MAL, funcname, "%s", err);
738 : }
739 :
740 : static str
741 366042 : ALGjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid,
742 : const bat *srid, const bit *nil_matches, const lng *estimate)
743 : {
744 366042 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
745 : false, false, false, false, nil_matches, NULL, NULL,
746 : estimate, BATjoin, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
747 : "algebra.join");
748 : }
749 :
750 : static str
751 43372 : ALGjoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid,
752 : const bat *srid, const bit *nil_matches, const lng *estimate)
753 : {
754 43372 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
755 : false, false, false, false, nil_matches, NULL, NULL,
756 : estimate, BATjoin, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
757 : "algebra.join");
758 : }
759 :
760 : static str
761 645 : ALGleftjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid,
762 : const bat *srid, const bit *nil_matches, const lng *estimate)
763 : {
764 645 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
765 : false, false, false, false, nil_matches, NULL, NULL,
766 : estimate, BATleftjoin, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
767 : "algebra.leftjoin");
768 : }
769 :
770 : static str
771 0 : ALGleftjoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid,
772 : const bat *srid, const bit *nil_matches, const lng *estimate)
773 : {
774 0 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
775 : false, false, false, false, nil_matches, NULL, NULL,
776 : estimate, BATleftjoin, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
777 : "algebra.leftjoin");
778 : }
779 :
780 : static str
781 119 : ALGouterjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid,
782 : const bat *srid, const bit *nil_matches, const bit *match_one,
783 : const lng *estimate)
784 : {
785 119 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
786 : false, false, false, false, nil_matches, NULL, match_one,
787 : estimate, NULL, BATouterjoin, NULL, NULL, NULL, NULL, NULL, NULL,
788 : "algebra.outerjoin");
789 : }
790 :
791 : static str
792 0 : ALGouterjoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid,
793 : const bat *srid, const bit *nil_matches, const bit *match_one,
794 : const lng *estimate)
795 : {
796 0 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
797 : false, false, false, false, nil_matches, NULL, match_one,
798 : estimate, NULL, BATouterjoin, NULL, NULL, NULL, NULL, NULL, NULL,
799 : "algebra.outerjoin");
800 : }
801 :
802 : static str
803 209 : ALGsemijoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid,
804 : const bat *srid, const bit *nil_matches, const bit *max_one,
805 : const lng *estimate)
806 : {
807 209 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
808 : false, false, false, false, nil_matches, NULL, max_one,
809 : estimate, NULL, BATsemijoin, NULL, NULL, NULL, NULL, NULL, NULL,
810 : "algebra.semijoin");
811 : }
812 :
813 : static str
814 19269 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
815 : const bat *slid, const bat *srid, const lng *estimate)
816 : {
817 19269 : return do_join(r1, NULL, r3, lid, rid, NULL, slid, srid, 0, NULL, NULL,
818 : false, false, false, false, NULL, NULL, NULL,
819 : estimate, NULL, NULL, BATmarkjoin, NULL, NULL, NULL, NULL, NULL,
820 : "algebra.markjoin");
821 : }
822 :
823 : static str
824 5 : ALGmark3join(bat *r1, bat *r2, bat *r3, const bat *lid, const bat *rid,
825 : const bat *slid, const bat *srid, const lng *estimate)
826 : {
827 5 : return do_join(r1, r2, r3, lid, rid, NULL, slid, srid, 0, NULL, NULL,
828 : false, false, false, false, NULL, NULL, NULL,
829 : estimate, NULL, NULL, BATmarkjoin, NULL, NULL, NULL, NULL, NULL,
830 : "algebra.markjoin");
831 : }
832 :
833 : static str
834 7675 : ALGthetajoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid,
835 : const bat *srid, const int *op, const bit *nil_matches,
836 : const lng *estimate)
837 : {
838 7675 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, *op, NULL, NULL,
839 : false, false, false, false, nil_matches, NULL, NULL,
840 : estimate, NULL, NULL, NULL, BATthetajoin, NULL, NULL, NULL, NULL,
841 : "algebra.thetajoin");
842 : }
843 :
844 : static str
845 41386 : ALGthetajoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid,
846 : const bat *srid, const int *op, const bit *nil_matches,
847 : const lng *estimate)
848 : {
849 41386 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, *op, NULL, NULL,
850 : false, false, false, false, nil_matches, NULL, NULL,
851 : estimate, NULL, NULL, NULL, BATthetajoin, NULL, NULL, NULL, NULL,
852 : "algebra.thetajoin");
853 : }
854 :
855 : static str
856 0 : ALGbandjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid,
857 : const bat *srid, const void *c1, const void *c2, const bit *li,
858 : const bit *hi, const lng *estimate)
859 : {
860 0 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, 0, c1, c2,
861 0 : *li, *hi, false, false, NULL, NULL, NULL, estimate,
862 : NULL, NULL, NULL, NULL, BATbandjoin, NULL, NULL, NULL,
863 : "algebra.bandjoin");
864 : }
865 :
866 : static str
867 0 : ALGbandjoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid,
868 : const bat *srid, const void *c1, const void *c2, const bit *li,
869 : const bit *hi, const lng *estimate)
870 : {
871 0 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, 0, c1, c2,
872 0 : *li, *hi, false, false, NULL, NULL, NULL, estimate,
873 : NULL, NULL, NULL, NULL, BATbandjoin, NULL, NULL, NULL,
874 : "algebra.bandjoin");
875 : }
876 :
877 : static str
878 118 : ALGrangejoin(bat *r1, bat *r2, const bat *lid, const bat *rlid, const bat *rhid,
879 : const bat *slid, const bat *srid, const bit *li, const bit *hi,
880 : const bit *anti, const bit *symmetric, const lng *estimate)
881 : {
882 240 : return do_join(r1, r2, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
883 118 : *li, *hi, *anti, *symmetric, NULL, NULL, NULL, estimate,
884 : NULL, NULL, NULL, NULL, NULL, BATrangejoin, NULL, NULL,
885 : "algebra.rangejoin");
886 : }
887 :
888 : static str
889 22 : ALGrangejoin1(bat *r1, const bat *lid, const bat *rlid, const bat *rhid,
890 : const bat *slid, const bat *srid, const bit *li, const bit *hi,
891 : const bit *anti, const bit *symmetric, const lng *estimate)
892 : {
893 47 : return do_join(r1, NULL, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
894 22 : *li, *hi, *anti, *symmetric, NULL, NULL, NULL, estimate,
895 : NULL, NULL, NULL, NULL, NULL, BATrangejoin, NULL, NULL,
896 : "algebra.rangejoin");
897 : }
898 :
899 : static str
900 160398 : ALGdifference(bat *r1, const bat *lid, const bat *rid, const bat *slid,
901 : const bat *srid, const bit *nil_matches, const bit *not_in,
902 : const lng *estimate)
903 : {
904 160398 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
905 : false, false, false, false, nil_matches, not_in, NULL,
906 : estimate, NULL, NULL, NULL, NULL, NULL, NULL, BATdiff, NULL,
907 : "algebra.difference");
908 : }
909 :
910 : static str
911 9645 : ALGintersect(bat *r1, const bat *lid, const bat *rid, const bat *slid,
912 : const bat *srid, const bit *nil_matches, const bit *max_one,
913 : const lng *estimate)
914 : {
915 9645 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
916 : false, false, false, false, nil_matches, NULL, max_one,
917 : estimate, NULL, NULL, NULL, NULL, NULL, NULL, NULL, BATintersect,
918 : "algebra.intersect");
919 : }
920 :
921 : /* algebra.firstn(b:bat[:any],
922 : * [ s:bat[:oid],
923 : * [ g:bat[:oid], ] ]
924 : * n:lng,
925 : * asc:bit,
926 : * nilslast:bit,
927 : * distinct:bit)
928 : * returns :bat[:oid] [ , :bat[:oid] ]
929 : */
930 : static str
931 1713 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
932 : {
933 1713 : bat *ret1, *ret2 = NULL;
934 1713 : bat bid, sid, gid;
935 1713 : BAT *b, *s = NULL, *g = NULL;
936 1713 : BAT *bn = NULL, *gn = NULL;
937 1713 : lng n;
938 1713 : bit asc, nilslast, distinct;
939 1713 : gdk_return rc;
940 :
941 1713 : (void) cntxt;
942 1713 : (void) mb;
943 :
944 1713 : assert(pci->retc == 1 || pci->retc == 2);
945 1713 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
946 :
947 1713 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
948 1713 : if (n < 0)
949 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
950 1713 : if (n > (lng) BUN_MAX)
951 : n = BUN_MAX;
952 1713 : ret1 = getArgReference_bat(stk, pci, 0);
953 1713 : if (pci->retc == 2)
954 617 : ret2 = getArgReference_bat(stk, pci, 1);
955 1713 : bid = *getArgReference_bat(stk, pci, pci->retc);
956 1713 : if ((b = BATdescriptor(bid)) == NULL)
957 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
958 1719 : if (pci->argc - pci->retc > 5) {
959 1720 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
960 1720 : if (!is_bat_nil(sid) && (s = BATdescriptor(sid)) == NULL) {
961 0 : BBPunfix(bid);
962 0 : throw(MAL, "algebra.firstn",
963 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
964 : }
965 1721 : if (pci->argc - pci->retc > 6) {
966 1721 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
967 1721 : if (!is_bat_nil(gid) && (g = BATdescriptor(gid)) == NULL) {
968 0 : BBPunfix(bid);
969 0 : BBPunfix(sid);
970 0 : throw(MAL, "algebra.firstn",
971 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
972 : }
973 : }
974 : }
975 1720 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
976 1720 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
977 1720 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
978 2818 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
979 : distinct);
980 1710 : BBPunfix(b->batCacheid);
981 1720 : BBPreclaim(s);
982 1719 : BBPreclaim(g);
983 1720 : if (rc != GDK_SUCCEED)
984 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
985 1720 : *ret1 = bn->batCacheid;
986 1720 : BBPkeepref(bn);
987 1718 : if (ret2) {
988 621 : *ret2 = gn->batCacheid;
989 621 : BBPkeepref(gn);
990 : }
991 : return MAL_SUCCEED;
992 : }
993 :
994 : static str
995 6 : ALGgroupedfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
996 : {
997 6 : bat *ret;
998 6 : bat sid, gid;
999 6 : BAT *s = NULL, *g = NULL;
1000 6 : BAT *bn = NULL;
1001 6 : lng n;
1002 :
1003 6 : (void) cntxt;
1004 6 : (void) mb;
1005 :
1006 6 : n = *getArgReference_lng(stk, pci, 1);
1007 6 : if (n < 0)
1008 0 : throw(MAL, "algebra.groupedfirstn", ILLEGAL_ARGUMENT);
1009 6 : ret = getArgReference_bat(stk, pci, 0);
1010 6 : sid = *getArgReference_bat(stk, pci, 2);
1011 6 : gid = *getArgReference_bat(stk, pci, 3);
1012 6 : int nbats = pci->argc - 4;
1013 6 : if (nbats % 3 != 0)
1014 0 : throw(MAL, "algebra.groupedfirstn", ILLEGAL_ARGUMENT);
1015 6 : nbats /= 3;
1016 6 : BAT **bats = GDKmalloc(nbats * sizeof(BAT *));
1017 6 : bool *ascs = GDKmalloc(nbats * sizeof(bool));
1018 6 : bool *nlss = GDKmalloc(nbats * sizeof(bool));
1019 6 : if (bats == NULL || ascs == NULL || nlss == NULL) {
1020 0 : GDKfree(bats);
1021 0 : GDKfree(ascs);
1022 0 : GDKfree(nlss);
1023 0 : throw(MAL, "algebra.groupedfirstn", MAL_MALLOC_FAIL);
1024 : }
1025 6 : if (!is_bat_nil(sid) && (s = BATdescriptor(sid)) == NULL) {
1026 0 : GDKfree(bats);
1027 0 : GDKfree(ascs);
1028 0 : GDKfree(nlss);
1029 0 : throw(MAL, "algebra.groupedfirstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1030 : }
1031 6 : if (!is_bat_nil(gid) && (g = BATdescriptor(gid)) == NULL) {
1032 0 : BBPreclaim(s);
1033 0 : GDKfree(bats);
1034 0 : GDKfree(ascs);
1035 0 : GDKfree(nlss);
1036 0 : throw(MAL, "algebra.groupedfirstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1037 : }
1038 12 : for (int i = 0; i < nbats; i++) {
1039 6 : bats[i] = BATdescriptor(*getArgReference_bat(stk, pci, i * 3 + 4));
1040 6 : if (bats[i] == NULL) {
1041 0 : while (i > 0)
1042 0 : BBPreclaim(bats[--i]);
1043 0 : BBPreclaim(g);
1044 0 : BBPreclaim(s);
1045 0 : GDKfree(bats);
1046 0 : GDKfree(ascs);
1047 0 : GDKfree(nlss);
1048 0 : throw(MAL, "algebra.groupedfirstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1049 : }
1050 6 : ascs[i] = *getArgReference_bit(stk, pci, i * 3 + 5);
1051 6 : nlss[i] = *getArgReference_bit(stk, pci, i * 3 + 6);
1052 : }
1053 6 : bn = BATgroupedfirstn((BUN) n, s, g, nbats, bats, ascs, nlss);
1054 6 : BBPreclaim(s);
1055 6 : BBPreclaim(g);
1056 12 : for (int i = 0; i < nbats; i++)
1057 12 : BBPreclaim(bats[i]);
1058 6 : GDKfree(bats);
1059 6 : GDKfree(ascs);
1060 6 : GDKfree(nlss);
1061 6 : if (bn == NULL)
1062 0 : throw(MAL, "algebra.groupedfirstn", GDK_EXCEPTION);
1063 6 : *ret = bn->batCacheid;
1064 6 : BBPkeepref(bn);
1065 6 : return MAL_SUCCEED;
1066 : }
1067 :
1068 : static str
1069 9 : ALGunary(bat *result, const bat *bid, BAT *(*func)(BAT *), const char *name)
1070 : {
1071 9 : BAT *b, *bn;
1072 :
1073 9 : if ((b = BATdescriptor(*bid)) == NULL) {
1074 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1075 : }
1076 9 : bn = (*func) (b);
1077 9 : BBPunfix(b->batCacheid);
1078 9 : if (bn == NULL)
1079 0 : throw(MAL, name, GDK_EXCEPTION);
1080 9 : *result = bn->batCacheid;
1081 9 : BBPkeepref(bn);
1082 9 : return MAL_SUCCEED;
1083 : }
1084 :
1085 : static inline BAT *
1086 9 : BATwcopy(BAT *b)
1087 : {
1088 9 : return COLcopy(b, b->ttype, true, TRANSIENT);
1089 : }
1090 :
1091 : static str
1092 9 : ALGcopy(bat *result, const bat *bid)
1093 : {
1094 9 : return ALGunary(result, bid, BATwcopy, "algebra.copy");
1095 : }
1096 :
1097 : static str
1098 74 : ALGunique(bat *result, const bat *bid, const bat *sid)
1099 : {
1100 74 : BAT *b, *s = NULL, *bn = NULL;
1101 :
1102 74 : if ((b = BATdescriptor(*bid)) == NULL) {
1103 0 : throw(MAL, "algebra.unique", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1104 : }
1105 74 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
1106 0 : BBPunfix(b->batCacheid);
1107 0 : throw(MAL, "algebra.unique", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1108 : }
1109 74 : bn = BATunique(b, s);
1110 74 : BBPunfix(b->batCacheid);
1111 74 : BBPreclaim(s);
1112 74 : if (bn == NULL)
1113 0 : throw(MAL, "algebra.unique", GDK_EXCEPTION);
1114 74 : *result = bn->batCacheid;
1115 74 : BBPkeepref(bn);
1116 74 : return MAL_SUCCEED;
1117 : }
1118 :
1119 : static str
1120 45438 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1121 : const bat *slid, const bat *srid, const bit *max_one)
1122 : {
1123 45438 : BAT *L, *R, *bn1, *bn2 = NULL;
1124 45438 : BAT *sl = NULL, *sr = NULL;
1125 45438 : gdk_return ret;
1126 :
1127 45438 : L = BATdescriptor(*left);
1128 46909 : R = BATdescriptor(*right);
1129 46972 : if (L == NULL || R == NULL) {
1130 0 : BBPreclaim(L);
1131 0 : BBPreclaim(R);
1132 0 : throw(MAL, "algebra.crossproduct",
1133 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1134 : }
1135 46972 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1136 1 : (srid && !is_bat_nil(*srid) && (sr = BATdescriptor(*srid)) == NULL)) {
1137 0 : BBPunfix(L->batCacheid);
1138 0 : BBPunfix(R->batCacheid);
1139 0 : BBPreclaim(sl);
1140 : /* sr == NULL, so no need to unfix */
1141 0 : throw(MAL, "algebra.crossproduct",
1142 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1143 : }
1144 48779 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1145 46972 : max_one && !is_bit_nil(*max_one) && *max_one);
1146 46397 : BBPunfix(L->batCacheid);
1147 46901 : BBPunfix(R->batCacheid);
1148 46968 : BBPreclaim(sl);
1149 46970 : BBPreclaim(sr);
1150 46961 : if (ret != GDK_SUCCEED)
1151 86 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1152 46875 : *l = bn1->batCacheid;
1153 46875 : BBPkeepref(bn1);
1154 46829 : if (r) {
1155 45036 : *r = bn2->batCacheid;
1156 45036 : BBPkeepref(bn2);
1157 : }
1158 : return MAL_SUCCEED;
1159 : }
1160 :
1161 : static str
1162 1747 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1163 : {
1164 1747 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1165 : }
1166 :
1167 : static str
1168 43761 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1169 : const bit *max_one)
1170 : {
1171 43761 : return ALGcrossproduct(l, r, left, right, NULL, NULL, max_one);
1172 : }
1173 :
1174 : static str
1175 0 : ALGcrossproduct3(bat *l, bat *r, const bat *left, const bat *right,
1176 : const bat *sl, const bat *sr, const bit *max_one)
1177 : {
1178 0 : return ALGcrossproduct(l, r, left, right, sl, sr, max_one);
1179 : }
1180 :
1181 : static str
1182 0 : ALGcrossproduct4(bat *l, const bat *left, const bat *right, const bat *sl,
1183 : const bat *sr, const bit *max_one)
1184 : {
1185 0 : return ALGcrossproduct(l, NULL, left, right, sl, sr, max_one);
1186 : }
1187 :
1188 : static str
1189 425 : ALGoutercrossproduct3(bat *l, bat *r, const bat *left, const bat *right, const bat *slid, const bat *srid, const bit *max_one)
1190 : {
1191 425 : BAT *L, *R, *bn1, *bn2 = NULL;
1192 425 : BAT *sl = NULL, *sr = NULL;
1193 425 : gdk_return ret;
1194 :
1195 425 : L = BATdescriptor(*left);
1196 425 : R = BATdescriptor(*right);
1197 425 : if (L == NULL || R == NULL) {
1198 0 : BBPreclaim(L);
1199 0 : BBPreclaim(R);
1200 0 : throw(MAL, "algebra.crossproduct", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1201 : }
1202 425 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1203 425 : (srid && !is_bat_nil(*srid) && (sr = BATdescriptor(*srid)) == NULL)) {
1204 0 : BBPunfix(L->batCacheid);
1205 0 : BBPunfix(R->batCacheid);
1206 0 : BBPreclaim(sl);
1207 : /* sr == NULL, so no need to unfix */
1208 0 : throw(MAL, "algebra.crossproduct", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1209 : }
1210 425 : ret = BAToutercross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1211 425 : max_one && !is_bit_nil(*max_one) && *max_one);
1212 425 : BBPunfix(L->batCacheid);
1213 425 : BBPunfix(R->batCacheid);
1214 425 : BBPreclaim(sl);
1215 425 : BBPreclaim(sr);
1216 425 : if (ret != GDK_SUCCEED)
1217 0 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1218 425 : *l = bn1->batCacheid;
1219 425 : BBPkeepref(bn1);
1220 425 : if (r) {
1221 425 : *r = bn2->batCacheid;
1222 425 : BBPkeepref(bn2);
1223 : }
1224 : return MAL_SUCCEED;
1225 : }
1226 :
1227 : static str
1228 1989823 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1229 : {
1230 1989823 : BAT *l, *r1, *r2 = NULL, *bn;
1231 :
1232 1989823 : if ((l = BATdescriptor(*lid)) == NULL) {
1233 0 : throw(MAL, "algebra.projection",
1234 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1235 : }
1236 2002892 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1237 0 : BBPunfix(l->batCacheid);
1238 0 : throw(MAL, "algebra.projection",
1239 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1240 : }
1241 2001774 : if (r2id && !is_bat_nil(*r2id) && (r2 = BATdescriptor(*r2id)) == NULL) {
1242 0 : BBPunfix(l->batCacheid);
1243 0 : BBPunfix(r1->batCacheid);
1244 0 : throw(MAL, "algebra.projection",
1245 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1246 : }
1247 2001774 : bn = BATproject2(l, r1, r2);
1248 1976411 : BBPunfix(l->batCacheid);
1249 1999358 : BBPunfix(r1->batCacheid);
1250 2001789 : BBPreclaim(r2);
1251 2002017 : if (bn == NULL)
1252 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1253 2002017 : *result = bn->batCacheid;
1254 2002017 : BBPkeepref(bn);
1255 2002017 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : str
1259 1991801 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1260 : {
1261 1991801 : return ALGprojection2(result, lid, rid, NULL);
1262 : }
1263 :
1264 : static str
1265 24761 : ALGsort33(bat *result, bat *norder, bat *ngroup, const bat *bid,
1266 : const bat *order, const bat *group, const bit *reverse,
1267 : const bit *nilslast, const bit *stable)
1268 : {
1269 24761 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1270 24761 : BAT *b = NULL, *o = NULL, *g = NULL;
1271 :
1272 24761 : if ((b = BATdescriptor(*bid)) == NULL)
1273 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1274 24761 : if (order && !is_bat_nil(*order) && (o = BATdescriptor(*order)) == NULL) {
1275 0 : BBPunfix(b->batCacheid);
1276 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1277 : }
1278 24761 : if (group &&!is_bat_nil(*group) && (g = BATdescriptor(*group)) == NULL) {
1279 0 : BBPreclaim(o);
1280 0 : BBPunfix(b->batCacheid);
1281 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1282 : }
1283 28503 : if (BATsort(result ? &bn : NULL,
1284 : norder ? &on : NULL,
1285 : ngroup ? &gn : NULL,
1286 24761 : b, o, g, *reverse, *nilslast, *stable) != GDK_SUCCEED) {
1287 0 : BBPreclaim(o);
1288 0 : BBPreclaim(g);
1289 0 : BBPunfix(b->batCacheid);
1290 0 : throw(MAL, "algebra.sort", GDK_EXCEPTION);
1291 : }
1292 24759 : BBPunfix(b->batCacheid);
1293 24761 : BBPreclaim(o);
1294 24761 : BBPreclaim(g);
1295 24760 : if (result) {
1296 24760 : *result = bn->batCacheid;
1297 24760 : BBPkeepref(bn);
1298 : }
1299 24760 : if (norder) {
1300 21018 : *norder = on->batCacheid;
1301 21018 : BBPkeepref(on);
1302 : }
1303 24761 : if (ngroup) {
1304 14109 : *ngroup = gn->batCacheid;
1305 14109 : BBPkeepref(gn);
1306 : }
1307 : return MAL_SUCCEED;
1308 : }
1309 :
1310 : static str
1311 4306 : ALGsort32(bat *result, bat *norder, const bat *bid, const bat *order,
1312 : const bat *group, const bit *reverse, const bit *nilslast,
1313 : const bit *stable)
1314 : {
1315 4306 : return ALGsort33(result, norder, NULL, bid, order, group, reverse, nilslast,
1316 : stable);
1317 : }
1318 :
1319 : static str
1320 2078 : ALGsort31(bat *result, const bat *bid, const bat *order, const bat *group,
1321 : const bit *reverse, const bit *nilslast, const bit *stable)
1322 : {
1323 2078 : return ALGsort33(result, NULL, NULL, bid, order, group, reverse, nilslast,
1324 : stable);
1325 : }
1326 :
1327 : static str
1328 0 : ALGsort23(bat *result, bat *norder, bat *ngroup, const bat *bid,
1329 : const bat *order, const bit *reverse, const bit *nilslast,
1330 : const bit *stable)
1331 : {
1332 0 : return ALGsort33(result, norder, ngroup, bid, order, NULL, reverse,
1333 : nilslast, stable);
1334 : }
1335 :
1336 : static str
1337 0 : ALGsort22(bat *result, bat *norder, const bat *bid, const bat *order,
1338 : const bit *reverse, const bit *nilslast, const bit *stable)
1339 : {
1340 0 : return ALGsort33(result, norder, NULL, bid, order, NULL, reverse, nilslast,
1341 : stable);
1342 : }
1343 :
1344 : static str
1345 0 : ALGsort21(bat *result, const bat *bid, const bat *order, const bit *reverse,
1346 : const bit *nilslast, const bit *stable)
1347 : {
1348 0 : return ALGsort33(result, NULL, NULL, bid, order, NULL, reverse, nilslast,
1349 : stable);
1350 : }
1351 :
1352 : static str
1353 6639 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1354 : const bit *reverse, const bit *nilslast, const bit *stable)
1355 : {
1356 6639 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1357 : stable);
1358 : }
1359 :
1360 : static str
1361 2604 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1362 : const bit *nilslast, const bit *stable)
1363 : {
1364 2604 : return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast,
1365 : stable);
1366 : }
1367 :
1368 : static str
1369 1664 : ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast,
1370 : const bit *stable)
1371 : {
1372 1664 : return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast,
1373 : stable);
1374 : }
1375 :
1376 : static str
1377 71052 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1378 : const bit *ignore_nils)
1379 : {
1380 71052 : BAT *b, *s = NULL;
1381 :
1382 71052 : if ((b = BATdescriptor(*bid)) == NULL) {
1383 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1384 : }
1385 71232 : if (cnd && !is_bat_nil(*cnd) && (s = BATdescriptor(*cnd)) == NULL) {
1386 0 : BBPunfix(b->batCacheid);
1387 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1388 : }
1389 71232 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1390 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1391 71202 : } else if (*ignore_nils) {
1392 1770 : *result = (lng) BATcount_no_nil(b, s);
1393 : } else {
1394 69432 : struct canditer ci;
1395 69432 : canditer_init(&ci, b, s);
1396 69453 : *result = (lng) ci.ncand;
1397 : }
1398 71253 : BBPreclaim(s);
1399 71253 : BBPunfix(b->batCacheid);
1400 71253 : return MAL_SUCCEED;
1401 : }
1402 :
1403 : static str
1404 1770 : ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils)
1405 : {
1406 1770 : return ALGcountCND_nil(result, bid, NULL, ignore_nils);
1407 : }
1408 :
1409 : static str
1410 0 : ALGcountCND_bat(lng *result, const bat *bid, const bat *cnd)
1411 : {
1412 0 : return ALGcountCND_nil(result, bid, cnd, &(bit) { 0 });
1413 : }
1414 :
1415 : static str
1416 69272 : ALGcount_bat(lng *result, const bat *bid)
1417 : {
1418 69272 : return ALGcountCND_nil(result, bid, NULL, &(bit) { 0 });
1419 : }
1420 :
1421 : static str
1422 0 : ALGcountCND_no_nil(lng *result, const bat *bid, const bat *cnd)
1423 : {
1424 0 : return ALGcountCND_nil(result, bid, cnd, &(bit) { 1 });
1425 : }
1426 :
1427 : static str
1428 0 : ALGcount_no_nil(lng *result, const bat *bid)
1429 : {
1430 0 : return ALGcountCND_nil(result, bid, NULL, &(bit) { 1 });
1431 : }
1432 :
1433 : static str
1434 6 : ALGslice(bat *ret, const bat *bid, const lng *start, const lng *end)
1435 : {
1436 6 : BAT *b, *bn = NULL;
1437 :
1438 6 : if ((b = BATdescriptor(*bid)) == NULL) {
1439 0 : throw(MAL, "algebra.slice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1440 : }
1441 6 : if (slice(&bn, b, *start, *end) == GDK_SUCCEED) {
1442 6 : *ret = bn->batCacheid;
1443 6 : BBPkeepref(bn);
1444 6 : BBPunfix(b->batCacheid);
1445 6 : return MAL_SUCCEED;
1446 : }
1447 0 : BBPunfix(b->batCacheid);
1448 0 : throw(MAL, "algebra.slice", GDK_EXCEPTION);
1449 : }
1450 :
1451 : static str
1452 1 : ALGslice_int(bat *ret, const bat *bid, const int *start, const int *end)
1453 : {
1454 1 : lng s = *start;
1455 1 : lng e = (is_int_nil(*end) ? lng_nil : *end);
1456 :
1457 1 : return ALGslice(ret, bid, &s, &e);
1458 : }
1459 :
1460 : static str
1461 0 : ALGslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1462 : {
1463 0 : lng s = *start;
1464 0 : lng e = *end;
1465 :
1466 0 : return ALGslice(ret, bid, &s, &e);
1467 : }
1468 :
1469 : /* carve out a slice based on the OIDs */
1470 : /* beware that BATs may have different OID bases */
1471 : static str
1472 5 : ALGslice_oid(bat *ret, const bat *bid, const oid *start, const oid *end)
1473 : {
1474 5 : lng s = (lng) (is_oid_nil(*start) ? 0 : (lng) *start);
1475 5 : lng e = (is_oid_nil(*end) ? lng_nil : (lng) *end);
1476 :
1477 5 : return ALGslice(ret, bid, &s, &e);
1478 : }
1479 :
1480 : static str
1481 17093 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1482 : {
1483 17093 : BAT *b, *bn;
1484 17093 : BUN s, e;
1485 :
1486 17093 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1487 0 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1488 17095 : if ((b = BBPquickdesc(*bid)) == NULL)
1489 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1490 17094 : s = (BUN) *start;
1491 17094 : if (s > BATcount(b))
1492 : s = BATcount(b);
1493 17094 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1494 17094 : if (e > BATcount(b))
1495 : e = BATcount(b);
1496 17094 : if (e < s)
1497 : e = s;
1498 17094 : bn = BATdense(0, b->hseqbase + s, e - s);
1499 17093 : if (bn == NULL)
1500 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1501 17093 : *ret = bn->batCacheid;
1502 17093 : BBPkeepref(bn);
1503 17093 : return MAL_SUCCEED;
1504 : }
1505 :
1506 : /*
1507 : * BUN Get/Fetch
1508 : */
1509 :
1510 : static str
1511 185078 : doALGfetch(ptr ret, BAT *b, BUN pos)
1512 : {
1513 185078 : assert(pos <= BUN_MAX);
1514 185078 : BATiter bi = bat_iterator(b);
1515 185078 : if (ATOMextern(b->ttype)) {
1516 190 : ptr _src = BUNtail(bi, pos);
1517 190 : size_t _len = ATOMlen(b->ttype, _src);
1518 190 : ptr _dst = GDKmalloc(_len);
1519 190 : if (_dst == NULL) {
1520 0 : bat_iterator_end(&bi);
1521 0 : throw(MAL, "doAlgFetch", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1522 : }
1523 190 : memcpy(_dst, _src, _len);
1524 190 : *(ptr *) ret = _dst;
1525 : } else {
1526 184888 : size_t _s = ATOMsize(ATOMtype(b->ttype));
1527 184888 : if (b->ttype == TYPE_void) {
1528 0 : *(oid *) ret = b->tseqbase;
1529 0 : if (!is_oid_nil(b->tseqbase))
1530 0 : *(oid *) ret += pos;
1531 184888 : } else if (_s == 4) {
1532 184801 : *(int *) ret = ((int *) bi.base)[pos];
1533 : } else if (_s == 1) {
1534 11 : *(bte *) ret = ((bte *) bi.base)[pos];
1535 : } else if (_s == 2) {
1536 1 : *(sht *) ret = ((sht *) bi.base)[pos];
1537 : } else if (_s == 8) {
1538 75 : *(lng *) ret = ((lng *) bi.base)[pos];
1539 : #ifdef HAVE_HGE
1540 : } else if (_s == 16) {
1541 0 : *(hge *) ret = ((hge *) bi.base)[pos];
1542 : #endif
1543 : } else {
1544 0 : memcpy(ret, (const char *) bi.base + (pos << bi.shift), _s);
1545 : }
1546 : }
1547 185078 : bat_iterator_end(&bi);
1548 185078 : return MAL_SUCCEED;
1549 : }
1550 :
1551 : static str
1552 185080 : ALGfetch(ptr ret, const bat *bid, const lng *pos)
1553 : {
1554 185080 : BAT *b;
1555 185080 : str msg;
1556 :
1557 185080 : if ((b = BATdescriptor(*bid)) == NULL) {
1558 0 : throw(MAL, "algebra.fetch", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1559 : }
1560 185080 : if (*pos < (lng) 0) {
1561 0 : BBPunfix(b->batCacheid);
1562 0 : throw(MAL, "algebra.fetch",
1563 : ILLEGAL_ARGUMENT ": row index to fetch must be non negative\n");
1564 : }
1565 185080 : if (BATcount(b) == 0) {
1566 2 : BBPunfix(b->batCacheid);
1567 2 : throw(MAL, "algebra.fetch",
1568 : ILLEGAL_ARGUMENT
1569 : ": cannot fetch a single row from an empty input\n");
1570 : }
1571 185078 : if (*pos >= (lng) BATcount(b)) {
1572 0 : BBPunfix(b->batCacheid);
1573 0 : throw(MAL, "algebra.fetch",
1574 : ILLEGAL_ARGUMENT ": row index to fetch is out of range\n");
1575 : }
1576 185078 : msg = doALGfetch(ret, b, (BUN) *pos);
1577 185077 : BBPunfix(b->batCacheid);
1578 185077 : return msg;
1579 : }
1580 :
1581 : str
1582 185080 : ALGfetchoid(ptr ret, const bat *bid, const oid *pos)
1583 : {
1584 185080 : lng o = *pos;
1585 :
1586 185080 : return ALGfetch(ret, bid, &o);
1587 : }
1588 :
1589 : static str
1590 0 : ALGexist(bit *ret, const bat *bid, const void *val)
1591 : {
1592 0 : BAT *b;
1593 0 : BUN q;
1594 :
1595 0 : if ((b = BATdescriptor(*bid)) == NULL) {
1596 0 : throw(MAL, "algebra.exist", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1597 : }
1598 0 : derefStr(b, val);
1599 0 : q = BUNfnd(b, val);
1600 0 : *ret = (q != BUN_NONE);
1601 0 : BBPunfix(b->batCacheid);
1602 0 : return MAL_SUCCEED;
1603 : }
1604 :
1605 : static str
1606 9 : ALGfind(oid *ret, const bat *bid, ptr val)
1607 : {
1608 9 : BAT *b;
1609 9 : BUN q;
1610 9 : str msg = MAL_SUCCEED;
1611 :
1612 9 : if ((b = BATdescriptor(*bid)) == NULL) {
1613 0 : throw(MAL, "algebra.find", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1614 : }
1615 9 : derefStr(b, val);
1616 9 : q = BUNfnd(b, val);
1617 :
1618 9 : if (q == BUN_NONE) {
1619 3 : *ret = oid_nil;
1620 : } else
1621 6 : *ret = (oid) q;
1622 9 : BBPunfix(b->batCacheid);
1623 9 : return msg;
1624 : }
1625 :
1626 :
1627 : static str
1628 293265 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1629 : {
1630 293265 : bat *ret = getArgReference_bat(stk, pci, 0);
1631 293265 : bat bid = *getArgReference_bat(stk, pci, 1);
1632 293265 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1633 293265 : BAT *b, *bn;
1634 :
1635 293265 : (void) cntxt;
1636 293265 : (void) mb;
1637 293265 : if (isaBatType(getArgType(mb, pci, 2)))
1638 0 : throw(MAL, "algebra.project", "Scalar value expected");
1639 293265 : if ((b = BBPquickdesc(bid)) == NULL)
1640 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1641 293230 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1642 293265 : if (bn == NULL) {
1643 0 : *ret = bat_nil;
1644 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1645 : }
1646 293265 : *ret = bn->batCacheid;
1647 293265 : BBPkeepref(bn);
1648 293265 : return MAL_SUCCEED;
1649 : }
1650 :
1651 :
1652 : static str
1653 0 : ALGreuse(bat *ret, const bat *bid)
1654 : {
1655 0 : BAT *b, *bn;
1656 0 : if ((b = BATdescriptor(*bid)) == NULL)
1657 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1658 :
1659 0 : if (!b->batTransient || b->batRestricted != BAT_WRITE) {
1660 0 : if (ATOMvarsized(b->ttype)) {
1661 0 : bn = BATwcopy(b);
1662 0 : if (bn == NULL) {
1663 0 : BBPunfix(b->batCacheid);
1664 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1665 : }
1666 : } else {
1667 0 : bn = COLnew(b->hseqbase, b->ttype, BATcount(b), TRANSIENT);
1668 0 : if (bn == NULL) {
1669 0 : BBPunfix(b->batCacheid);
1670 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1671 : }
1672 0 : BATsetcount(bn, BATcount(b));
1673 0 : bn->tsorted = false;
1674 0 : bn->trevsorted = false;
1675 0 : BATkey(bn, false);
1676 : }
1677 0 : *ret = bn->batCacheid;
1678 0 : BBPkeepref(bn);
1679 0 : BBPunfix(b->batCacheid);
1680 : } else
1681 0 : BBPkeepref(b);
1682 : return MAL_SUCCEED;
1683 : }
1684 :
1685 : /*
1686 : * BAT standard deviation
1687 : */
1688 : static str
1689 7 : ALGstdev(dbl *res, const bat *bid)
1690 : {
1691 7 : BAT *b;
1692 7 : dbl stdev;
1693 :
1694 7 : if ((b = BATdescriptor(*bid)) == NULL)
1695 0 : throw(MAL, "aggr.stdev", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1696 7 : stdev = BATcalcstdev_sample(NULL, b);
1697 7 : BBPunfix(b->batCacheid);
1698 7 : if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0])
1699 0 : throw(MAL, "aggr.stdev", GDK_EXCEPTION);
1700 7 : *res = stdev;
1701 7 : return MAL_SUCCEED;
1702 : }
1703 :
1704 : static str
1705 13 : ALGstdevp(dbl *res, const bat *bid)
1706 : {
1707 13 : BAT *b;
1708 13 : dbl stdev;
1709 :
1710 13 : if ((b = BATdescriptor(*bid)) == NULL)
1711 0 : throw(MAL, "aggr.stdevp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1712 13 : stdev = BATcalcstdev_population(NULL, b);
1713 13 : BBPunfix(b->batCacheid);
1714 13 : if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0])
1715 1 : throw(MAL, "aggr.stdevp", GDK_EXCEPTION);
1716 12 : *res = stdev;
1717 12 : return MAL_SUCCEED;
1718 : }
1719 :
1720 : /*
1721 : * BAT variance
1722 : */
1723 : static str
1724 2 : ALGvariance(dbl *res, const bat *bid)
1725 : {
1726 2 : BAT *b;
1727 2 : dbl variance;
1728 :
1729 2 : if ((b = BATdescriptor(*bid)) == NULL)
1730 0 : throw(MAL, "aggr.variance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1731 2 : variance = BATcalcvariance_sample(NULL, b);
1732 2 : BBPunfix(b->batCacheid);
1733 2 : if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0])
1734 0 : throw(MAL, "aggr.variance", GDK_EXCEPTION);
1735 2 : *res = variance;
1736 2 : return MAL_SUCCEED;
1737 : }
1738 :
1739 : static str
1740 5 : ALGvariancep(dbl *res, const bat *bid)
1741 : {
1742 5 : BAT *b;
1743 5 : dbl variance;
1744 :
1745 5 : if ((b = BATdescriptor(*bid)) == NULL)
1746 0 : throw(MAL, "aggr.variancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1747 5 : variance = BATcalcvariance_population(NULL, b);
1748 5 : BBPunfix(b->batCacheid);
1749 5 : if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0])
1750 1 : throw(MAL, "aggr.variancep", GDK_EXCEPTION);
1751 4 : *res = variance;
1752 4 : return MAL_SUCCEED;
1753 : }
1754 :
1755 : /*
1756 : * BAT covariance
1757 : */
1758 : static str
1759 4 : ALGcovariance(dbl *res, const bat *bid1, const bat *bid2)
1760 : {
1761 4 : BAT *b1, *b2;
1762 4 : dbl covariance;
1763 :
1764 4 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1765 0 : throw(MAL, "aggr.covariance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1766 5 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1767 0 : BBPunfix(b1->batCacheid);
1768 0 : throw(MAL, "aggr.covariance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1769 : }
1770 :
1771 5 : covariance = BATcalccovariance_sample(b1, b2);
1772 5 : BBPunfix(b1->batCacheid);
1773 5 : BBPunfix(b2->batCacheid);
1774 5 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1775 0 : throw(MAL, "aggr.covariance", GDK_EXCEPTION);
1776 5 : *res = covariance;
1777 5 : return MAL_SUCCEED;
1778 : }
1779 :
1780 : static str
1781 9 : ALGcovariancep(dbl *res, const bat *bid1, const bat *bid2)
1782 : {
1783 9 : BAT *b1, *b2;
1784 9 : dbl covariance;
1785 :
1786 9 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1787 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1788 9 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1789 0 : BBPunfix(b1->batCacheid);
1790 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1791 : }
1792 :
1793 9 : covariance = BATcalccovariance_population(b1, b2);
1794 9 : BBPunfix(b1->batCacheid);
1795 9 : BBPunfix(b2->batCacheid);
1796 9 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1797 1 : throw(MAL, "aggr.covariancep", GDK_EXCEPTION);
1798 8 : *res = covariance;
1799 8 : return MAL_SUCCEED;
1800 : }
1801 :
1802 : /*
1803 : * BAT correlation
1804 : */
1805 : static str
1806 19 : ALGcorr(dbl *res, const bat *bid1, const bat *bid2)
1807 : {
1808 19 : BAT *b1, *b2;
1809 19 : dbl covariance;
1810 :
1811 19 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1812 0 : throw(MAL, "aggr.corr", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1813 19 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1814 0 : BBPunfix(b1->batCacheid);
1815 0 : throw(MAL, "aggr.corr", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1816 : }
1817 :
1818 19 : covariance = BATcalccorrelation(b1, b2);
1819 19 : BBPunfix(b1->batCacheid);
1820 19 : BBPunfix(b2->batCacheid);
1821 19 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1822 1 : throw(MAL, "aggr.corr", GDK_EXCEPTION);
1823 18 : *res = covariance;
1824 18 : return MAL_SUCCEED;
1825 : }
1826 :
1827 : #include "mel.h"
1828 : mel_func algebra_init_funcs[] = {
1829 : command("algebra", "groupby", ALGgroupby, false, "Produces a new BAT with groups identified by the head column. The result contains tail times the head value, ie the tail contains the result group sizes.", args(1,3, batarg("",oid),batarg("gids",oid),batarg("cnts",lng))),
1830 : command("algebra", "find", ALGfind, false, "Returns the index position of a value. If no such BUN exists return OID-nil.", args(1,3, arg("",oid),batargany("b",1),argany("t",1))),
1831 : command("algebra", "fetch", ALGfetchoid, false, "Returns the value of the BUN at x-th position with 0 <= x < b.count", args(1,3, argany("",1),batargany("b",1),arg("x",oid))),
1832 : pattern("algebra", "project", ALGprojecttail, false, "Fill the tail with a constant", args(1,3, batargany("",2),batargany("b",1),argany("v",2))),
1833 : command("algebra", "projection", ALGprojection, false, "Project left input onto right input.", args(1,3, batargany("",1),batarg("left",oid),batargany("right",1))),
1834 : command("algebra", "projection", ALGprojection2, false, "Project left input onto right inputs which should be consecutive.", args(1,4, batargany("",1),batarg("left",oid),batargany("right1",1),batargany("right2",1))),
1835 : command("algebra", "copy", ALGcopy, false, "Returns physical copy of a BAT.", args(1,2, batargany("",1),batargany("b",1))),
1836 : command("algebra", "exist", ALGexist, false, "Returns whether 'val' occurs in b.", args(1,3, arg("",bit),batargany("b",1),argany("val",1))),
1837 : command("algebra", "select", ALGselect1, false, "Select all head values for which the tail value is in range.\nInput is a dense-headed BAT, output is a dense-headed BAT with in\nthe tail the head value of the input BAT for which the tail value\nis between the values low and high (inclusive if li respectively\nhi is set). The output BAT is sorted on the tail value. If low\nor high is nil, the boundary is not considered (effectively - and\n+ infinity). If anti is set, the result is the complement. Nil\nvalues in the tail are never matched, unless low=nil, high=nil,\nli=1, hi=1, anti=0. All non-nil values are returned if low=nil,\nhigh=nil, and li, hi are not both 1, or anti=1.\nNote that the output is suitable as second input for the other\nversion of this function.", args(1,7, batarg("",oid),batargany("b",1),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1838 : command("algebra", "select", ALGselect2, false, "Select all head values of the first input BAT for which the tail value\nis in range and for which the head value occurs in the tail of the\nsecond input BAT.\nThe first input is a dense-headed BAT, the second input is a\ndense-headed BAT with sorted tail, output is a dense-headed BAT\nwith in the tail the head value of the input BAT for which the\ntail value is between the values low and high (inclusive if li\nrespectively hi is set). The output BAT is sorted on the tail\nvalue. If low or high is nil, the boundary is not considered\n(effectively - and + infinity). If anti is set, the result is the\ncomplement. Nil values in the tail are never matched, unless\nlow=nil, high=nil, li=1, hi=1, anti=0. All non-nil values are\nreturned if low=nil, high=nil, and li, hi are not both 1, or anti=1.\nNote that the output is suitable as second input for this\nfunction.", args(1,8, batarg("",oid),batargany("b",1),batarg("s",oid),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1839 : command("algebra", "select", ALGselect1nil, false, "With unknown set, each nil != nil", args(1,8, batarg("",oid),batargany("b",1),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("unknown",bit))),
1840 : command("algebra", "select", ALGselect2nil, false, "With unknown set, each nil != nil", args(1,9, batarg("",oid),batargany("b",1),batarg("s",oid),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("unknown",bit))),
1841 : command("algebra", "thetaselect", ALGthetaselect2, false, "Select all head values of the first input BAT for which the tail value\nobeys the relation value OP VAL and for which the head value occurs in\nthe tail of the second input BAT.\nInput is a dense-headed BAT, output is a dense-headed BAT with in\nthe tail the head value of the input BAT for which the\nrelationship holds. The output BAT is sorted on the tail value.", args(1,5, batarg("",oid),batargany("b",1),batarg("s",oid),argany("val",1),arg("op",str))),
1842 : command("algebra", "markselect", ALGmarkselect, false, "Group on group-ids, return aggregated anyequal or allnotequal", args(2,6, batarg("",oid), batarg("", bit), batarg("gid",oid), batarg("m", bit), batarg("p", bit), arg("any", bit))),
1843 : command("algebra", "outerselect", ALGouterselect, false, "Per input lid return at least one row, if none of the predicates (p) hold, return a nil, else 'all' true cases.", args(2,6, batarg("",oid), batarg("", bit), batarg("lid", oid), batarg("rid", bit), batarg("predicate", bit), arg("any", bit))),
1844 : command("algebra", "selectNotNil", ALGselectNotNil, false, "Select all not-nil values", args(1,2, batargany("",1),batargany("b",1))),
1845 : command("algebra", "sort", ALGsort11, false, "Returns a copy of the BAT sorted on tail values.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(1,5, batargany("",1),batargany("b",1),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1846 : command("algebra", "sort", ALGsort12, false, "Returns a copy of the BAT sorted on tail values and a BAT that\nspecifies how the input was reordered.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(2,6, batargany("",1),batarg("",oid),batargany("b",1),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1847 : command("algebra", "sort", ALGsort13, false, "Returns a copy of the BAT sorted on tail values, a BAT that specifies\nhow the input was reordered, and a BAT with group information.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(3,7, batargany("",1),batarg("",oid),batarg("",oid),batargany("b",1),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1848 : command("algebra", "sort", ALGsort21, false, "Returns a copy of the BAT sorted on tail values.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(1,6, batargany("",1),batargany("b",1),batarg("o",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1849 : command("algebra", "sort", ALGsort22, false, "Returns a copy of the BAT sorted on tail values and a BAT that\nspecifies how the input was reordered.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(2,7, batargany("",1),batarg("",oid),batargany("b",1),batarg("o",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1850 : command("algebra", "sort", ALGsort23, false, "Returns a copy of the BAT sorted on tail values, a BAT that specifies\nhow the input was reordered, and a BAT with group information.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(3,8, batargany("",1),batarg("",oid),batarg("",oid),batargany("b",1),batarg("o",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1851 : command("algebra", "sort", ALGsort31, false, "Returns a copy of the BAT sorted on tail values.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(1,7, batargany("",1),batargany("b",1),batarg("o",oid),batarg("g",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1852 : command("algebra", "sort", ALGsort32, false, "Returns a copy of the BAT sorted on tail values and a BAT that\nspecifies how the input was reordered.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(2,8, batargany("",1),batarg("",oid),batargany("b",1),batarg("o",oid),batarg("g",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1853 : command("algebra", "sort", ALGsort33, false, "Returns a copy of the BAT sorted on tail values, a BAT that specifies\nhow the input was reordered, and a BAT with group information.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(3,9, batargany("",1),batarg("",oid),batarg("",oid),batargany("b",1),batarg("o",oid),batarg("g",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1854 : command("algebra", "unique", ALGunique, false, "Select all unique values from the tail of the first input.\nInput is a dense-headed BAT, the second input is a\ndense-headed BAT with sorted tail, output is a dense-headed\nBAT with in the tail the head value of the input BAT that was\nselected. The output BAT is sorted on the tail value. The\nsecond input BAT is a list of candidates.", args(1,3, batarg("",oid),batargany("b",1),batarg("s",oid))),
1855 : command("algebra", "crossproduct", ALGcrossproduct2, false, "Returns 2 columns with all BUNs, consisting of the head-oids\nfrom 'left' and 'right' for which there are BUNs in 'left'\nand 'right' with equal tails", args(2,5, batarg("l",oid),batarg("r",oid),batargany("left",1),batargany("right",2),arg("max_one",bit))),
1856 : command("algebra", "crossproduct", ALGcrossproduct1, false, "Compute the cross product of both input bats; but only produce left output", args(1,4, batarg("",oid),batargany("left",1),batargany("right",2),arg("max_one",bit))),
1857 : command("algebra", "crossproduct", ALGcrossproduct3, false, "Compute the cross product of both input bats", args(2,7, batarg("l",oid),batarg("r",oid),batargany("left",1),batargany("right",2),batarg("sl",oid),batarg("sr",oid),arg("max_one",bit))),
1858 : command("algebra", "crossproduct", ALGcrossproduct4, false, "Compute the cross product of both input bats; but only produce left output", args(1,6, batarg("",oid),batargany("left",1),batargany("right",2),batarg("sl",oid),batarg("sr",oid),arg("max_one",bit))),
1859 : command("algebra", "outercrossproduct", ALGoutercrossproduct3, false, "Compute the outer cross product of both input bats", args(2,7, batarg("l",oid),batarg("r",oid),batargany("left",1),batargany("right",2),batarg("sl",oid),batarg("sr",oid),arg("max_one",bit))),
1860 : command("algebra", "join", ALGjoin, false, "Join", args(2,8, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1861 : command("algebra", "join", ALGjoin1, false, "Join; only produce left output", args(1,7, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1862 : command("algebra", "leftjoin", ALGleftjoin, false, "Left join with candidate lists", args(2,8, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1863 : command("algebra", "leftjoin", ALGleftjoin1, false, "Left join with candidate lists; only produce left output", args(1,7, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1864 : command("algebra", "outerjoin", ALGouterjoin, false, "Left outer join with candidate lists", args(2,9, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("match_one",bit),arg("estimate",lng))),
1865 : command("algebra", "outerjoin", ALGouterjoin1, false, "Left outer join with candidate lists; only produce left output", args(1,8,batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("match_one",bit),arg("estimate",lng))),
1866 : command("algebra", "semijoin", ALGsemijoin, false, "Semi join with candidate lists", args(2,9, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("max_one",bit),arg("estimate",lng))),
1867 : command("algebra", "markjoin", ALGmark2join, false, "Mark join with candidate lists", args(2,7, batarg("",oid),batarg("",bit),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("estimate",lng))),
1868 : command("algebra", "markjoin", ALGmark3join, false, "Mark join with candidate lists", args(3,8, batarg("",oid),batarg("",oid),batarg("",bit),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("estimate",lng))),
1869 : command("algebra", "thetajoin", ALGthetajoin, false, "Theta join with candidate lists", args(2,9, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("op",int),arg("nil_matches",bit),arg("estimate",lng))),
1870 : command("algebra", "thetajoin", ALGthetajoin1, false, "Theta join with candidate lists; only produce left output", args(1,8, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("op",int),arg("nil_matches",bit),arg("estimate",lng))),
1871 : command("algebra", "bandjoin", ALGbandjoin, false, "Band join: values in l and r match if r - c1 <[=] l <[=] r + c2", args(2,11, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),argany("c1",1),argany("c2",1),arg("li",bit),arg("hi",bit),arg("estimate",lng))),
1872 : command("algebra", "bandjoin", ALGbandjoin1, false, "Band join: values in l and r match if r - c1 <[=] l <[=] r + c2; only produce left output", args(1,10, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),argany("c1",1),argany("c2",1),arg("li",bit),arg("hi",bit),arg("estimate",lng))),
1873 : command("algebra", "rangejoin", ALGrangejoin, false, "Range join: values in l and r1/r2 match if r1 <[=] l <[=] r2", args(2,12, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r1",1),batargany("r2",1),batarg("sl",oid),batarg("sr",oid),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("symmetric",bit),arg("estimate",lng))),
1874 : command("algebra", "rangejoin", ALGrangejoin1, false, "Range join: values in l and r1/r2 match if r1 <[=] l <[=] r2; only produce left output", args(1,11,batarg("",oid),batargany("l",1),batargany("r1",1),batargany("r2",1),batarg("sl",oid),batarg("sr",oid),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("symmetric",bit),arg("estimate",lng))),
1875 : command("algebra", "difference", ALGdifference, false, "Difference of l and r with candidate lists", args(1,8, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("nil_clears",bit),arg("estimate",lng))),
1876 : command("algebra", "intersect", ALGintersect, false, "Intersection of l and r with candidate lists (i.e. half of semi-join)", args(1,8, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("max_one",bit),arg("estimate",lng))),
1877 : pattern("algebra", "firstn", ALGfirstn, false, "Calculate first N values of B with candidate list S", args(1,8, batarg("",oid),batargany("b",0),batarg("s",oid),batarg("g",oid),arg("n",lng),arg("asc",bit),arg("nilslast",bit),arg("distinct",bit))),
1878 : pattern("algebra", "firstn", ALGfirstn, false, "Calculate first N values of B with candidate list S", args(2,9, batarg("",oid),batarg("",oid),batargany("b",0),batarg("s",oid),batarg("g",oid),arg("n",lng),arg("asc",bit),arg("nilslast",bit),arg("distinct",bit))),
1879 : pattern("algebra", "groupedfirstn", ALGgroupedfirstn, false, "Grouped firstn", args(1,5, batarg("",oid),arg("n",lng),batarg("s",oid),batarg("g",oid),varargany("arg",0))),
1880 : command("algebra", "reuse", ALGreuse, false, "Reuse a temporary BAT if you can. Otherwise,\nallocate enough storage to accept result of an\noperation (not involving the heap)", args(1,2, batargany("",1),batargany("b",1))),
1881 : command("algebra", "slice", ALGslice_oid, false, "Return the slice based on head oid x till y (exclusive).", args(1,4, batargany("",1),batargany("b",1),arg("x",oid),arg("y",oid))),
1882 : command("algebra", "slice", ALGslice_int, false, "Return the slice with the BUNs at position x till y.", args(1,4, batargany("",1),batargany("b",1),arg("x",int),arg("y",int))),
1883 : command("algebra", "slice", ALGslice_lng, false, "Return the slice with the BUNs at position x till y.", args(1,4, batargany("",1),batargany("b",1),arg("x",lng),arg("y",lng))),
1884 : command("algebra", "subslice", ALGsubslice_lng, false, "Return the oids of the slice with the BUNs at position x till y.", args(1,4, batarg("",oid),batargany("b",1),arg("x",lng),arg("y",lng))),
1885 : command("aggr", "count", ALGcount_bat, false, "Return the current size (in number of elements) in a BAT.", args(1,2, arg("",lng),batargany("b",0))),
1886 : command("aggr", "count", ALGcount_nil, false, "Return the number of elements currently in a BAT ignores\nBUNs with nil-tail iff ignore_nils==TRUE.", args(1,3, arg("",lng),batargany("b",0),arg("ignore_nils",bit))),
1887 : command("aggr", "count_no_nil", ALGcount_no_nil, false, "Return the number of elements currently\nin a BAT ignoring BUNs with nil-tail", args(1,2, arg("",lng),batargany("b",2))),
1888 : command("aggr", "count", ALGcountCND_bat, false, "Return the current size (in number of elements) in a BAT.", args(1,3, arg("",lng),batargany("b",0),batarg("cnd",oid))),
1889 : command("aggr", "count", ALGcountCND_nil, false, "Return the number of elements currently in a BAT ignores\nBUNs with nil-tail iff ignore_nils==TRUE.", args(1,4, arg("",lng),batargany("b",0),batarg("cnd",oid),arg("ignore_nils",bit))),
1890 : command("aggr", "count_no_nil", ALGcountCND_no_nil, false, "Return the number of elements currently\nin a BAT ignoring BUNs with nil-tail", args(1,3, arg("",lng),batargany("b",2),batarg("cnd",oid))),
1891 : command("aggr", "cardinality", ALGcard, false, "Return the cardinality of the BAT tail values.", args(1,2, arg("",lng),batargany("b",2))),
1892 : command("aggr", "min", ALGminany, false, "Return the lowest tail value or nil.", args(1,2, argany("",2),batargany("b",2))),
1893 : command("aggr", "min", ALGminany_skipnil, false, "Return the lowest tail value or nil.", args(1,3, argany("",2),batargany("b",2),arg("skipnil",bit))),
1894 : command("aggr", "max", ALGmaxany, false, "Return the highest tail value or nil.", args(1,2, argany("",2),batargany("b",2))),
1895 : command("aggr", "max", ALGmaxany_skipnil, false, "Return the highest tail value or nil.", args(1,3, argany("",2),batargany("b",2),arg("skipnil",bit))),
1896 : command("aggr", "stdev", ALGstdev, false, "Gives the standard deviation of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1897 : command("aggr", "stdevp", ALGstdevp, false, "Gives the standard deviation of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1898 : command("aggr", "variance", ALGvariance, false, "Gives the variance of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1899 : command("aggr", "variancep", ALGvariancep, false, "Gives the variance of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1900 : command("aggr", "covariance", ALGcovariance, false, "Gives the covariance of all tail values", args(1,3, arg("",dbl),batargany("b1",2),batargany("b2",2))),
1901 : command("aggr", "covariancep", ALGcovariancep, false, "Gives the covariance of all tail values", args(1,3, arg("",dbl),batargany("b1",2),batargany("b2",2))),
1902 : command("aggr", "corr", ALGcorr, false, "Gives the correlation of all tail values", args(1,3, arg("",dbl),batargany("b1",2),batargany("b2",2))),
1903 : // sql
1904 : command("aggr", "exist", ALGexist, false, "", args(1,3, arg("",bit),batargany("b",2),argany("h",1))),
1905 : { .imp=NULL }
1906 : };
1907 : #include "mal_import.h"
1908 : #ifdef _MSC_VER
1909 : #undef read
1910 : #pragma section(".CRT$XCU",read)
1911 : #endif
1912 345 : LIB_STARTUP_FUNC(init_algebra_mal)
1913 345 : { mal_module("algebra", NULL, algebra_init_funcs); }
|