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 2392 : CMDgen_group(BAT **result, BAT *gids, BAT *cnts)
60 : {
61 2392 : BUN j;
62 2392 : BATiter gi = bat_iterator(gids);
63 2392 : 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 95163 : lng i, sz = cnt[j];
75 190262 : for (i = 0; i < sz; i++) {
76 95100 : 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 2392 : bat_iterator_end(&ci);
102 2392 : r->tkey = false;
103 2392 : r->tseqbase = oid_nil;
104 2392 : r->tsorted = gi.sorted;
105 2392 : r->trevsorted = gi.revsorted;
106 2392 : r->tnonil = gi.nonil;
107 2392 : 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 781 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 781 : BAT *b;
143 781 : ptr p;
144 781 : str msg = MAL_SUCCEED;
145 :
146 781 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
147 0 : throw(MAL, "algebra.min", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 :
149 782 : 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 782 : if (ATOMextern(b->ttype)) {
155 42 : *(ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil);
156 : } else {
157 740 : 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 780 : if (msg == MAL_SUCCEED && p == NULL)
163 0 : msg = createException(MAL, "algebra.min", GDK_EXCEPTION);
164 : }
165 780 : BBPunfix(b->batCacheid);
166 780 : return msg;
167 : }
168 :
169 : static str
170 781 : ALGminany(ptr result, const bat *bid)
171 : {
172 781 : bit skipnil = TRUE;
173 781 : return ALGminany_skipnil(result, bid, &skipnil);
174 : }
175 :
176 : static str
177 548 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 548 : BAT *b;
180 548 : ptr p;
181 548 : str msg = MAL_SUCCEED;
182 :
183 548 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 551 : 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 551 : if (ATOMextern(b->ttype)) {
192 68 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 483 : 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 549 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 549 : bit skipnil = TRUE;
210 549 : return ALGmaxany_skipnil(result, bid, &skipnil);
211 : }
212 :
213 : static str
214 2392 : ALGgroupby(bat *res, const bat *gids, const bat *cnts)
215 : {
216 2392 : BAT *bn, *g, *c;
217 :
218 2392 : 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 2392 : *res = bn->batCacheid;
233 2392 : 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 137401 : 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 137401 : BAT *b, *s = NULL, *bn;
265 :
266 137401 : if ((*li != 0 && *li != 1) ||
267 137401 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 :
271 137563 : if ((b = BATdescriptor(*bid)) == NULL) {
272 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
273 : }
274 138237 : 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 138260 : derefStr(b, low);
279 138260 : derefStr(b, high);
280 :
281 138260 : bool nanti = *anti, nli = *li, nhi = *hi;
282 :
283 : /* here we don't need open ended parts with nil */
284 138260 : if (!nanti && *unknown) {
285 1584 : const void *nilptr = ATOMnilptr(b->ttype);
286 1584 : if (nilptr) {
287 1584 : if (nli && ATOMcmp(b->ttype, low, nilptr) == 0) {
288 22 : low = high;
289 22 : nli = false;
290 : }
291 1581 : if (nhi && ATOMcmp(b->ttype, high, nilptr) == 0) {
292 24 : high = low;
293 24 : nhi = false;
294 : }
295 1580 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
296 14 : nanti = true;
297 : }
298 136676 : } else if (!*unknown) {
299 130425 : const void *nilptr = ATOMnilptr(b->ttype);
300 260517 : if (nli && nhi && nilptr != NULL &&
301 130463 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
302 24 : ATOMcmp(b->ttype, high, nilptr) == 0) {
303 : /* special case: equi-select for NIL */
304 137913 : high = NULL;
305 : }
306 : }
307 :
308 137913 : bn = BATselect(b, s, low, high, nli, nhi, nanti, false);
309 136929 : BBPunfix(b->batCacheid);
310 138186 : BBPreclaim(s);
311 138087 : if (bn == NULL)
312 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
313 138087 : *result = bn->batCacheid;
314 138087 : BBPkeepref(bn);
315 138087 : return MAL_SUCCEED;
316 : }
317 :
318 : static str
319 40862 : 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 40862 : return ALGselect2nil(result, bid, sid, low, high, li, hi, anti, &(bit){0});
323 : }
324 :
325 : static str
326 89089 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
327 : const bit *li, const bit *hi, const bit *anti)
328 : {
329 89089 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, &(bit){0});
330 : }
331 :
332 : static str
333 308 : 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 308 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown);
337 : }
338 :
339 : static str
340 526247 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
341 : const char **op)
342 : {
343 526247 : BAT *b, *s = NULL, *bn;
344 :
345 526247 : if ((b = BATdescriptor(*bid)) == NULL) {
346 0 : throw(MAL, "algebra.thetaselect",
347 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
348 : }
349 528644 : 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 528897 : derefStr(b, val);
355 528897 : bn = BATthetaselect(b, s, val, *op);
356 526197 : BBPunfix(b->batCacheid);
357 528523 : BBPreclaim(s);
358 528528 : if (bn == NULL)
359 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
360 528528 : *result = bn->batCacheid;
361 528528 : BBPkeepref(bn);
362 528528 : return MAL_SUCCEED;
363 : }
364 :
365 : static str
366 398 : ALGmarkselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
367 : {
368 398 : BAT *g = BATdescriptor(*gid); /* oid */
369 398 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
370 398 : BAT *p = BATdescriptor(*pid); /* bit */
371 398 : BAT *res1 = NULL, *res2 = NULL;
372 398 : bit any = *Any; /* any or normal comparison semantics */
373 :
374 398 : 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 398 : BUN nr = BATcount(g), q = 0;
381 :
382 398 : 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 398 : assert(g->tsorted);
390 398 : oid *ri1 = Tloc(res1, 0);
391 398 : bit *ri2 = Tloc(res2, 0);
392 398 : bit *mi = Tloc(m, 0);
393 398 : bit *pi = Tloc(p, 0);
394 398 : oid cur = oid_nil;
395 :
396 398 : if (g->ttype == TYPE_void) { /* void case ? */
397 33 : oid c = g->hseqbase;
398 131 : for (BUN n = 0; n < nr; n++, c++) {
399 98 : ri1[q] = c;
400 98 : ri2[q] = FALSE;
401 98 : if (pi[n] == TRUE && mi[n] == TRUE)
402 7 : ri2[q] = TRUE;
403 91 : 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 98 : 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 398 : BATsetcount(res1, q);
438 398 : BATsetcount(res2, q);
439 398 : res1->tsorted = true;
440 398 : res1->tkey = true;
441 398 : res1->trevsorted = false;
442 398 : res2->tsorted = false;
443 398 : res2->trevsorted = false;
444 398 : res1->tnil = false;
445 398 : res1->tnonil = true;
446 398 : res2->tnonil = false;
447 398 : res2->tkey = false;
448 :
449 398 : BBPreclaim(g);
450 398 : BBPreclaim(m);
451 398 : BBPreclaim(p);
452 :
453 398 : BBPkeepref(res1);
454 398 : BBPkeepref(res2);
455 398 : *r1 = res1->batCacheid;
456 398 : *r2 = res2->batCacheid;
457 398 : 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 1585 : MT_lock_set(&b->theaplock);
571 1585 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
572 1585 : MT_lock_unset(&b->theaplock);
573 1586 : if (!bnonil) {
574 125 : BAT *s;
575 125 : s = BATselect(b, NULL, ATOMnilptr(b->ttype), NULL, true, true, true, false);
576 124 : if (s) {
577 124 : BAT *bn = BATproject(s, b);
578 125 : BBPunfix(s->batCacheid);
579 125 : if (bn) {
580 125 : BBPunfix(b->batCacheid);
581 125 : *result = bn->batCacheid;
582 125 : BBPkeepref(bn);
583 125 : 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 647780 : 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 647780 : BAT *left = NULL, *right = NULL, *right2 = NULL;
616 647780 : BAT *candleft = NULL, *candright = NULL;
617 647780 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
618 647780 : BUN est;
619 647780 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
620 :
621 647780 : assert(r2id == NULL || rangefunc != NULL);
622 :
623 647780 : if ((left = BATdescriptor(*lid)) == NULL)
624 0 : goto fail;
625 654521 : if ((right = BATdescriptor(*rid)) == NULL)
626 0 : goto fail;
627 654519 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
628 0 : goto fail;
629 654522 : if (srid && !is_bat_nil(*srid)
630 0 : && (candright = BATdescriptor(*srid)) == NULL)
631 0 : goto fail;
632 654522 : 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 654522 : err = NULL; /* most likely error now is GDK_EXCEPTION */
639 :
640 654522 : if (thetafunc) {
641 51398 : assert(joinfunc == NULL);
642 51398 : assert(semifunc == NULL);
643 51398 : assert(markfunc == NULL);
644 51398 : assert(bandfunc == NULL);
645 51398 : assert(rangefunc == NULL);
646 51398 : assert(difffunc == NULL);
647 51398 : assert(interfunc == NULL);
648 51398 : if ((*thetafunc)
649 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
650 51398 : op, *nil_matches, est) != GDK_SUCCEED)
651 0 : goto fail;
652 603124 : } else if (joinfunc) {
653 413129 : assert(semifunc == NULL);
654 413129 : assert(markfunc == NULL);
655 413129 : assert(bandfunc == NULL);
656 413129 : assert(rangefunc == NULL);
657 413129 : assert(difffunc == NULL);
658 413129 : assert(interfunc == NULL);
659 413129 : if ((*joinfunc)
660 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
661 413129 : *nil_matches, est) != GDK_SUCCEED)
662 1 : goto fail;
663 189995 : } else if (semifunc) {
664 334 : assert(markfunc == NULL);
665 334 : assert(bandfunc == NULL);
666 334 : assert(rangefunc == NULL);
667 334 : assert(difffunc == NULL);
668 334 : assert(interfunc == NULL);
669 334 : if ((*semifunc)
670 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
671 334 : *nil_matches, *max_one, est) != GDK_SUCCEED)
672 44 : goto fail;
673 189661 : } else if (markfunc) {
674 19347 : assert(bandfunc == NULL);
675 19347 : assert(rangefunc == NULL);
676 19347 : assert(difffunc == NULL);
677 19347 : assert(interfunc == NULL);
678 38688 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
679 : left, right, candleft, candright, est) != GDK_SUCCEED)
680 0 : goto fail;
681 170314 : } 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 170314 : } 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 170167 : } else if (difffunc) {
702 160510 : assert(r2 == NULL);
703 160510 : assert(interfunc == NULL);
704 160226 : if ((result1 = (*difffunc) (left, right, candleft, candright,
705 160510 : *nil_matches, *not_in, est)) == NULL)
706 0 : goto fail;
707 : } else {
708 9657 : assert(r2 == NULL);
709 9615 : if ((result1 = (*interfunc) (left, right, candleft, candright,
710 9657 : *nil_matches, *max_one, est)) == NULL)
711 1 : goto fail;
712 : }
713 649825 : *r1 = result1->batCacheid;
714 649825 : BBPkeepref(result1);
715 652460 : if (r2) {
716 376929 : *r2 = result2->batCacheid;
717 376929 : BBPkeepref(result2);
718 : }
719 653282 : if (r3) {
720 19284 : *r3 = result3->batCacheid;
721 19284 : BBPkeepref(result3);
722 : }
723 653313 : BBPunfix(left->batCacheid);
724 653915 : BBPunfix(right->batCacheid);
725 654389 : BBPreclaim(candleft);
726 654414 : BBPreclaim(candright);
727 : return MAL_SUCCEED;
728 :
729 46 : fail:
730 46 : BBPreclaim(left);
731 46 : BBPreclaim(right);
732 46 : BBPreclaim(right2);
733 46 : BBPreclaim(candleft);
734 46 : BBPreclaim(candright);
735 46 : if (err == NULL)
736 46 : throw(MAL, funcname, GDK_EXCEPTION);
737 0 : throw(MAL, funcname, "%s", err);
738 : }
739 :
740 : static str
741 366208 : 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 366208 : 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 43365 : 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 43365 : 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 211 : 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 211 : 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 19265 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
815 : const bat *slid, const bat *srid, const lng *estimate)
816 : {
817 19265 : 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 7685 : 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 7685 : 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 41396 : 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 41396 : 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 117 : 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 239 : return do_join(r1, r2, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
883 117 : *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 23 : 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 48 : return do_join(r1, NULL, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
894 23 : *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 160447 : 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 160447 : 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 1717 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
932 : {
933 1717 : bat *ret1, *ret2 = NULL;
934 1717 : bat bid, sid, gid;
935 1717 : BAT *b, *s = NULL, *g = NULL;
936 1717 : BAT *bn = NULL, *gn = NULL;
937 1717 : lng n;
938 1717 : bit asc, nilslast, distinct;
939 1717 : gdk_return rc;
940 :
941 1717 : (void) cntxt;
942 1717 : (void) mb;
943 :
944 1717 : assert(pci->retc == 1 || pci->retc == 2);
945 1717 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
946 :
947 1717 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
948 1717 : if (n < 0)
949 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
950 1717 : if (n > (lng) BUN_MAX)
951 : n = BUN_MAX;
952 1717 : ret1 = getArgReference_bat(stk, pci, 0);
953 1717 : if (pci->retc == 2)
954 621 : ret2 = getArgReference_bat(stk, pci, 1);
955 1717 : bid = *getArgReference_bat(stk, pci, pci->retc);
956 1717 : if ((b = BATdescriptor(bid)) == NULL)
957 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
958 1718 : if (pci->argc - pci->retc > 5) {
959 1718 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
960 1718 : 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 1719 : if (pci->argc - pci->retc > 6) {
966 1719 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
967 1719 : 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 1719 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
976 1719 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
977 1719 : 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 1719 : BBPunfix(b->batCacheid);
981 1723 : BBPreclaim(s);
982 1720 : BBPreclaim(g);
983 1722 : if (rc != GDK_SUCCEED)
984 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
985 1722 : *ret1 = bn->batCacheid;
986 1722 : BBPkeepref(bn);
987 1717 : if (ret2) {
988 622 : *ret2 = gn->batCacheid;
989 622 : 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 45503 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1121 : const bat *slid, const bat *srid, const bit *max_one)
1122 : {
1123 45503 : BAT *L, *R, *bn1, *bn2 = NULL;
1124 45503 : BAT *sl = NULL, *sr = NULL;
1125 45503 : gdk_return ret;
1126 :
1127 45503 : L = BATdescriptor(*left);
1128 46918 : R = BATdescriptor(*right);
1129 46991 : 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 46991 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1136 0 : (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 48802 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1145 46991 : max_one && !is_bit_nil(*max_one) && *max_one);
1146 46412 : BBPunfix(L->batCacheid);
1147 46925 : BBPunfix(R->batCacheid);
1148 46999 : BBPreclaim(sl);
1149 46999 : BBPreclaim(sr);
1150 46995 : if (ret != GDK_SUCCEED)
1151 88 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1152 46907 : *l = bn1->batCacheid;
1153 46907 : BBPkeepref(bn1);
1154 46862 : if (r) {
1155 45066 : *r = bn2->batCacheid;
1156 45066 : BBPkeepref(bn2);
1157 : }
1158 : return MAL_SUCCEED;
1159 : }
1160 :
1161 : static str
1162 1767 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1163 : {
1164 1767 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1165 : }
1166 :
1167 : static str
1168 43797 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1169 : const bit *max_one)
1170 : {
1171 43797 : 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 427 : ALGoutercrossproduct3(bat *l, bat *r, const bat *left, const bat *right, const bat *slid, const bat *srid, const bit *max_one)
1190 : {
1191 427 : BAT *L, *R, *bn1, *bn2 = NULL;
1192 427 : BAT *sl = NULL, *sr = NULL;
1193 427 : gdk_return ret;
1194 :
1195 427 : L = BATdescriptor(*left);
1196 427 : R = BATdescriptor(*right);
1197 427 : 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 427 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1203 427 : (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 427 : ret = BAToutercross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1211 427 : max_one && !is_bit_nil(*max_one) && *max_one);
1212 427 : BBPunfix(L->batCacheid);
1213 427 : BBPunfix(R->batCacheid);
1214 427 : BBPreclaim(sl);
1215 427 : BBPreclaim(sr);
1216 427 : if (ret != GDK_SUCCEED)
1217 0 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1218 427 : *l = bn1->batCacheid;
1219 427 : BBPkeepref(bn1);
1220 427 : if (r) {
1221 427 : *r = bn2->batCacheid;
1222 427 : BBPkeepref(bn2);
1223 : }
1224 : return MAL_SUCCEED;
1225 : }
1226 :
1227 : static str
1228 1991435 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1229 : {
1230 1991435 : BAT *l, *r1, *r2 = NULL, *bn;
1231 :
1232 1991435 : if ((l = BATdescriptor(*lid)) == NULL) {
1233 0 : throw(MAL, "algebra.projection",
1234 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1235 : }
1236 2003602 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1237 0 : BBPunfix(l->batCacheid);
1238 0 : throw(MAL, "algebra.projection",
1239 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1240 : }
1241 2002673 : 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 2002673 : bn = BATproject2(l, r1, r2);
1248 1976181 : BBPunfix(l->batCacheid);
1249 1999932 : BBPunfix(r1->batCacheid);
1250 2002541 : BBPreclaim(r2);
1251 2002737 : if (bn == NULL)
1252 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1253 2002737 : *result = bn->batCacheid;
1254 2002737 : BBPkeepref(bn);
1255 2002737 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : str
1259 1993312 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1260 : {
1261 1993312 : return ALGprojection2(result, lid, rid, NULL);
1262 : }
1263 :
1264 : static str
1265 24717 : 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 24717 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1270 24717 : BAT *b = NULL, *o = NULL, *g = NULL;
1271 :
1272 24717 : if ((b = BATdescriptor(*bid)) == NULL)
1273 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1274 24717 : 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 24717 : 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 28460 : if (BATsort(result ? &bn : NULL,
1284 : norder ? &on : NULL,
1285 : ngroup ? &gn : NULL,
1286 24717 : 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 24717 : BBPunfix(b->batCacheid);
1293 24717 : BBPreclaim(o);
1294 24717 : BBPreclaim(g);
1295 24717 : if (result) {
1296 24717 : *result = bn->batCacheid;
1297 24717 : BBPkeepref(bn);
1298 : }
1299 24717 : if (norder) {
1300 20974 : *norder = on->batCacheid;
1301 20974 : BBPkeepref(on);
1302 : }
1303 24717 : if (ngroup) {
1304 14087 : *ngroup = gn->batCacheid;
1305 14087 : BBPkeepref(gn);
1306 : }
1307 : return MAL_SUCCEED;
1308 : }
1309 :
1310 : static str
1311 4284 : 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 4284 : 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 6617 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1354 : const bit *reverse, const bit *nilslast, const bit *stable)
1355 : {
1356 6617 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1357 : stable);
1358 : }
1359 :
1360 : static str
1361 2603 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1362 : const bit *nilslast, const bit *stable)
1363 : {
1364 2603 : return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast,
1365 : stable);
1366 : }
1367 :
1368 : static str
1369 1665 : ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast,
1370 : const bit *stable)
1371 : {
1372 1665 : return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast,
1373 : stable);
1374 : }
1375 :
1376 : static str
1377 70955 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1378 : const bit *ignore_nils)
1379 : {
1380 70955 : BAT *b, *s = NULL;
1381 :
1382 70955 : if ((b = BATdescriptor(*bid)) == NULL) {
1383 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1384 : }
1385 71242 : 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 71242 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1390 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1391 71212 : } else if (*ignore_nils) {
1392 1770 : *result = (lng) BATcount_no_nil(b, s);
1393 : } else {
1394 69442 : struct canditer ci;
1395 69442 : canditer_init(&ci, b, s);
1396 69421 : *result = (lng) ci.ncand;
1397 : }
1398 71219 : BBPreclaim(s);
1399 71219 : BBPunfix(b->batCacheid);
1400 71219 : return MAL_SUCCEED;
1401 : }
1402 :
1403 : static str
1404 1768 : ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils)
1405 : {
1406 1768 : 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 69194 : ALGcount_bat(lng *result, const bat *bid)
1417 : {
1418 69194 : 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 17460 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1482 : {
1483 17460 : BAT *b, *bn;
1484 17460 : BUN s, e;
1485 :
1486 17460 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1487 2 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1488 17458 : if ((b = BBPquickdesc(*bid)) == NULL)
1489 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1490 17459 : s = (BUN) *start;
1491 17459 : if (s > BATcount(b))
1492 : s = BATcount(b);
1493 17459 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1494 17459 : if (e > BATcount(b))
1495 : e = BATcount(b);
1496 17459 : if (e < s)
1497 : e = s;
1498 17459 : bn = BATdense(0, b->hseqbase + s, e - s);
1499 17460 : if (bn == NULL)
1500 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1501 17460 : *ret = bn->batCacheid;
1502 17460 : BBPkeepref(bn);
1503 17460 : return MAL_SUCCEED;
1504 : }
1505 :
1506 : /*
1507 : * BUN Get/Fetch
1508 : */
1509 :
1510 : static str
1511 185286 : doALGfetch(ptr ret, BAT *b, BUN pos)
1512 : {
1513 185286 : assert(pos <= BUN_MAX);
1514 185286 : BATiter bi = bat_iterator(b);
1515 185286 : 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 185096 : size_t _s = ATOMsize(ATOMtype(b->ttype));
1527 185096 : 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 185096 : } else if (_s == 4) {
1532 185009 : *(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 185286 : bat_iterator_end(&bi);
1548 185286 : return MAL_SUCCEED;
1549 : }
1550 :
1551 : static str
1552 185288 : ALGfetch(ptr ret, const bat *bid, const lng *pos)
1553 : {
1554 185288 : BAT *b;
1555 185288 : str msg;
1556 :
1557 185288 : if ((b = BATdescriptor(*bid)) == NULL) {
1558 0 : throw(MAL, "algebra.fetch", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1559 : }
1560 185288 : 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 185288 : 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 185286 : 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 185286 : msg = doALGfetch(ret, b, (BUN) *pos);
1577 185286 : BBPunfix(b->batCacheid);
1578 185286 : return msg;
1579 : }
1580 :
1581 : str
1582 185288 : ALGfetchoid(ptr ret, const bat *bid, const oid *pos)
1583 : {
1584 185288 : lng o = *pos;
1585 :
1586 185288 : 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 293210 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1629 : {
1630 293210 : bat *ret = getArgReference_bat(stk, pci, 0);
1631 293210 : bat bid = *getArgReference_bat(stk, pci, 1);
1632 293210 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1633 293210 : BAT *b, *bn;
1634 :
1635 293210 : (void) cntxt;
1636 293210 : (void) mb;
1637 293210 : if (isaBatType(getArgType(mb, pci, 2)))
1638 0 : throw(MAL, "algebra.project", "Scalar value expected");
1639 293210 : if ((b = BBPquickdesc(bid)) == NULL)
1640 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1641 293186 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1642 293270 : if (bn == NULL) {
1643 0 : *ret = bat_nil;
1644 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1645 : }
1646 293270 : *ret = bn->batCacheid;
1647 293270 : BBPkeepref(bn);
1648 293270 : 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 5 : ALGcovariance(dbl *res, const bat *bid1, const bat *bid2)
1760 : {
1761 5 : BAT *b1, *b2;
1762 5 : dbl covariance;
1763 :
1764 5 : 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); }
|