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 728 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 728 : BAT *b;
143 728 : ptr p;
144 728 : str msg = MAL_SUCCEED;
145 :
146 728 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
147 0 : throw(MAL, "algebra.min", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 :
149 728 : 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 728 : if (ATOMextern(b->ttype)) {
155 34 : *(ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil);
156 : } else {
157 694 : p = BATmin_skipnil(b, result, *skipnil);
158 694 : if (p != result)
159 0 : msg = createException(MAL, "algebra.min",
160 : SQLSTATE(HY002) "INTERNAL ERROR");
161 : }
162 728 : if (msg == MAL_SUCCEED && p == NULL)
163 0 : msg = createException(MAL, "algebra.min", GDK_EXCEPTION);
164 : }
165 728 : BBPunfix(b->batCacheid);
166 728 : return msg;
167 : }
168 :
169 : static str
170 728 : ALGminany(ptr result, const bat *bid)
171 : {
172 728 : bit skipnil = TRUE;
173 728 : return ALGminany_skipnil(result, bid, &skipnil);
174 : }
175 :
176 : static str
177 484 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 484 : BAT *b;
180 484 : ptr p;
181 484 : str msg = MAL_SUCCEED;
182 :
183 484 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 484 : 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 484 : if (ATOMextern(b->ttype)) {
192 45 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 439 : p = BATmax_skipnil(b, result, *skipnil);
195 439 : if (p != result)
196 0 : msg = createException(MAL, "algebra.max",
197 : SQLSTATE(HY002) "INTERNAL ERROR");
198 : }
199 484 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 484 : BBPunfix(b->batCacheid);
203 484 : return msg;
204 : }
205 :
206 : static str
207 484 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 484 : bit skipnil = TRUE;
210 484 : 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 70837 : 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 70837 : BAT *b, *s = NULL, *bn;
265 :
266 70837 : if ((*li != 0 && *li != 1) ||
267 70837 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 1 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 :
271 70836 : if ((b = BATdescriptor(*bid)) == NULL) {
272 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
273 : }
274 70836 : 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 70835 : derefStr(b, low);
279 70835 : derefStr(b, high);
280 :
281 70835 : bool nanti = *anti, nli = *li, nhi = *hi;
282 :
283 : /* here we don't need open ended parts with nil */
284 70835 : if (!nanti && *unknown) {
285 1076 : const void *nilptr = ATOMnilptr(b->ttype);
286 1076 : if (nilptr) {
287 1076 : if (nli && ATOMcmp(b->ttype, low, nilptr) == 0) {
288 11 : low = high;
289 11 : nli = false;
290 : }
291 1076 : if (nhi && ATOMcmp(b->ttype, high, nilptr) == 0) {
292 11 : high = low;
293 11 : nhi = false;
294 : }
295 1076 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
296 7 : nanti = true;
297 : }
298 69759 : } else if (!*unknown) {
299 66678 : const void *nilptr = ATOMnilptr(b->ttype);
300 133204 : if (nli && nhi && nilptr != NULL &&
301 66549 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
302 24 : ATOMcmp(b->ttype, high, nilptr) == 0) {
303 : /* special case: equi-select for NIL */
304 70836 : high = NULL;
305 : }
306 : }
307 :
308 70836 : bn = BATselect(b, s, low, high, nli, nhi, nanti, false);
309 70839 : BBPunfix(b->batCacheid);
310 70832 : BBPreclaim(s);
311 70831 : if (bn == NULL)
312 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
313 70831 : *result = bn->batCacheid;
314 70831 : BBPkeepref(bn);
315 70831 : return MAL_SUCCEED;
316 : }
317 :
318 : static str
319 20748 : 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 20748 : return ALGselect2nil(result, bid, sid, low, high, li, hi, anti, &(bit){0});
323 : }
324 :
325 : static str
326 45937 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
327 : const bit *li, const bit *hi, const bit *anti)
328 : {
329 45937 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, &(bit){0});
330 : }
331 :
332 : static str
333 270 : 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 270 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown);
337 : }
338 :
339 : static str
340 352339 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
341 : const char **op)
342 : {
343 352339 : BAT *b, *s = NULL, *bn;
344 :
345 352339 : if ((b = BATdescriptor(*bid)) == NULL) {
346 0 : throw(MAL, "algebra.thetaselect",
347 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
348 : }
349 352330 : 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 352324 : derefStr(b, val);
355 352324 : bn = BATthetaselect(b, s, val, *op);
356 352305 : BBPunfix(b->batCacheid);
357 352327 : BBPreclaim(s);
358 352318 : if (bn == NULL)
359 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
360 352318 : *result = bn->batCacheid;
361 352318 : BBPkeepref(bn);
362 352318 : return MAL_SUCCEED;
363 : }
364 :
365 : static str
366 398 : ALGmarkselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
367 : {
368 398 : BAT *g = BATdescriptor(*gid); /* oid */
369 398 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
370 398 : BAT *p = BATdescriptor(*pid); /* bit */
371 398 : BAT *res1 = NULL, *res2 = NULL;
372 398 : bit any = *Any; /* any or normal comparison semantics */
373 :
374 398 : if (!g || !m || !p) {
375 0 : if (g) BBPreclaim(g);
376 0 : if (m) BBPreclaim(m);
377 0 : if (p) BBPreclaim(p);
378 0 : throw(MAL, "algebra.markselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
379 : }
380 398 : BUN nr = BATcount(g), q = 0;
381 :
382 398 : if ((res1 = COLnew(0, TYPE_oid, nr, TRANSIENT)) == NULL || (res2 = COLnew(0, TYPE_bit, nr, TRANSIENT)) == NULL) {
383 : BBPreclaim(g);
384 0 : BBPreclaim(m);
385 0 : BBPreclaim(p);
386 0 : if (res1) BBPreclaim(res1);
387 0 : throw(MAL, "algebra.markselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
388 : }
389 398 : assert(g->tsorted);
390 398 : oid *ri1 = Tloc(res1, 0);
391 398 : bit *ri2 = Tloc(res2, 0);
392 398 : bit *mi = Tloc(m, 0);
393 398 : bit *pi = Tloc(p, 0);
394 398 : oid cur = oid_nil;
395 :
396 398 : if (g->ttype == TYPE_void) { /* void case ? */
397 34 : oid c = g->hseqbase;
398 136 : for (BUN n = 0; n < nr; n++, c++) {
399 102 : ri1[q] = c;
400 102 : ri2[q] = FALSE;
401 102 : if (pi[n] == TRUE && mi[n] == TRUE)
402 7 : ri2[q] = TRUE;
403 95 : 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 102 : 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 398 : BATsetcount(res1, q);
438 398 : BATsetcount(res2, q);
439 398 : res1->tsorted = true;
440 398 : res1->tkey = true;
441 398 : res1->trevsorted = false;
442 398 : res2->tsorted = false;
443 398 : res2->trevsorted = false;
444 398 : res1->tnil = false;
445 398 : res1->tnonil = true;
446 398 : res2->tnonil = false;
447 398 : res2->tkey = false;
448 :
449 398 : BBPreclaim(g);
450 398 : BBPreclaim(m);
451 398 : BBPreclaim(p);
452 :
453 398 : BBPkeepref(res1);
454 398 : BBPkeepref(res2);
455 398 : *r1 = res1->batCacheid;
456 398 : *r2 = res2->batCacheid;
457 398 : return MAL_SUCCEED;
458 : }
459 :
460 : static str
461 38 : ALGouterselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
462 : {
463 38 : BAT *g = BATdescriptor(*gid); /* oid */
464 38 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
465 38 : BAT *p = BATdescriptor(*pid); /* bit */
466 38 : BAT *res1 = NULL, *res2 = NULL;
467 38 : bit any = *Any; /* any or normal comparison semantics */
468 :
469 38 : if (!g || !m || !p) {
470 0 : if (g) BBPreclaim(g);
471 0 : if (m) BBPreclaim(m);
472 0 : if (p) BBPreclaim(p);
473 0 : throw(MAL, "algebra.outerselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
474 : }
475 38 : BUN nr = BATcount(g), q = 0;
476 :
477 38 : if ((res1 = COLnew(0, TYPE_oid, nr, TRANSIENT)) == NULL || (res2 = COLnew(0, TYPE_bit, nr, TRANSIENT)) == NULL) {
478 : BBPreclaim(g);
479 0 : BBPreclaim(m);
480 0 : BBPreclaim(p);
481 0 : if (res1) BBPreclaim(res1);
482 0 : throw(MAL, "algebra.outerselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
483 : }
484 38 : assert(g->tsorted);
485 38 : oid *ri1 = Tloc(res1, 0);
486 38 : bit *ri2 = Tloc(res2, 0);
487 38 : bit *mi = Tloc(m, 0);
488 38 : bit *pi = Tloc(p, 0);
489 38 : oid cur = oid_nil;
490 :
491 38 : if (g->ttype == TYPE_void) { /* void case ? */
492 12 : oid c = g->hseqbase;
493 101 : for (BUN n = 0; n < nr; n++, c++) {
494 89 : ri1[q] = c;
495 161 : ri2[q] = (any && (mi[n] == bit_nil || pi[n] == bit_nil))?bit_nil:(mi[n] == TRUE && pi[n] == TRUE)?TRUE:FALSE;
496 89 : q++;
497 : }
498 : } else {
499 26 : oid *gi = Tloc(g, 0);
500 26 : oid c = g->hseqbase;
501 26 : if (nr)
502 26 : cur = gi[0];
503 : bool used = false;
504 602 : for (BUN n = 0; n < nr; n++, c++) {
505 576 : if (c && cur != gi[n]) {
506 159 : if (!used) {
507 3 : ri1[q] = c-1;
508 3 : ri2[q] = false;
509 3 : q++;
510 : }
511 159 : used = false;
512 159 : cur = gi[n];
513 : }
514 576 : if (mi[n] == TRUE && pi[n] == TRUE) {
515 322 : ri1[q] = c;
516 322 : ri2[q] = TRUE;
517 322 : used = true;
518 322 : q++;
519 254 : } else if (mi[n] == FALSE) { /* empty */
520 55 : ri1[q] = c;
521 55 : ri2[q] = FALSE;
522 55 : used = true;
523 55 : q++;
524 199 : } else if (any && (mi[n] == bit_nil /* ie has nil */ || pi[n] == bit_nil)) {
525 6 : ri1[q] = c;
526 6 : ri2[q] = bit_nil;
527 6 : used = true;
528 6 : q++;
529 : }
530 : }
531 26 : if (nr && !used) {
532 1 : ri1[q] = c-1;
533 1 : ri2[q] = FALSE;
534 1 : q++;
535 : }
536 : }
537 38 : BATsetcount(res1, q);
538 38 : BATsetcount(res2, q);
539 38 : res1->tsorted = true;
540 38 : res1->tkey = true;
541 38 : res1->trevsorted = false;
542 38 : res2->tsorted = false;
543 38 : res2->trevsorted = false;
544 38 : res1->tnil = false;
545 38 : res1->tnonil = true;
546 38 : res2->tnonil = false;
547 38 : res2->tkey = false;
548 :
549 38 : BBPreclaim(g);
550 38 : BBPreclaim(m);
551 38 : BBPreclaim(p);
552 :
553 38 : BBPkeepref(res1);
554 38 : BBPkeepref(res2);
555 38 : *r1 = res1->batCacheid;
556 38 : *r2 = res2->batCacheid;
557 38 : return MAL_SUCCEED;
558 : }
559 :
560 :
561 : static str
562 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 99 : BAT *s;
575 99 : s = BATselect(b, NULL, ATOMnilptr(b->ttype), NULL, true, true, true, false);
576 99 : if (s) {
577 99 : BAT *bn = BATproject(s, b);
578 99 : BBPunfix(s->batCacheid);
579 99 : if (bn) {
580 99 : BBPunfix(b->batCacheid);
581 99 : *result = bn->batCacheid;
582 99 : BBPkeepref(bn);
583 99 : 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 1488 : *result = b->batCacheid;
591 1488 : BBPkeepref(b);
592 1488 : return MAL_SUCCEED;
593 : }
594 :
595 : static str
596 345961 : 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 345961 : BAT *left = NULL, *right = NULL, *right2 = NULL;
616 345961 : BAT *candleft = NULL, *candright = NULL;
617 345961 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
618 345961 : BUN est;
619 345961 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
620 :
621 345961 : assert(r2id == NULL || rangefunc != NULL);
622 :
623 345961 : if ((left = BATdescriptor(*lid)) == NULL)
624 0 : goto fail;
625 345958 : if ((right = BATdescriptor(*rid)) == NULL)
626 0 : goto fail;
627 345952 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
628 0 : goto fail;
629 345953 : if (srid && !is_bat_nil(*srid)
630 0 : && (candright = BATdescriptor(*srid)) == NULL)
631 0 : goto fail;
632 345953 : 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 345953 : err = NULL; /* most likely error now is GDK_EXCEPTION */
639 :
640 345953 : if (thetafunc) {
641 16829 : assert(joinfunc == NULL);
642 16829 : assert(semifunc == NULL);
643 16829 : assert(markfunc == NULL);
644 16829 : assert(bandfunc == NULL);
645 16829 : assert(rangefunc == NULL);
646 16829 : assert(difffunc == NULL);
647 16829 : assert(interfunc == NULL);
648 16829 : if ((*thetafunc)
649 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
650 16829 : op, *nil_matches, est) != GDK_SUCCEED)
651 0 : goto fail;
652 329124 : } else if (joinfunc) {
653 219680 : assert(semifunc == NULL);
654 219680 : assert(markfunc == NULL);
655 219680 : assert(bandfunc == NULL);
656 219680 : assert(rangefunc == NULL);
657 219680 : assert(difffunc == NULL);
658 219680 : assert(interfunc == NULL);
659 219680 : if ((*joinfunc)
660 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
661 219680 : *nil_matches, est) != GDK_SUCCEED)
662 1 : goto fail;
663 109444 : } 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 109109 : } else if (markfunc) {
674 9812 : assert(bandfunc == NULL);
675 9812 : assert(rangefunc == NULL);
676 9812 : assert(difffunc == NULL);
677 9812 : assert(interfunc == NULL);
678 19619 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
679 : left, right, candleft, candright, est) != GDK_SUCCEED)
680 0 : goto fail;
681 99297 : } 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 99297 : } else if (rangefunc) {
690 125 : assert(difffunc == NULL);
691 125 : assert(interfunc == NULL);
692 125 : if ((right2 = BATdescriptor(*r2id)) == NULL) {
693 0 : err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
694 0 : goto fail;
695 : }
696 148 : 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 125 : BBPunfix(right2->batCacheid);
701 99172 : } else if (difffunc) {
702 92994 : assert(r2 == NULL);
703 92994 : assert(interfunc == NULL);
704 92996 : if ((result1 = (*difffunc) (left, right, candleft, candright,
705 92994 : *nil_matches, *not_in, est)) == NULL)
706 0 : goto fail;
707 : } else {
708 6178 : assert(r2 == NULL);
709 6178 : if ((result1 = (*interfunc) (left, right, candleft, candright,
710 6178 : *nil_matches, *max_one, est)) == NULL)
711 1 : goto fail;
712 : }
713 345903 : *r1 = result1->batCacheid;
714 345903 : BBPkeepref(result1);
715 345860 : if (r2) {
716 197068 : *r2 = result2->batCacheid;
717 197068 : BBPkeepref(result2);
718 : }
719 345834 : if (r3) {
720 9810 : *r3 = result3->batCacheid;
721 9810 : BBPkeepref(result3);
722 : }
723 345833 : BBPunfix(left->batCacheid);
724 345873 : BBPunfix(right->batCacheid);
725 345888 : BBPreclaim(candleft);
726 345890 : 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 191774 : 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 191774 : 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 27262 : 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 27262 : 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 124 : 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 124 : 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 9807 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
815 : const bat *slid, const bat *srid, const lng *estimate)
816 : {
817 9807 : 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 4296 : 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 4296 : 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 12537 : 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 12537 : 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 102 : 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 204 : return do_join(r1, r2, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
883 102 : *li, *hi, *anti, *symmetric, NULL, NULL, NULL, estimate,
884 : NULL, NULL, NULL, NULL, NULL, BATrangejoin, NULL, NULL,
885 : "algebra.rangejoin");
886 : }
887 :
888 : static str
889 23 : ALGrangejoin1(bat *r1, const bat *lid, const bat *rlid, const bat *rhid,
890 : const bat *slid, const bat *srid, const bit *li, const bit *hi,
891 : const bit *anti, const bit *symmetric, const lng *estimate)
892 : {
893 46 : return do_join(r1, NULL, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
894 23 : *li, *hi, *anti, *symmetric, NULL, NULL, NULL, estimate,
895 : NULL, NULL, NULL, NULL, NULL, BATrangejoin, NULL, NULL,
896 : "algebra.rangejoin");
897 : }
898 :
899 : static str
900 92998 : 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 92998 : 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 6178 : 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 6178 : 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 1275 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
932 : {
933 1275 : bat *ret1, *ret2 = NULL;
934 1275 : bat bid, sid, gid;
935 1275 : BAT *b, *s = NULL, *g = NULL;
936 1275 : BAT *bn = NULL, *gn = NULL;
937 1275 : lng n;
938 1275 : bit asc, nilslast, distinct;
939 1275 : gdk_return rc;
940 :
941 1275 : (void) cntxt;
942 1275 : (void) mb;
943 :
944 1275 : assert(pci->retc == 1 || pci->retc == 2);
945 1275 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
946 :
947 1275 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
948 1275 : if (n < 0)
949 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
950 1275 : if (n > (lng) BUN_MAX)
951 : n = BUN_MAX;
952 1275 : ret1 = getArgReference_bat(stk, pci, 0);
953 1275 : if (pci->retc == 2)
954 512 : ret2 = getArgReference_bat(stk, pci, 1);
955 1275 : bid = *getArgReference_bat(stk, pci, pci->retc);
956 1275 : if ((b = BATdescriptor(bid)) == NULL)
957 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
958 1275 : if (pci->argc - pci->retc > 5) {
959 1275 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
960 1275 : 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 1275 : if (pci->argc - pci->retc > 6) {
966 1275 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
967 1275 : 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 1275 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
976 1275 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
977 1275 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
978 2038 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
979 : distinct);
980 1274 : BBPunfix(b->batCacheid);
981 1275 : BBPreclaim(s);
982 1275 : BBPreclaim(g);
983 1275 : if (rc != GDK_SUCCEED)
984 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
985 1275 : *ret1 = bn->batCacheid;
986 1275 : BBPkeepref(bn);
987 1275 : if (ret2) {
988 512 : *ret2 = gn->batCacheid;
989 512 : 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 27382 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1121 : const bat *slid, const bat *srid, const bit *max_one)
1122 : {
1123 27382 : BAT *L, *R, *bn1, *bn2 = NULL;
1124 27382 : BAT *sl = NULL, *sr = NULL;
1125 27382 : gdk_return ret;
1126 :
1127 27382 : L = BATdescriptor(*left);
1128 27383 : R = BATdescriptor(*right);
1129 27382 : 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 27382 : 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 28832 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1145 27382 : max_one && !is_bit_nil(*max_one) && *max_one);
1146 27373 : BBPunfix(L->batCacheid);
1147 27380 : BBPunfix(R->batCacheid);
1148 27382 : BBPreclaim(sl);
1149 27382 : BBPreclaim(sr);
1150 27383 : if (ret != GDK_SUCCEED)
1151 79 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1152 27304 : *l = bn1->batCacheid;
1153 27304 : BBPkeepref(bn1);
1154 27300 : if (r) {
1155 25857 : *r = bn2->batCacheid;
1156 25857 : BBPkeepref(bn2);
1157 : }
1158 : return MAL_SUCCEED;
1159 : }
1160 :
1161 : static str
1162 1450 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1163 : {
1164 1450 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1165 : }
1166 :
1167 : static str
1168 25933 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1169 : const bit *max_one)
1170 : {
1171 25933 : 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 426 : ALGoutercrossproduct3(bat *l, bat *r, const bat *left, const bat *right, const bat *slid, const bat *srid, const bit *max_one)
1190 : {
1191 426 : BAT *L, *R, *bn1, *bn2 = NULL;
1192 426 : BAT *sl = NULL, *sr = NULL;
1193 426 : gdk_return ret;
1194 :
1195 426 : L = BATdescriptor(*left);
1196 426 : R = BATdescriptor(*right);
1197 426 : 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 426 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1203 426 : (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 426 : ret = BAToutercross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1211 426 : max_one && !is_bit_nil(*max_one) && *max_one);
1212 426 : BBPunfix(L->batCacheid);
1213 426 : BBPunfix(R->batCacheid);
1214 426 : BBPreclaim(sl);
1215 426 : BBPreclaim(sr);
1216 426 : if (ret != GDK_SUCCEED)
1217 0 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1218 426 : *l = bn1->batCacheid;
1219 426 : BBPkeepref(bn1);
1220 426 : if (r) {
1221 426 : *r = bn2->batCacheid;
1222 426 : BBPkeepref(bn2);
1223 : }
1224 : return MAL_SUCCEED;
1225 : }
1226 :
1227 : static str
1228 1203263 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1229 : {
1230 1203263 : BAT *l, *r1, *r2 = NULL, *bn;
1231 :
1232 1203263 : if ((l = BATdescriptor(*lid)) == NULL) {
1233 0 : throw(MAL, "algebra.projection",
1234 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1235 : }
1236 1203254 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1237 0 : BBPunfix(l->batCacheid);
1238 0 : throw(MAL, "algebra.projection",
1239 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1240 : }
1241 1203119 : 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 1203119 : bn = BATproject2(l, r1, r2);
1248 1202867 : BBPunfix(l->batCacheid);
1249 1203195 : BBPunfix(r1->batCacheid);
1250 1203135 : BBPreclaim(r2);
1251 1203134 : if (bn == NULL)
1252 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1253 1203134 : *result = bn->batCacheid;
1254 1203134 : BBPkeepref(bn);
1255 1203134 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : str
1259 1203275 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1260 : {
1261 1203275 : return ALGprojection2(result, lid, rid, NULL);
1262 : }
1263 :
1264 : static str
1265 24783 : 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 24783 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1270 24783 : BAT *b = NULL, *o = NULL, *g = NULL;
1271 :
1272 24783 : if ((b = BATdescriptor(*bid)) == NULL)
1273 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1274 24783 : 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 24783 : 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 28532 : if (BATsort(result ? &bn : NULL,
1284 : norder ? &on : NULL,
1285 : ngroup ? &gn : NULL,
1286 24783 : 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 24783 : BBPunfix(b->batCacheid);
1293 24783 : BBPreclaim(o);
1294 24783 : BBPreclaim(g);
1295 24783 : if (result) {
1296 24783 : *result = bn->batCacheid;
1297 24783 : BBPkeepref(bn);
1298 : }
1299 24783 : if (norder) {
1300 21034 : *norder = on->batCacheid;
1301 21034 : BBPkeepref(on);
1302 : }
1303 24783 : if (ngroup) {
1304 14119 : *ngroup = gn->batCacheid;
1305 14119 : BBPkeepref(gn);
1306 : }
1307 : return MAL_SUCCEED;
1308 : }
1309 :
1310 : static str
1311 4306 : ALGsort32(bat *result, bat *norder, const bat *bid, const bat *order,
1312 : const bat *group, const bit *reverse, const bit *nilslast,
1313 : const bit *stable)
1314 : {
1315 4306 : return ALGsort33(result, norder, NULL, bid, order, group, reverse, nilslast,
1316 : stable);
1317 : }
1318 :
1319 : static str
1320 2078 : ALGsort31(bat *result, const bat *bid, const bat *order, const bat *group,
1321 : const bit *reverse, const bit *nilslast, const bit *stable)
1322 : {
1323 2078 : return ALGsort33(result, NULL, NULL, bid, order, group, reverse, nilslast,
1324 : stable);
1325 : }
1326 :
1327 : static str
1328 0 : ALGsort23(bat *result, bat *norder, bat *ngroup, const bat *bid,
1329 : const bat *order, const bit *reverse, const bit *nilslast,
1330 : const bit *stable)
1331 : {
1332 0 : return ALGsort33(result, norder, ngroup, bid, order, NULL, reverse,
1333 : nilslast, stable);
1334 : }
1335 :
1336 : static str
1337 0 : ALGsort22(bat *result, bat *norder, const bat *bid, const bat *order,
1338 : const bit *reverse, const bit *nilslast, const bit *stable)
1339 : {
1340 0 : return ALGsort33(result, norder, NULL, bid, order, NULL, reverse, nilslast,
1341 : stable);
1342 : }
1343 :
1344 : static str
1345 0 : ALGsort21(bat *result, const bat *bid, const bat *order, const bit *reverse,
1346 : const bit *nilslast, const bit *stable)
1347 : {
1348 0 : return ALGsort33(result, NULL, NULL, bid, order, NULL, reverse, nilslast,
1349 : stable);
1350 : }
1351 :
1352 : static str
1353 6644 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1354 : const bit *reverse, const bit *nilslast, const bit *stable)
1355 : {
1356 6644 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1357 : stable);
1358 : }
1359 :
1360 : static str
1361 2609 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1362 : const bit *nilslast, const bit *stable)
1363 : {
1364 2609 : 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 70825 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1378 : const bit *ignore_nils)
1379 : {
1380 70825 : BAT *b, *s = NULL;
1381 :
1382 70825 : if ((b = BATdescriptor(*bid)) == NULL) {
1383 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1384 : }
1385 70826 : 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 70826 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1390 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1391 70796 : } else if (*ignore_nils) {
1392 1721 : *result = (lng) BATcount_no_nil(b, s);
1393 : } else {
1394 69075 : struct canditer ci;
1395 69075 : canditer_init(&ci, b, s);
1396 69075 : *result = (lng) ci.ncand;
1397 : }
1398 70826 : BBPreclaim(s);
1399 70826 : BBPunfix(b->batCacheid);
1400 70826 : return MAL_SUCCEED;
1401 : }
1402 :
1403 : static str
1404 1720 : ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils)
1405 : {
1406 1720 : 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 69105 : ALGcount_bat(lng *result, const bat *bid)
1417 : {
1418 69105 : 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 17381 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1482 : {
1483 17381 : BAT *b, *bn;
1484 17381 : BUN s, e;
1485 :
1486 17381 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1487 2 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1488 17379 : if ((b = BBPquickdesc(*bid)) == NULL)
1489 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1490 17379 : s = (BUN) *start;
1491 17379 : if (s > BATcount(b))
1492 : s = BATcount(b);
1493 17379 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1494 17379 : if (e > BATcount(b))
1495 : e = BATcount(b);
1496 17379 : if (e < s)
1497 : e = s;
1498 17379 : bn = BATdense(0, b->hseqbase + s, e - s);
1499 17379 : if (bn == NULL)
1500 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1501 17379 : *ret = bn->batCacheid;
1502 17379 : BBPkeepref(bn);
1503 17379 : return MAL_SUCCEED;
1504 : }
1505 :
1506 : /*
1507 : * BUN Get/Fetch
1508 : */
1509 :
1510 : static str
1511 185400 : doALGfetch(ptr ret, BAT *b, BUN pos)
1512 : {
1513 185400 : assert(pos <= BUN_MAX);
1514 185400 : BATiter bi = bat_iterator(b);
1515 185400 : 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 185200 : size_t _s = ATOMsize(ATOMtype(b->ttype));
1527 185200 : 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 185200 : } else if (_s == 4) {
1532 185113 : *(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 185400 : bat_iterator_end(&bi);
1548 185400 : return MAL_SUCCEED;
1549 : }
1550 :
1551 : static str
1552 185402 : ALGfetch(ptr ret, const bat *bid, const lng *pos)
1553 : {
1554 185402 : BAT *b;
1555 185402 : str msg;
1556 :
1557 185402 : if ((b = BATdescriptor(*bid)) == NULL) {
1558 0 : throw(MAL, "algebra.fetch", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1559 : }
1560 185402 : 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 185402 : 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 185400 : 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 185400 : msg = doALGfetch(ret, b, (BUN) *pos);
1577 185400 : BBPunfix(b->batCacheid);
1578 185400 : return msg;
1579 : }
1580 :
1581 : str
1582 185402 : ALGfetchoid(ptr ret, const bat *bid, const oid *pos)
1583 : {
1584 185402 : lng o = *pos;
1585 :
1586 185402 : 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 180571 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1629 : {
1630 180571 : bat *ret = getArgReference_bat(stk, pci, 0);
1631 180571 : bat bid = *getArgReference_bat(stk, pci, 1);
1632 180571 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1633 180571 : BAT *b, *bn;
1634 :
1635 180571 : (void) cntxt;
1636 180571 : (void) mb;
1637 180571 : if (isaBatType(getArgType(mb, pci, 2)))
1638 0 : throw(MAL, "algebra.project", "Scalar value expected");
1639 180571 : if ((b = BBPquickdesc(bid)) == NULL)
1640 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1641 180560 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1642 180569 : if (bn == NULL) {
1643 0 : *ret = bat_nil;
1644 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1645 : }
1646 180569 : *ret = bn->batCacheid;
1647 180569 : BBPkeepref(bn);
1648 180569 : return MAL_SUCCEED;
1649 : }
1650 :
1651 :
1652 : static str
1653 0 : ALGreuse(bat *ret, const bat *bid)
1654 : {
1655 0 : BAT *b, *bn;
1656 0 : if ((b = BATdescriptor(*bid)) == NULL)
1657 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1658 :
1659 0 : if (!b->batTransient || b->batRestricted != BAT_WRITE) {
1660 0 : if (ATOMvarsized(b->ttype)) {
1661 0 : bn = BATwcopy(b);
1662 0 : if (bn == NULL) {
1663 0 : BBPunfix(b->batCacheid);
1664 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1665 : }
1666 : } else {
1667 0 : bn = COLnew(b->hseqbase, b->ttype, BATcount(b), TRANSIENT);
1668 0 : if (bn == NULL) {
1669 0 : BBPunfix(b->batCacheid);
1670 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1671 : }
1672 0 : BATsetcount(bn, BATcount(b));
1673 0 : bn->tsorted = false;
1674 0 : bn->trevsorted = false;
1675 0 : BATkey(bn, false);
1676 : }
1677 0 : *ret = bn->batCacheid;
1678 0 : BBPkeepref(bn);
1679 0 : BBPunfix(b->batCacheid);
1680 : } else
1681 0 : BBPkeepref(b);
1682 : return MAL_SUCCEED;
1683 : }
1684 :
1685 : /*
1686 : * BAT standard deviation
1687 : */
1688 : static str
1689 7 : ALGstdev(dbl *res, const bat *bid)
1690 : {
1691 7 : BAT *b;
1692 7 : dbl stdev;
1693 :
1694 7 : if ((b = BATdescriptor(*bid)) == NULL)
1695 0 : throw(MAL, "aggr.stdev", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1696 7 : stdev = BATcalcstdev_sample(NULL, b);
1697 7 : BBPunfix(b->batCacheid);
1698 7 : if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0])
1699 0 : throw(MAL, "aggr.stdev", GDK_EXCEPTION);
1700 7 : *res = stdev;
1701 7 : return MAL_SUCCEED;
1702 : }
1703 :
1704 : static str
1705 13 : ALGstdevp(dbl *res, const bat *bid)
1706 : {
1707 13 : BAT *b;
1708 13 : dbl stdev;
1709 :
1710 13 : if ((b = BATdescriptor(*bid)) == NULL)
1711 0 : throw(MAL, "aggr.stdevp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1712 13 : stdev = BATcalcstdev_population(NULL, b);
1713 13 : BBPunfix(b->batCacheid);
1714 13 : if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0])
1715 1 : throw(MAL, "aggr.stdevp", GDK_EXCEPTION);
1716 12 : *res = stdev;
1717 12 : return MAL_SUCCEED;
1718 : }
1719 :
1720 : /*
1721 : * BAT variance
1722 : */
1723 : static str
1724 2 : ALGvariance(dbl *res, const bat *bid)
1725 : {
1726 2 : BAT *b;
1727 2 : dbl variance;
1728 :
1729 2 : if ((b = BATdescriptor(*bid)) == NULL)
1730 0 : throw(MAL, "aggr.variance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1731 2 : variance = BATcalcvariance_sample(NULL, b);
1732 2 : BBPunfix(b->batCacheid);
1733 2 : if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0])
1734 0 : throw(MAL, "aggr.variance", GDK_EXCEPTION);
1735 2 : *res = variance;
1736 2 : return MAL_SUCCEED;
1737 : }
1738 :
1739 : static str
1740 5 : ALGvariancep(dbl *res, const bat *bid)
1741 : {
1742 5 : BAT *b;
1743 5 : dbl variance;
1744 :
1745 5 : if ((b = BATdescriptor(*bid)) == NULL)
1746 0 : throw(MAL, "aggr.variancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1747 5 : variance = BATcalcvariance_population(NULL, b);
1748 5 : BBPunfix(b->batCacheid);
1749 5 : if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0])
1750 1 : throw(MAL, "aggr.variancep", GDK_EXCEPTION);
1751 4 : *res = variance;
1752 4 : return MAL_SUCCEED;
1753 : }
1754 :
1755 : /*
1756 : * BAT covariance
1757 : */
1758 : static str
1759 5 : ALGcovariance(dbl *res, const bat *bid1, const bat *bid2)
1760 : {
1761 5 : BAT *b1, *b2;
1762 5 : dbl covariance;
1763 :
1764 5 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1765 0 : throw(MAL, "aggr.covariance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1766 5 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1767 0 : BBPunfix(b1->batCacheid);
1768 0 : throw(MAL, "aggr.covariance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1769 : }
1770 :
1771 5 : covariance = BATcalccovariance_sample(b1, b2);
1772 5 : BBPunfix(b1->batCacheid);
1773 5 : BBPunfix(b2->batCacheid);
1774 5 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1775 0 : throw(MAL, "aggr.covariance", GDK_EXCEPTION);
1776 5 : *res = covariance;
1777 5 : return MAL_SUCCEED;
1778 : }
1779 :
1780 : static str
1781 9 : ALGcovariancep(dbl *res, const bat *bid1, const bat *bid2)
1782 : {
1783 9 : BAT *b1, *b2;
1784 9 : dbl covariance;
1785 :
1786 9 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1787 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1788 9 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1789 0 : BBPunfix(b1->batCacheid);
1790 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1791 : }
1792 :
1793 9 : covariance = BATcalccovariance_population(b1, b2);
1794 9 : BBPunfix(b1->batCacheid);
1795 9 : BBPunfix(b2->batCacheid);
1796 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 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 350 : LIB_STARTUP_FUNC(init_algebra_mal)
1913 350 : { mal_module("algebra", NULL, algebra_init_funcs); }
|