Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024, 2025 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
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 777 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 777 : BAT *b;
143 777 : ptr p;
144 777 : str msg = MAL_SUCCEED;
145 :
146 777 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
147 0 : throw(MAL, "algebra.min", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 :
149 778 : 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 778 : if (ATOMextern(b->ttype)) {
155 42 : *(ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil);
156 : } else {
157 736 : p = BATmin_skipnil(b, result, *skipnil);
158 737 : if (p != result)
159 0 : msg = createException(MAL, "algebra.min",
160 : SQLSTATE(HY002) "INTERNAL ERROR");
161 : }
162 779 : if (msg == MAL_SUCCEED && p == NULL)
163 0 : msg = createException(MAL, "algebra.min", GDK_EXCEPTION);
164 : }
165 779 : BBPunfix(b->batCacheid);
166 779 : return msg;
167 : }
168 :
169 : static str
170 777 : ALGminany(ptr result, const bat *bid)
171 : {
172 777 : bit skipnil = TRUE;
173 777 : return ALGminany_skipnil(result, bid, &skipnil);
174 : }
175 :
176 : static str
177 544 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 544 : BAT *b;
180 544 : ptr p;
181 544 : str msg = MAL_SUCCEED;
182 :
183 544 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 543 : 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 543 : if (ATOMextern(b->ttype)) {
192 64 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 479 : 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 547 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 547 : BBPunfix(b->batCacheid);
203 547 : return msg;
204 : }
205 :
206 : static str
207 544 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 544 : bit skipnil = TRUE;
210 544 : 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 137556 : 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 137556 : BAT *b, *s = NULL, *bn;
265 :
266 137556 : if ((*li != 0 && *li != 1) ||
267 137556 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 :
271 137700 : if ((b = BATdescriptor(*bid)) == NULL) {
272 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
273 : }
274 138382 : 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 138406 : derefStr(b, low);
279 138406 : derefStr(b, high);
280 :
281 138406 : bool nanti = *anti, nli = *li, nhi = *hi;
282 :
283 : /* here we don't need open ended parts with nil */
284 138406 : if (!nanti && *unknown) {
285 1574 : const void *nilptr = ATOMnilptr(b->ttype);
286 1574 : if (nilptr) {
287 1574 : if (nli && ATOMcmp(b->ttype, low, nilptr) == 0) {
288 17 : low = high;
289 17 : nli = false;
290 : }
291 1570 : if (nhi && ATOMcmp(b->ttype, high, nilptr) == 0) {
292 17 : high = low;
293 17 : nhi = false;
294 : }
295 1571 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
296 10 : nanti = true;
297 : }
298 136832 : } else if (!*unknown) {
299 130607 : const void *nilptr = ATOMnilptr(b->ttype);
300 260867 : if (nli && nhi && nilptr != NULL &&
301 130661 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
302 24 : ATOMcmp(b->ttype, high, nilptr) == 0) {
303 : /* special case: equi-select for NIL */
304 138030 : high = NULL;
305 : }
306 : }
307 :
308 138030 : bn = BATselect(b, s, low, high, nli, nhi, nanti, false);
309 137311 : BBPunfix(b->batCacheid);
310 138302 : BBPreclaim(s);
311 138340 : if (bn == NULL)
312 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
313 138340 : *result = bn->batCacheid;
314 138340 : BBPkeepref(bn);
315 138340 : return MAL_SUCCEED;
316 : }
317 :
318 : static str
319 40836 : 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 40836 : return ALGselect2nil(result, bid, sid, low, high, li, hi, anti, &(bit){0});
323 : }
324 :
325 : static str
326 89253 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
327 : const bit *li, const bit *hi, const bit *anti)
328 : {
329 89253 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, &(bit){0});
330 : }
331 :
332 : static str
333 310 : 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 310 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown);
337 : }
338 :
339 : static str
340 518504 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
341 : const char **op)
342 : {
343 518504 : BAT *b, *s = NULL, *bn;
344 :
345 518504 : if ((b = BATdescriptor(*bid)) == NULL) {
346 0 : throw(MAL, "algebra.thetaselect",
347 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
348 : }
349 520808 : 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 520909 : derefStr(b, val);
355 520909 : bn = BATthetaselect(b, s, val, *op);
356 518532 : BBPunfix(b->batCacheid);
357 520621 : BBPreclaim(s);
358 520505 : if (bn == NULL)
359 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
360 520505 : *result = bn->batCacheid;
361 520505 : BBPkeepref(bn);
362 520505 : 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 32 : oid c = g->hseqbase;
398 132 : for (BUN n = 0; n < nr; n++, c++) {
399 100 : ri1[q] = c;
400 100 : ri2[q] = FALSE;
401 100 : if (pi[n] == TRUE && mi[n] == TRUE)
402 7 : ri2[q] = TRUE;
403 93 : 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 100 : q++;
406 : }
407 : } else {
408 364 : oid *gi = Tloc(g, 0);
409 364 : oid c = g->hseqbase;
410 364 : if (nr)
411 364 : cur = gi[0];
412 : bit m = FALSE;
413 : bool has_nil = false;
414 332644 : for (BUN n = 0; n < nr; n++, c++) {
415 332280 : if (c && cur != gi[n]) {
416 57732 : ri1[q] = c-1;
417 57732 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
418 57732 : q++;
419 57732 : cur = gi[n];
420 57732 : m = FALSE;
421 57732 : has_nil = false;
422 : }
423 332280 : if (m == TRUE)
424 191843 : continue;
425 :
426 140437 : if (pi[n] == TRUE && mi[n] == TRUE)
427 : m = TRUE;
428 133510 : else if ((mi[n] == bit_nil && pi[n] != bit_nil && !any) || (mi[n] != FALSE && pi[n] == bit_nil && any))
429 332280 : has_nil = true;
430 : }
431 364 : if (nr) {
432 364 : ri1[q] = c-1;
433 364 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
434 : }
435 364 : 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 1587 : ALGselectNotNil(bat *result, const bat *bid)
563 : {
564 1587 : BAT *b;
565 :
566 1587 : if ((b = BATdescriptor(*bid)) == NULL)
567 0 : throw(MAL, "algebra.selectNotNil",
568 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
569 :
570 1587 : MT_lock_set(&b->theaplock);
571 1587 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
572 1587 : MT_lock_unset(&b->theaplock);
573 1587 : if (!bnonil) {
574 125 : BAT *s;
575 125 : s = BATselect(b, NULL, ATOMnilptr(b->ttype), NULL, true, true, true, false);
576 125 : if (s) {
577 125 : 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 1462 : *result = b->batCacheid;
591 1462 : BBPkeepref(b);
592 1462 : return MAL_SUCCEED;
593 : }
594 :
595 : static str
596 652123 : 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 652123 : BAT *left = NULL, *right = NULL, *right2 = NULL;
616 652123 : BAT *candleft = NULL, *candright = NULL;
617 652123 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
618 652123 : BUN est;
619 652123 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
620 :
621 652123 : assert(r2id == NULL || rangefunc != NULL);
622 :
623 652123 : if ((left = BATdescriptor(*lid)) == NULL)
624 0 : goto fail;
625 659218 : if ((right = BATdescriptor(*rid)) == NULL)
626 0 : goto fail;
627 659240 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
628 0 : goto fail;
629 659241 : if (srid && !is_bat_nil(*srid)
630 0 : && (candright = BATdescriptor(*srid)) == NULL)
631 0 : goto fail;
632 659241 : 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 659241 : err = NULL; /* most likely error now is GDK_EXCEPTION */
639 :
640 659241 : if (thetafunc) {
641 51259 : assert(joinfunc == NULL);
642 51259 : assert(semifunc == NULL);
643 51259 : assert(markfunc == NULL);
644 51259 : assert(bandfunc == NULL);
645 51259 : assert(rangefunc == NULL);
646 51259 : assert(difffunc == NULL);
647 51259 : assert(interfunc == NULL);
648 51259 : if ((*thetafunc)
649 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
650 51259 : op, *nil_matches, est) != GDK_SUCCEED)
651 0 : goto fail;
652 607982 : } else if (joinfunc) {
653 417337 : assert(semifunc == NULL);
654 417337 : assert(markfunc == NULL);
655 417337 : assert(bandfunc == NULL);
656 417337 : assert(rangefunc == NULL);
657 417337 : assert(difffunc == NULL);
658 417337 : assert(interfunc == NULL);
659 417337 : if ((*joinfunc)
660 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
661 417337 : *nil_matches, est) != GDK_SUCCEED)
662 1 : goto fail;
663 190645 : } else if (semifunc) {
664 335 : assert(markfunc == NULL);
665 335 : assert(bandfunc == NULL);
666 335 : assert(rangefunc == NULL);
667 335 : assert(difffunc == NULL);
668 335 : assert(interfunc == NULL);
669 335 : if ((*semifunc)
670 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
671 335 : *nil_matches, *max_one, est) != GDK_SUCCEED)
672 44 : goto fail;
673 190310 : } else if (markfunc) {
674 19519 : assert(bandfunc == NULL);
675 19519 : assert(rangefunc == NULL);
676 19519 : assert(difffunc == NULL);
677 19519 : assert(interfunc == NULL);
678 39033 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
679 : left, right, candleft, candright, est) != GDK_SUCCEED)
680 0 : goto fail;
681 170791 : } 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 170791 : } 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 143 : BBPunfix(right2->batCacheid);
701 170644 : } else if (difffunc) {
702 160926 : assert(r2 == NULL);
703 160926 : assert(interfunc == NULL);
704 160678 : if ((result1 = (*difffunc) (left, right, candleft, candright,
705 160926 : *nil_matches, *not_in, est)) == NULL)
706 0 : goto fail;
707 : } else {
708 9718 : assert(r2 == NULL);
709 9689 : if ((result1 = (*interfunc) (left, right, candleft, candright,
710 9718 : *nil_matches, *max_one, est)) == NULL)
711 1 : goto fail;
712 : }
713 655161 : *r1 = result1->batCacheid;
714 655161 : BBPkeepref(result1);
715 656703 : if (r2) {
716 380928 : *r2 = result2->batCacheid;
717 380928 : BBPkeepref(result2);
718 : }
719 656960 : if (r3) {
720 19446 : *r3 = result3->batCacheid;
721 19446 : BBPkeepref(result3);
722 : }
723 657014 : BBPunfix(left->batCacheid);
724 658660 : BBPunfix(right->batCacheid);
725 659003 : BBPreclaim(candleft);
726 658851 : 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 370130 : 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 370130 : 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 43216 : 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 43216 : 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 123 : 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 123 : 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 19427 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
815 : const bat *slid, const bat *srid, const lng *estimate)
816 : {
817 19427 : 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 7613 : 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 7613 : 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 41380 : 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 41380 : 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 24 : 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 49 : return do_join(r1, NULL, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
894 24 : *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 160779 : 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 160779 : 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 9718 : 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 9718 : 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 1719 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
932 : {
933 1719 : bat *ret1, *ret2 = NULL;
934 1719 : bat bid, sid, gid;
935 1719 : BAT *b, *s = NULL, *g = NULL;
936 1719 : BAT *bn = NULL, *gn = NULL;
937 1719 : lng n;
938 1719 : bit asc, nilslast, distinct;
939 1719 : gdk_return rc;
940 :
941 1719 : (void) cntxt;
942 1719 : (void) mb;
943 :
944 1719 : assert(pci->retc == 1 || pci->retc == 2);
945 1719 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
946 :
947 1719 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
948 1719 : if (n < 0)
949 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
950 1719 : if (n > (lng) BUN_MAX)
951 : n = BUN_MAX;
952 1719 : ret1 = getArgReference_bat(stk, pci, 0);
953 1719 : if (pci->retc == 2)
954 618 : ret2 = getArgReference_bat(stk, pci, 1);
955 1719 : bid = *getArgReference_bat(stk, pci, pci->retc);
956 1719 : if ((b = BATdescriptor(bid)) == NULL)
957 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
958 1721 : if (pci->argc - pci->retc > 5) {
959 1722 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
960 1722 : 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 1725 : if (pci->argc - pci->retc > 6) {
966 1725 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
967 1725 : 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 1724 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
976 1724 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
977 1724 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
978 2826 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
979 : distinct);
980 1721 : BBPunfix(b->batCacheid);
981 1723 : BBPreclaim(s);
982 1723 : BBPreclaim(g);
983 1723 : if (rc != GDK_SUCCEED)
984 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
985 1723 : *ret1 = bn->batCacheid;
986 1723 : BBPkeepref(bn);
987 1720 : if (ret2) {
988 623 : *ret2 = gn->batCacheid;
989 623 : 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 45274 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1121 : const bat *slid, const bat *srid, const bit *max_one)
1122 : {
1123 45274 : BAT *L, *R, *bn1, *bn2 = NULL;
1124 45274 : BAT *sl = NULL, *sr = NULL;
1125 45274 : gdk_return ret;
1126 :
1127 45274 : L = BATdescriptor(*left);
1128 46794 : R = BATdescriptor(*right);
1129 46854 : 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 46854 : 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 48667 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1145 46854 : max_one && !is_bit_nil(*max_one) && *max_one);
1146 46388 : BBPunfix(L->batCacheid);
1147 46758 : BBPunfix(R->batCacheid);
1148 46860 : BBPreclaim(sl);
1149 46861 : BBPreclaim(sr);
1150 46864 : if (ret != GDK_SUCCEED)
1151 88 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1152 46776 : *l = bn1->batCacheid;
1153 46776 : BBPkeepref(bn1);
1154 46705 : if (r) {
1155 44911 : *r = bn2->batCacheid;
1156 44911 : BBPkeepref(bn2);
1157 : }
1158 : return MAL_SUCCEED;
1159 : }
1160 :
1161 : static str
1162 1748 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1163 : {
1164 1748 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1165 : }
1166 :
1167 : static str
1168 43595 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1169 : const bit *max_one)
1170 : {
1171 43595 : 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 424 : ALGoutercrossproduct3(bat *l, bat *r, const bat *left, const bat *right, const bat *slid, const bat *srid, const bit *max_one)
1190 : {
1191 424 : BAT *L, *R, *bn1, *bn2 = NULL;
1192 424 : BAT *sl = NULL, *sr = NULL;
1193 424 : gdk_return ret;
1194 :
1195 424 : L = BATdescriptor(*left);
1196 424 : R = BATdescriptor(*right);
1197 424 : 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 424 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1203 424 : (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 424 : ret = BAToutercross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1211 424 : max_one && !is_bit_nil(*max_one) && *max_one);
1212 424 : BBPunfix(L->batCacheid);
1213 424 : BBPunfix(R->batCacheid);
1214 424 : BBPreclaim(sl);
1215 424 : BBPreclaim(sr);
1216 424 : if (ret != GDK_SUCCEED)
1217 0 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1218 424 : *l = bn1->batCacheid;
1219 424 : BBPkeepref(bn1);
1220 424 : if (r) {
1221 424 : *r = bn2->batCacheid;
1222 424 : BBPkeepref(bn2);
1223 : }
1224 : return MAL_SUCCEED;
1225 : }
1226 :
1227 : static str
1228 1979300 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1229 : {
1230 1979300 : BAT *l, *r1, *r2 = NULL, *bn;
1231 :
1232 1979300 : if ((l = BATdescriptor(*lid)) == NULL) {
1233 0 : throw(MAL, "algebra.projection",
1234 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1235 : }
1236 1992013 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1237 0 : BBPunfix(l->batCacheid);
1238 0 : throw(MAL, "algebra.projection",
1239 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1240 : }
1241 1991209 : 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 1991209 : bn = BATproject2(l, r1, r2);
1248 1975943 : BBPunfix(l->batCacheid);
1249 1989886 : BBPunfix(r1->batCacheid);
1250 1990464 : BBPreclaim(r2);
1251 1989784 : if (bn == NULL)
1252 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1253 1989784 : *result = bn->batCacheid;
1254 1989784 : BBPkeepref(bn);
1255 1989784 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : str
1259 1981229 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1260 : {
1261 1981229 : return ALGprojection2(result, lid, rid, NULL);
1262 : }
1263 :
1264 : static str
1265 27208 : 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 27208 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1270 27208 : BAT *b = NULL, *o = NULL, *g = NULL;
1271 :
1272 27208 : if ((b = BATdescriptor(*bid)) == NULL)
1273 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1274 27209 : 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 27209 : 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 30958 : if (BATsort(result ? &bn : NULL,
1284 : norder ? &on : NULL,
1285 : ngroup ? &gn : NULL,
1286 27209 : 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 27209 : BBPunfix(b->batCacheid);
1293 27209 : BBPreclaim(o);
1294 27209 : BBPreclaim(g);
1295 27209 : if (result) {
1296 27209 : *result = bn->batCacheid;
1297 27209 : BBPkeepref(bn);
1298 : }
1299 27209 : if (norder) {
1300 23460 : *norder = on->batCacheid;
1301 23460 : BBPkeepref(on);
1302 : }
1303 27209 : if (ngroup) {
1304 14120 : *ngroup = gn->batCacheid;
1305 14120 : BBPkeepref(gn);
1306 : }
1307 : return MAL_SUCCEED;
1308 : }
1309 :
1310 : static str
1311 4307 : 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 4307 : 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 6645 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1354 : const bit *reverse, const bit *nilslast, const bit *stable)
1355 : {
1356 6645 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1357 : stable);
1358 : }
1359 :
1360 : static str
1361 5033 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1362 : const bit *nilslast, const bit *stable)
1363 : {
1364 5033 : return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast,
1365 : stable);
1366 : }
1367 :
1368 : static str
1369 1671 : ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast,
1370 : const bit *stable)
1371 : {
1372 1671 : return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast,
1373 : stable);
1374 : }
1375 :
1376 : static str
1377 71379 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1378 : const bit *ignore_nils)
1379 : {
1380 71379 : BAT *b, *s = NULL;
1381 :
1382 71379 : if ((b = BATdescriptor(*bid)) == NULL) {
1383 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1384 : }
1385 71623 : 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 71623 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1390 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1391 71593 : } else if (*ignore_nils) {
1392 1767 : *result = (lng) BATcount_no_nil(b, s);
1393 : } else {
1394 69826 : struct canditer ci;
1395 69826 : canditer_init(&ci, b, s);
1396 69794 : *result = (lng) ci.ncand;
1397 : }
1398 71591 : BBPreclaim(s);
1399 71591 : BBPunfix(b->batCacheid);
1400 71591 : return MAL_SUCCEED;
1401 : }
1402 :
1403 : static str
1404 1767 : ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils)
1405 : {
1406 1767 : 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 69601 : ALGcount_bat(lng *result, const bat *bid)
1417 : {
1418 69601 : 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 17455 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1482 : {
1483 17455 : BAT *b, *bn;
1484 17455 : BUN s, e;
1485 :
1486 17455 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1487 0 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1488 17455 : if ((b = BBPquickdesc(*bid)) == NULL)
1489 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1490 17460 : s = (BUN) *start;
1491 17460 : if (s > BATcount(b))
1492 : s = BATcount(b);
1493 17460 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1494 17460 : if (e > BATcount(b))
1495 : e = BATcount(b);
1496 17460 : if (e < s)
1497 : e = s;
1498 17460 : bn = BATdense(0, b->hseqbase + s, e - s);
1499 17455 : if (bn == NULL)
1500 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1501 17455 : *ret = bn->batCacheid;
1502 17455 : BBPkeepref(bn);
1503 17455 : return MAL_SUCCEED;
1504 : }
1505 :
1506 : /*
1507 : * BUN Get/Fetch
1508 : */
1509 :
1510 : static str
1511 185984 : doALGfetch(ptr ret, BAT *b, BUN pos)
1512 : {
1513 185984 : assert(pos <= BUN_MAX);
1514 185984 : BATiter bi = bat_iterator(b);
1515 185984 : if (ATOMextern(b->ttype)) {
1516 200 : ptr _src = BUNtail(bi, pos);
1517 200 : size_t _len = ATOMlen(b->ttype, _src);
1518 200 : ptr _dst = GDKmalloc(_len);
1519 200 : if (_dst == NULL) {
1520 0 : bat_iterator_end(&bi);
1521 0 : throw(MAL, "doAlgFetch", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1522 : }
1523 200 : memcpy(_dst, _src, _len);
1524 200 : *(ptr *) ret = _dst;
1525 : } else {
1526 185784 : size_t _s = ATOMsize(ATOMtype(b->ttype));
1527 185784 : 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 185784 : } else if (_s == 4) {
1532 185697 : *(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 185984 : bat_iterator_end(&bi);
1548 185984 : return MAL_SUCCEED;
1549 : }
1550 :
1551 : static str
1552 185986 : ALGfetch(ptr ret, const bat *bid, const lng *pos)
1553 : {
1554 185986 : BAT *b;
1555 185986 : str msg;
1556 :
1557 185986 : if ((b = BATdescriptor(*bid)) == NULL) {
1558 0 : throw(MAL, "algebra.fetch", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1559 : }
1560 185986 : 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 185986 : 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 185984 : 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 185984 : msg = doALGfetch(ret, b, (BUN) *pos);
1577 185984 : BBPunfix(b->batCacheid);
1578 185984 : return msg;
1579 : }
1580 :
1581 : str
1582 185986 : ALGfetchoid(ptr ret, const bat *bid, const oid *pos)
1583 : {
1584 185986 : lng o = *pos;
1585 :
1586 185986 : 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 296724 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1629 : {
1630 296724 : bat *ret = getArgReference_bat(stk, pci, 0);
1631 296724 : bat bid = *getArgReference_bat(stk, pci, 1);
1632 296724 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1633 296724 : BAT *b, *bn;
1634 :
1635 296724 : (void) cntxt;
1636 296724 : (void) mb;
1637 296724 : if (isaBatType(getArgType(mb, pci, 2)))
1638 0 : throw(MAL, "algebra.project", "Scalar value expected");
1639 296724 : if ((b = BBPquickdesc(bid)) == NULL)
1640 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1641 297168 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1642 296954 : if (bn == NULL) {
1643 0 : *ret = bat_nil;
1644 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1645 : }
1646 296954 : *ret = bn->batCacheid;
1647 296954 : BBPkeepref(bn);
1648 296954 : 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 4 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1775 0 : throw(MAL, "aggr.covariance", GDK_EXCEPTION);
1776 4 : *res = covariance;
1777 4 : return MAL_SUCCEED;
1778 : }
1779 :
1780 : static str
1781 8 : ALGcovariancep(dbl *res, const bat *bid1, const bat *bid2)
1782 : {
1783 8 : BAT *b1, *b2;
1784 8 : dbl covariance;
1785 :
1786 8 : 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 8 : BBPunfix(b1->batCacheid);
1795 9 : BBPunfix(b2->batCacheid);
1796 8 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1797 1 : throw(MAL, "aggr.covariancep", GDK_EXCEPTION);
1798 7 : *res = covariance;
1799 7 : 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 18 : 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 351 : LIB_STARTUP_FUNC(init_algebra_mal)
1913 351 : { mal_module("algebra", NULL, algebra_init_funcs); }
|