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 480 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 480 : BAT *b;
180 480 : ptr p;
181 480 : str msg = MAL_SUCCEED;
182 :
183 480 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 480 : 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 480 : if (ATOMextern(b->ttype)) {
192 48 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 432 : p = BATmax_skipnil(b, result, *skipnil);
195 432 : if (p != result)
196 0 : msg = createException(MAL, "algebra.max",
197 : SQLSTATE(HY002) "INTERNAL ERROR");
198 : }
199 480 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 480 : BBPunfix(b->batCacheid);
203 480 : return msg;
204 : }
205 :
206 : static str
207 480 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 480 : bit skipnil = TRUE;
210 480 : 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 89154 : 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 89154 : BAT *b, *s = NULL, *bn;
264 89154 : const void *nilptr;
265 :
266 89154 : if ((*li != 0 && *li != 1) ||
267 89154 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 1 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 89153 : if ((b = BATdescriptor(*bid)) == NULL) {
271 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
272 : }
273 89157 : 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 89155 : derefStr(b, low);
278 89155 : derefStr(b, high);
279 89155 : nilptr = ATOMnilptr(b->ttype);
280 178158 : if (*li == 1 && *hi == 1 && nilptr != NULL &&
281 111806 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
282 22806 : ATOMcmp(b->ttype, high, nilptr) == 0) {
283 : /* special case: equi-select for NIL */
284 89156 : high = NULL;
285 : }
286 89156 : bn = BATselect(b, s, low, high, *li, *hi, *anti);
287 89156 : BBPunfix(b->batCacheid);
288 89157 : BBPreclaim(s);
289 89155 : if (bn == NULL)
290 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
291 89155 : *result = bn->batCacheid;
292 89155 : BBPkeepref(bn);
293 89155 : return MAL_SUCCEED;
294 : }
295 :
296 : static str
297 3964 : 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 3964 : BAT *b, *s = NULL, *bn;
302 3964 : bit nanti = *anti, nli = *li, nhi = *hi;
303 :
304 3964 : if (!*unknown)
305 0 : return ALGselect2(result, bid, sid, low, high, li, hi, anti);
306 :
307 3964 : if ((nli != 0 && nli != 1) ||
308 3964 : (nhi != 0 && nhi != 1) || (nanti != 0 && nanti != 1)) {
309 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
310 : }
311 3964 : if ((b = BATdescriptor(*bid)) == NULL) {
312 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
313 : }
314 3964 : 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 3964 : derefStr(b, low);
319 3964 : derefStr(b, high);
320 : /* here we don't need open ended parts with nil */
321 3964 : if (!nanti) {
322 886 : const void *nilptr = ATOMnilptr(b->ttype);
323 886 : if (nilptr) {
324 886 : if (nli == 1 && ATOMcmp(b->ttype, low, nilptr) == 0) {
325 16 : low = high;
326 16 : nli = 0;
327 : }
328 886 : if (nhi == 1 && ATOMcmp(b->ttype, high, nilptr) == 0) {
329 18 : high = low;
330 18 : nhi = 0;
331 : }
332 886 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
333 3964 : nanti = 1;
334 : }
335 : }
336 :
337 3964 : bn = BATselect(b, s, low, high, nli, nhi, nanti);
338 3964 : BBPunfix(b->batCacheid);
339 3964 : BBPreclaim(s);
340 3964 : if (bn == NULL)
341 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
342 3964 : *result = bn->batCacheid;
343 3964 : BBPkeepref(bn);
344 3964 : return MAL_SUCCEED;
345 : }
346 :
347 : static str
348 62592 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
349 : const bit *li, const bit *hi, const bit *anti)
350 : {
351 62592 : 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 338654 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
363 : const char **op)
364 : {
365 338654 : BAT *b, *s = NULL, *bn;
366 :
367 338654 : if ((b = BATdescriptor(*bid)) == NULL) {
368 0 : throw(MAL, "algebra.thetaselect",
369 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
370 : }
371 338652 : 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 338640 : derefStr(b, val);
377 338640 : bn = BATthetaselect(b, s, val, *op);
378 338625 : BBPunfix(b->batCacheid);
379 338651 : BBPreclaim(s);
380 338639 : if (bn == NULL)
381 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
382 338639 : *result = bn->batCacheid;
383 338639 : BBPkeepref(bn);
384 338639 : 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 1588 : ALGselectNotNil(bat *result, const bat *bid)
585 : {
586 1588 : BAT *b;
587 :
588 1588 : if ((b = BATdescriptor(*bid)) == NULL)
589 0 : throw(MAL, "algebra.selectNotNil",
590 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
591 :
592 1588 : MT_lock_set(&b->theaplock);
593 1588 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
594 1588 : MT_lock_unset(&b->theaplock);
595 1588 : 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 1491 : *result = b->batCacheid;
613 1491 : BBPkeepref(b);
614 1491 : return MAL_SUCCEED;
615 : }
616 :
617 : static str
618 342681 : 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 342681 : BAT *left = NULL, *right = NULL, *right2 = NULL;
638 342681 : BAT *candleft = NULL, *candright = NULL;
639 342681 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
640 342681 : BUN est;
641 342681 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
642 :
643 342681 : assert(r2id == NULL || rangefunc != NULL);
644 :
645 342681 : if ((left = BATdescriptor(*lid)) == NULL)
646 0 : goto fail;
647 342672 : if ((right = BATdescriptor(*rid)) == NULL)
648 0 : goto fail;
649 342661 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
650 0 : goto fail;
651 342661 : if (srid && !is_bat_nil(*srid)
652 0 : && (candright = BATdescriptor(*srid)) == NULL)
653 0 : goto fail;
654 342661 : 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 342661 : err = NULL; /* most likely error now is GDK_EXCEPTION */
661 :
662 342661 : if (thetafunc) {
663 16833 : assert(joinfunc == NULL);
664 16833 : assert(semifunc == NULL);
665 16833 : assert(markfunc == NULL);
666 16833 : assert(bandfunc == NULL);
667 16833 : assert(rangefunc == NULL);
668 16833 : assert(difffunc == NULL);
669 16833 : assert(interfunc == NULL);
670 16833 : if ((*thetafunc)
671 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
672 16833 : op, *nil_matches, est) != GDK_SUCCEED)
673 0 : goto fail;
674 325828 : } else if (joinfunc) {
675 217538 : assert(semifunc == NULL);
676 217538 : assert(markfunc == NULL);
677 217538 : assert(bandfunc == NULL);
678 217538 : assert(rangefunc == NULL);
679 217538 : assert(difffunc == NULL);
680 217538 : assert(interfunc == NULL);
681 217538 : if ((*joinfunc)
682 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
683 217538 : *nil_matches, est) != GDK_SUCCEED)
684 1 : goto fail;
685 108290 : } else if (semifunc) {
686 332 : assert(markfunc == NULL);
687 332 : assert(bandfunc == NULL);
688 332 : assert(rangefunc == NULL);
689 332 : assert(difffunc == NULL);
690 332 : assert(interfunc == NULL);
691 332 : if ((*semifunc)
692 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
693 332 : *nil_matches, *max_one, est) != GDK_SUCCEED)
694 42 : goto fail;
695 107958 : } else if (markfunc) {
696 9686 : assert(bandfunc == NULL);
697 9686 : assert(rangefunc == NULL);
698 9686 : assert(difffunc == NULL);
699 9686 : assert(interfunc == NULL);
700 19367 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
701 : left, right, candleft, candright, est) != GDK_SUCCEED)
702 0 : goto fail;
703 98272 : } 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 98272 : } 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 98143 : } else if (difffunc) {
724 92158 : assert(r2 == NULL);
725 92158 : assert(interfunc == NULL);
726 92154 : if ((result1 = (*difffunc) (left, right, candleft, candright,
727 92158 : *nil_matches, *not_in, est)) == NULL)
728 0 : goto fail;
729 : } else {
730 5985 : assert(r2 == NULL);
731 5985 : if ((result1 = (*interfunc) (left, right, candleft, candright,
732 5985 : *nil_matches, *max_one, est)) == NULL)
733 1 : goto fail;
734 : }
735 342601 : *r1 = result1->batCacheid;
736 342601 : BBPkeepref(result1);
737 342610 : if (r2) {
738 195690 : *r2 = result2->batCacheid;
739 195690 : BBPkeepref(result2);
740 : }
741 342593 : if (r3) {
742 9686 : *r3 = result3->batCacheid;
743 9686 : BBPkeepref(result3);
744 : }
745 342593 : BBPunfix(left->batCacheid);
746 342611 : BBPunfix(right->batCacheid);
747 342612 : BBPreclaim(candleft);
748 342612 : 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 190363 : 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 190363 : 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 26538 : 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 26538 : 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 123 : 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 123 : 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 9680 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
837 : const bat *slid, const bat *srid, const lng *estimate)
838 : {
839 9680 : 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 4298 : 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 4298 : 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 92162 : 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 92162 : 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 5985 : 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 5985 : 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 1269 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
954 : {
955 1269 : bat *ret1, *ret2 = NULL;
956 1269 : bat bid, sid, gid;
957 1269 : BAT *b, *s = NULL, *g = NULL;
958 1269 : BAT *bn = NULL, *gn = NULL;
959 1269 : lng n;
960 1269 : bit asc, nilslast, distinct;
961 1269 : gdk_return rc;
962 :
963 1269 : (void) cntxt;
964 1269 : (void) mb;
965 :
966 1269 : assert(pci->retc == 1 || pci->retc == 2);
967 1269 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
968 :
969 1269 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
970 1269 : if (n < 0)
971 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
972 1269 : if (n > (lng) BUN_MAX)
973 : n = BUN_MAX;
974 1269 : ret1 = getArgReference_bat(stk, pci, 0);
975 1269 : if (pci->retc == 2)
976 510 : ret2 = getArgReference_bat(stk, pci, 1);
977 1269 : bid = *getArgReference_bat(stk, pci, pci->retc);
978 1269 : if ((b = BATdescriptor(bid)) == NULL)
979 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
980 1269 : if (pci->argc - pci->retc > 5) {
981 1269 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
982 1269 : 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 1269 : if (pci->argc - pci->retc > 6) {
988 1269 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
989 1269 : 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 1269 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
998 1269 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
999 1269 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
1000 2028 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
1001 : distinct);
1002 1269 : BBPunfix(b->batCacheid);
1003 1268 : BBPreclaim(s);
1004 1269 : BBPreclaim(g);
1005 1269 : if (rc != GDK_SUCCEED)
1006 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
1007 1269 : *ret1 = bn->batCacheid;
1008 1269 : BBPkeepref(bn);
1009 1269 : if (ret2) {
1010 510 : *ret2 = gn->batCacheid;
1011 510 : 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 26749 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1069 : const bat *slid, const bat *srid, const bit *max_one)
1070 : {
1071 26749 : BAT *L, *R, *bn1, *bn2 = NULL;
1072 26749 : BAT *sl = NULL, *sr = NULL;
1073 26749 : gdk_return ret;
1074 :
1075 26749 : L = BATdescriptor(*left);
1076 26751 : R = BATdescriptor(*right);
1077 26751 : 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 26751 : 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 28138 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1093 26751 : max_one && !is_bit_nil(*max_one) && *max_one);
1094 26743 : BBPunfix(L->batCacheid);
1095 26750 : BBPunfix(R->batCacheid);
1096 26751 : BBPreclaim(sl);
1097 26751 : BBPreclaim(sr);
1098 26751 : if (ret != GDK_SUCCEED)
1099 77 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1100 26674 : *l = bn1->batCacheid;
1101 26674 : BBPkeepref(bn1);
1102 26671 : if (r) {
1103 25291 : *r = bn2->batCacheid;
1104 25291 : BBPkeepref(bn2);
1105 : }
1106 : return MAL_SUCCEED;
1107 : }
1108 :
1109 : static str
1110 1387 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1111 : {
1112 1387 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1113 : }
1114 :
1115 : static str
1116 25362 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1117 : const bit *max_one)
1118 : {
1119 25362 : 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 1193500 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1177 : {
1178 1193500 : BAT *l, *r1, *r2 = NULL, *bn;
1179 :
1180 1193500 : if ((l = BATdescriptor(*lid)) == NULL) {
1181 0 : throw(MAL, "algebra.projection",
1182 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1183 : }
1184 1193460 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1185 0 : BBPunfix(l->batCacheid);
1186 0 : throw(MAL, "algebra.projection",
1187 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1188 : }
1189 1193326 : 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 1193326 : bn = BATproject2(l, r1, r2);
1196 1192990 : BBPunfix(l->batCacheid);
1197 1193419 : BBPunfix(r1->batCacheid);
1198 1193378 : BBPreclaim(r2);
1199 1193385 : if (bn == NULL)
1200 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1201 1193385 : *result = bn->batCacheid;
1202 1193385 : BBPkeepref(bn);
1203 1193385 : return MAL_SUCCEED;
1204 : }
1205 :
1206 : str
1207 1193489 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1208 : {
1209 1193489 : return ALGprojection2(result, lid, rid, NULL);
1210 : }
1211 :
1212 : static str
1213 24130 : 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 24130 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1218 24130 : BAT *b = NULL, *o = NULL, *g = NULL;
1219 :
1220 24130 : if ((b = BATdescriptor(*bid)) == NULL)
1221 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1222 24130 : 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 24130 : 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 27858 : if (BATsort(result ? &bn : NULL,
1232 : norder ? &on : NULL,
1233 : ngroup ? &gn : NULL,
1234 24130 : 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 24130 : BBPunfix(b->batCacheid);
1241 24130 : BBPreclaim(o);
1242 24130 : BBPreclaim(g);
1243 24130 : if (result) {
1244 24130 : *result = bn->batCacheid;
1245 24130 : BBPkeepref(bn);
1246 : }
1247 24130 : if (norder) {
1248 20402 : *norder = on->batCacheid;
1249 20402 : BBPkeepref(on);
1250 : }
1251 24130 : if (ngroup) {
1252 13701 : *ngroup = gn->batCacheid;
1253 13701 : BBPkeepref(gn);
1254 : }
1255 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : static str
1259 4100 : 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 4100 : return ALGsort33(result, norder, NULL, bid, order, group, reverse, nilslast,
1264 : stable);
1265 : }
1266 :
1267 : static str
1268 2085 : ALGsort31(bat *result, const bat *bid, const bat *order, const bat *group,
1269 : const bit *reverse, const bit *nilslast, const bit *stable)
1270 : {
1271 2085 : 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 6440 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1302 : const bit *reverse, const bit *nilslast, const bit *stable)
1303 : {
1304 6440 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1305 : stable);
1306 : }
1307 :
1308 : static str
1309 2601 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1310 : const bit *nilslast, const bit *stable)
1311 : {
1312 2601 : return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast,
1313 : stable);
1314 : }
1315 :
1316 : static str
1317 1643 : ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast,
1318 : const bit *stable)
1319 : {
1320 1643 : return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast,
1321 : stable);
1322 : }
1323 :
1324 : static str
1325 69577 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1326 : const bit *ignore_nils)
1327 : {
1328 69577 : BAT *b, *s = NULL;
1329 :
1330 69577 : if ((b = BATdescriptor(*bid)) == NULL) {
1331 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1332 : }
1333 69576 : 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 69576 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1338 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1339 69546 : } else if (*ignore_nils) {
1340 1723 : *result = (lng) BATcount_no_nil(b, s);
1341 : } else {
1342 67823 : struct canditer ci;
1343 67823 : canditer_init(&ci, b, s);
1344 67824 : *result = (lng) ci.ncand;
1345 : }
1346 69577 : BBPreclaim(s);
1347 69577 : BBPunfix(b->batCacheid);
1348 69577 : 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 67854 : ALGcount_bat(lng *result, const bat *bid)
1365 : {
1366 67854 : 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 17160 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1430 : {
1431 17160 : BAT *b, *bn;
1432 17160 : BUN s, e;
1433 :
1434 17160 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1435 0 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1436 17160 : if ((b = BBPquickdesc(*bid)) == NULL)
1437 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1438 17160 : s = (BUN) *start;
1439 17160 : if (s > BATcount(b))
1440 : s = BATcount(b);
1441 17160 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1442 17160 : if (e > BATcount(b))
1443 : e = BATcount(b);
1444 17160 : if (e < s)
1445 : e = s;
1446 17160 : bn = BATdense(0, b->hseqbase + s, e - s);
1447 17160 : if (bn == NULL)
1448 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1449 17160 : *ret = bn->batCacheid;
1450 17160 : BBPkeepref(bn);
1451 17160 : 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 178609 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1577 : {
1578 178609 : bat *ret = getArgReference_bat(stk, pci, 0);
1579 178609 : bat bid = *getArgReference_bat(stk, pci, 1);
1580 178609 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1581 178609 : BAT *b, *bn;
1582 :
1583 178609 : (void) cntxt;
1584 178609 : (void) mb;
1585 178609 : if (isaBatType(getArgType(mb, pci, 2)))
1586 0 : throw(MAL, "algebra.project", "Scalar value expected");
1587 178609 : if ((b = BBPquickdesc(bid)) == NULL)
1588 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1589 178604 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1590 178608 : if (bn == NULL) {
1591 0 : *ret = bat_nil;
1592 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1593 : }
1594 178608 : *ret = bn->batCacheid;
1595 178608 : BBPkeepref(bn);
1596 178608 : 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 325 : LIB_STARTUP_FUNC(init_algebra_mal)
1860 325 : { mal_module("algebra", NULL, algebra_init_funcs); }
|