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