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 774 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 774 : BAT *b;
143 774 : ptr p;
144 774 : str msg = MAL_SUCCEED;
145 :
146 774 : 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 774 : ALGminany(ptr result, const bat *bid)
171 : {
172 774 : bit skipnil = TRUE;
173 774 : 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 546 : 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 546 : if (ATOMextern(b->ttype)) {
192 65 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 481 : 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 548 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 548 : BBPunfix(b->batCacheid);
203 548 : 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 137417 : 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 137417 : BAT *b, *s = NULL, *bn;
265 :
266 137417 : if ((*li != 0 && *li != 1) ||
267 137417 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 :
271 137557 : if ((b = BATdescriptor(*bid)) == NULL) {
272 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
273 : }
274 138239 : 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 138261 : derefStr(b, low);
279 138261 : derefStr(b, high);
280 :
281 138261 : bool nanti = *anti, nli = *li, nhi = *hi;
282 :
283 : /* here we don't need open ended parts with nil */
284 138261 : 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 16 : low = high;
289 16 : nli = false;
290 : }
291 1572 : if (nhi && ATOMcmp(b->ttype, high, nilptr) == 0) {
292 17 : high = low;
293 17 : nhi = false;
294 : }
295 1572 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
296 10 : nanti = true;
297 : }
298 136687 : } else if (!*unknown) {
299 130484 : const void *nilptr = ATOMnilptr(b->ttype);
300 260565 : if (nli && nhi && nilptr != NULL &&
301 130510 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
302 24 : ATOMcmp(b->ttype, high, nilptr) == 0) {
303 : /* special case: equi-select for NIL */
304 137856 : high = NULL;
305 : }
306 : }
307 :
308 137856 : bn = BATselect(b, s, low, high, nli, nhi, nanti, false);
309 137134 : BBPunfix(b->batCacheid);
310 138147 : BBPreclaim(s);
311 138195 : if (bn == NULL)
312 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
313 138195 : *result = bn->batCacheid;
314 138195 : BBPkeepref(bn);
315 138195 : return MAL_SUCCEED;
316 : }
317 :
318 : static str
319 40835 : 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 40835 : return ALGselect2nil(result, bid, sid, low, high, li, hi, anti, &(bit){0});
323 : }
324 :
325 : static str
326 89099 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
327 : const bit *li, const bit *hi, const bit *anti)
328 : {
329 89099 : 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 518745 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
341 : const char **op)
342 : {
343 518745 : BAT *b, *s = NULL, *bn;
344 :
345 518745 : if ((b = BATdescriptor(*bid)) == NULL) {
346 0 : throw(MAL, "algebra.thetaselect",
347 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
348 : }
349 521008 : 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 521085 : derefStr(b, val);
355 521085 : bn = BATthetaselect(b, s, val, *op);
356 518863 : BBPunfix(b->batCacheid);
357 520806 : BBPreclaim(s);
358 520696 : if (bn == NULL)
359 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
360 520696 : *result = bn->batCacheid;
361 520696 : BBPkeepref(bn);
362 520696 : 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 1586 : ALGselectNotNil(bat *result, const bat *bid)
563 : {
564 1586 : BAT *b;
565 :
566 1586 : if ((b = BATdescriptor(*bid)) == NULL)
567 0 : throw(MAL, "algebra.selectNotNil",
568 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
569 :
570 1588 : MT_lock_set(&b->theaplock);
571 1587 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
572 1587 : MT_lock_unset(&b->theaplock);
573 1588 : 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 1463 : *result = b->batCacheid;
591 1463 : BBPkeepref(b);
592 1463 : return MAL_SUCCEED;
593 : }
594 :
595 : static str
596 652775 : 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 652775 : BAT *left = NULL, *right = NULL, *right2 = NULL;
616 652775 : BAT *candleft = NULL, *candright = NULL;
617 652775 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
618 652775 : BUN est;
619 652775 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
620 :
621 652775 : assert(r2id == NULL || rangefunc != NULL);
622 :
623 652775 : if ((left = BATdescriptor(*lid)) == NULL)
624 0 : goto fail;
625 659362 : if ((right = BATdescriptor(*rid)) == NULL)
626 0 : goto fail;
627 659412 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
628 0 : goto fail;
629 659411 : if (srid && !is_bat_nil(*srid)
630 0 : && (candright = BATdescriptor(*srid)) == NULL)
631 0 : goto fail;
632 659411 : 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 659411 : err = NULL; /* most likely error now is GDK_EXCEPTION */
639 :
640 659411 : if (thetafunc) {
641 51252 : assert(joinfunc == NULL);
642 51252 : assert(semifunc == NULL);
643 51252 : assert(markfunc == NULL);
644 51252 : assert(bandfunc == NULL);
645 51252 : assert(rangefunc == NULL);
646 51252 : assert(difffunc == NULL);
647 51252 : assert(interfunc == NULL);
648 51252 : if ((*thetafunc)
649 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
650 51252 : op, *nil_matches, est) != GDK_SUCCEED)
651 0 : goto fail;
652 608159 : } else if (joinfunc) {
653 417368 : assert(semifunc == NULL);
654 417368 : assert(markfunc == NULL);
655 417368 : assert(bandfunc == NULL);
656 417368 : assert(rangefunc == NULL);
657 417368 : assert(difffunc == NULL);
658 417368 : assert(interfunc == NULL);
659 417368 : if ((*joinfunc)
660 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
661 417368 : *nil_matches, est) != GDK_SUCCEED)
662 1 : goto fail;
663 190791 : } 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 190456 : } else if (markfunc) {
674 19551 : assert(bandfunc == NULL);
675 19551 : assert(rangefunc == NULL);
676 19551 : assert(difffunc == NULL);
677 19551 : assert(interfunc == NULL);
678 39097 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
679 : left, right, candleft, candright, est) != GDK_SUCCEED)
680 0 : goto fail;
681 170905 : } 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 170905 : } else if (rangefunc) {
690 146 : assert(difffunc == NULL);
691 146 : assert(interfunc == NULL);
692 146 : 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 170759 : } else if (difffunc) {
702 161051 : assert(r2 == NULL);
703 161051 : assert(interfunc == NULL);
704 160847 : if ((result1 = (*difffunc) (left, right, candleft, candright,
705 161051 : *nil_matches, *not_in, est)) == NULL)
706 0 : goto fail;
707 : } else {
708 9708 : assert(r2 == NULL);
709 9685 : if ((result1 = (*interfunc) (left, right, candleft, candright,
710 9708 : *nil_matches, *max_one, est)) == NULL)
711 1 : goto fail;
712 : }
713 655513 : *r1 = result1->batCacheid;
714 655513 : BBPkeepref(result1);
715 656995 : if (r2) {
716 381037 : *r2 = result2->batCacheid;
717 381037 : BBPkeepref(result2);
718 : }
719 657244 : if (r3) {
720 19483 : *r3 = result3->batCacheid;
721 19483 : BBPkeepref(result3);
722 : }
723 657286 : BBPunfix(left->batCacheid);
724 658861 : BBPunfix(right->batCacheid);
725 659159 : BBPreclaim(candleft);
726 659073 : 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 370321 : 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 370321 : 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 43242 : 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 43242 : 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 121 : 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 121 : 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 19451 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
815 : const bat *slid, const bat *srid, const lng *estimate)
816 : {
817 19451 : 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 7727 : 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 7727 : 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 41420 : 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 41420 : 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 115 : 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 237 : return do_join(r1, r2, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
883 115 : *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 21 : 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 46 : return do_join(r1, NULL, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
894 21 : *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 160887 : 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 160887 : 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 9701 : 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 9701 : 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 1718 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
932 : {
933 1718 : bat *ret1, *ret2 = NULL;
934 1718 : bat bid, sid, gid;
935 1718 : BAT *b, *s = NULL, *g = NULL;
936 1718 : BAT *bn = NULL, *gn = NULL;
937 1718 : lng n;
938 1718 : bit asc, nilslast, distinct;
939 1718 : gdk_return rc;
940 :
941 1718 : (void) cntxt;
942 1718 : (void) mb;
943 :
944 1718 : assert(pci->retc == 1 || pci->retc == 2);
945 1718 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
946 :
947 1718 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
948 1718 : if (n < 0)
949 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
950 1718 : if (n > (lng) BUN_MAX)
951 : n = BUN_MAX;
952 1718 : ret1 = getArgReference_bat(stk, pci, 0);
953 1718 : if (pci->retc == 2)
954 619 : ret2 = getArgReference_bat(stk, pci, 1);
955 1718 : bid = *getArgReference_bat(stk, pci, pci->retc);
956 1718 : 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 1719 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
960 1719 : if (!is_bat_nil(sid) && (s = BATdescriptor(sid)) == NULL) {
961 0 : BBPunfix(bid);
962 0 : throw(MAL, "algebra.firstn",
963 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
964 : }
965 1721 : if (pci->argc - pci->retc > 6) {
966 1721 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
967 1721 : if (!is_bat_nil(gid) && (g = BATdescriptor(gid)) == NULL) {
968 0 : BBPunfix(bid);
969 0 : BBPunfix(sid);
970 0 : throw(MAL, "algebra.firstn",
971 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
972 : }
973 : }
974 : }
975 1720 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
976 1720 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
977 1720 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
978 2821 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
979 : distinct);
980 1719 : BBPunfix(b->batCacheid);
981 1724 : BBPreclaim(s);
982 1722 : BBPreclaim(g);
983 1720 : if (rc != GDK_SUCCEED)
984 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
985 1720 : *ret1 = bn->batCacheid;
986 1720 : BBPkeepref(bn);
987 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 45358 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1121 : const bat *slid, const bat *srid, const bit *max_one)
1122 : {
1123 45358 : BAT *L, *R, *bn1, *bn2 = NULL;
1124 45358 : BAT *sl = NULL, *sr = NULL;
1125 45358 : gdk_return ret;
1126 :
1127 45358 : L = BATdescriptor(*left);
1128 46809 : R = BATdescriptor(*right);
1129 46858 : 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 46858 : 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 48673 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1145 46858 : max_one && !is_bit_nil(*max_one) && *max_one);
1146 46304 : BBPunfix(L->batCacheid);
1147 46743 : BBPunfix(R->batCacheid);
1148 46860 : BBPreclaim(sl);
1149 46862 : 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 46720 : if (r) {
1155 44923 : *r = bn2->batCacheid;
1156 44923 : BBPkeepref(bn2);
1157 : }
1158 : return MAL_SUCCEED;
1159 : }
1160 :
1161 : static str
1162 1752 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1163 : {
1164 1752 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1165 : }
1166 :
1167 : static str
1168 43669 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1169 : const bit *max_one)
1170 : {
1171 43669 : 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 1978815 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1229 : {
1230 1978815 : BAT *l, *r1, *r2 = NULL, *bn;
1231 :
1232 1978815 : if ((l = BATdescriptor(*lid)) == NULL) {
1233 0 : throw(MAL, "algebra.projection",
1234 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1235 : }
1236 1991397 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1237 0 : BBPunfix(l->batCacheid);
1238 0 : throw(MAL, "algebra.projection",
1239 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1240 : }
1241 1990671 : 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 1990671 : bn = BATproject2(l, r1, r2);
1248 1977338 : BBPunfix(l->batCacheid);
1249 1989448 : BBPunfix(r1->batCacheid);
1250 1989920 : BBPreclaim(r2);
1251 1989176 : if (bn == NULL)
1252 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1253 1989176 : *result = bn->batCacheid;
1254 1989176 : BBPkeepref(bn);
1255 1989176 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : str
1259 1980822 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1260 : {
1261 1980822 : return ALGprojection2(result, lid, rid, NULL);
1262 : }
1263 :
1264 : static str
1265 27217 : 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 27217 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1270 27217 : BAT *b = NULL, *o = NULL, *g = NULL;
1271 :
1272 27217 : if ((b = BATdescriptor(*bid)) == NULL)
1273 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1274 27218 : 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 27218 : 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 30967 : if (BATsort(result ? &bn : NULL,
1284 : norder ? &on : NULL,
1285 : ngroup ? &gn : NULL,
1286 27218 : 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 27218 : BBPunfix(b->batCacheid);
1293 27218 : BBPreclaim(o);
1294 27218 : BBPreclaim(g);
1295 27218 : if (result) {
1296 27218 : *result = bn->batCacheid;
1297 27218 : BBPkeepref(bn);
1298 : }
1299 27218 : if (norder) {
1300 23469 : *norder = on->batCacheid;
1301 23469 : BBPkeepref(on);
1302 : }
1303 27218 : if (ngroup) {
1304 14123 : *ngroup = gn->batCacheid;
1305 14123 : 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 6646 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1354 : const bit *reverse, const bit *nilslast, const bit *stable)
1355 : {
1356 6646 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1357 : stable);
1358 : }
1359 :
1360 : static str
1361 5038 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1362 : const bit *nilslast, const bit *stable)
1363 : {
1364 5038 : 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 71462 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1378 : const bit *ignore_nils)
1379 : {
1380 71462 : BAT *b, *s = NULL;
1381 :
1382 71462 : if ((b = BATdescriptor(*bid)) == NULL) {
1383 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1384 : }
1385 71733 : 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 71733 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1390 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1391 71703 : } else if (*ignore_nils) {
1392 1767 : *result = (lng) BATcount_no_nil(b, s);
1393 : } else {
1394 69936 : struct canditer ci;
1395 69936 : canditer_init(&ci, b, s);
1396 69894 : *result = (lng) ci.ncand;
1397 : }
1398 71692 : BBPreclaim(s);
1399 71692 : BBPunfix(b->batCacheid);
1400 71692 : 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 69703 : ALGcount_bat(lng *result, const bat *bid)
1417 : {
1418 69703 : 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 17079 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1482 : {
1483 17079 : BAT *b, *bn;
1484 17079 : BUN s, e;
1485 :
1486 17079 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1487 2 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1488 17077 : if ((b = BBPquickdesc(*bid)) == NULL)
1489 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1490 17078 : s = (BUN) *start;
1491 17078 : if (s > BATcount(b))
1492 : s = BATcount(b);
1493 17078 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1494 17078 : if (e > BATcount(b))
1495 : e = BATcount(b);
1496 17078 : if (e < s)
1497 : e = s;
1498 17078 : bn = BATdense(0, b->hseqbase + s, e - s);
1499 17070 : if (bn == NULL)
1500 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1501 17070 : *ret = bn->batCacheid;
1502 17070 : BBPkeepref(bn);
1503 17070 : 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 296937 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1629 : {
1630 296937 : bat *ret = getArgReference_bat(stk, pci, 0);
1631 296937 : bat bid = *getArgReference_bat(stk, pci, 1);
1632 296937 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1633 296937 : BAT *b, *bn;
1634 :
1635 296937 : (void) cntxt;
1636 296937 : (void) mb;
1637 296937 : if (isaBatType(getArgType(mb, pci, 2)))
1638 0 : throw(MAL, "algebra.project", "Scalar value expected");
1639 296937 : if ((b = BBPquickdesc(bid)) == NULL)
1640 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1641 297347 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1642 297106 : if (bn == NULL) {
1643 0 : *ret = bat_nil;
1644 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1645 : }
1646 297106 : *ret = bn->batCacheid;
1647 297106 : BBPkeepref(bn);
1648 297106 : 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 4 : 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 351 : LIB_STARTUP_FUNC(init_algebra_mal)
1913 351 : { mal_module("algebra", NULL, algebra_init_funcs); }
|