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 770 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 770 : BAT *b;
143 770 : ptr p;
144 770 : str msg = MAL_SUCCEED;
145 :
146 770 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
147 0 : throw(MAL, "algebra.min", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 :
149 771 : 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 771 : if (ATOMextern(b->ttype)) {
155 42 : *(ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil);
156 : } else {
157 729 : p = BATmin_skipnil(b, result, *skipnil);
158 731 : if (p != result)
159 0 : msg = createException(MAL, "algebra.min",
160 : SQLSTATE(HY002) "INTERNAL ERROR");
161 : }
162 773 : if (msg == MAL_SUCCEED && p == NULL)
163 0 : msg = createException(MAL, "algebra.min", GDK_EXCEPTION);
164 : }
165 773 : BBPunfix(b->batCacheid);
166 773 : return msg;
167 : }
168 :
169 : static str
170 770 : ALGminany(ptr result, const bat *bid)
171 : {
172 770 : bit skipnil = TRUE;
173 770 : return ALGminany_skipnil(result, bid, &skipnil);
174 : }
175 :
176 : static str
177 541 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 541 : BAT *b;
180 541 : ptr p;
181 541 : str msg = MAL_SUCCEED;
182 :
183 541 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 541 : 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 541 : if (ATOMextern(b->ttype)) {
192 68 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 473 : p = BATmax_skipnil(b, result, *skipnil);
195 476 : if (p != result)
196 0 : msg = createException(MAL, "algebra.max",
197 : SQLSTATE(HY002) "INTERNAL ERROR");
198 : }
199 544 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 544 : BBPunfix(b->batCacheid);
203 544 : return msg;
204 : }
205 :
206 : static str
207 540 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 540 : bit skipnil = TRUE;
210 540 : 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 154286 : 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 154286 : BAT *b, *s = NULL, *bn;
264 154286 : const void *nilptr;
265 :
266 154286 : if ((*li != 0 && *li != 1) ||
267 154286 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 154400 : if ((b = BATdescriptor(*bid)) == NULL) {
271 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
272 : }
273 155079 : 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 155091 : derefStr(b, low);
278 155091 : derefStr(b, high);
279 155091 : nilptr = ATOMnilptr(b->ttype);
280 309572 : if (*li == 1 && *hi == 1 && nilptr != NULL &&
281 182399 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
282 27593 : ATOMcmp(b->ttype, high, nilptr) == 0) {
283 : /* special case: equi-select for NIL */
284 154766 : high = NULL;
285 : }
286 154766 : bn = BATselect(b, s, low, high, *li, *hi, *anti);
287 154129 : BBPunfix(b->batCacheid);
288 154876 : BBPreclaim(s);
289 154944 : if (bn == NULL)
290 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
291 154944 : *result = bn->batCacheid;
292 154944 : BBPkeepref(bn);
293 154944 : return MAL_SUCCEED;
294 : }
295 :
296 : static str
297 7363 : 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 7363 : BAT *b, *s = NULL, *bn;
302 7363 : bit nanti = *anti, nli = *li, nhi = *hi;
303 :
304 7363 : if (!*unknown)
305 0 : return ALGselect2(result, bid, sid, low, high, li, hi, anti);
306 :
307 7363 : if ((nli != 0 && nli != 1) ||
308 7363 : (nhi != 0 && nhi != 1) || (nanti != 0 && nanti != 1)) {
309 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
310 : }
311 7365 : if ((b = BATdescriptor(*bid)) == NULL) {
312 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
313 : }
314 7384 : 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 7386 : derefStr(b, low);
319 7386 : derefStr(b, high);
320 : /* here we don't need open ended parts with nil */
321 7386 : if (!nanti) {
322 1377 : const void *nilptr = ATOMnilptr(b->ttype);
323 1377 : if (nilptr) {
324 1377 : if (nli == 1 && ATOMcmp(b->ttype, low, nilptr) == 0) {
325 22 : low = high;
326 22 : nli = 0;
327 : }
328 1374 : if (nhi == 1 && ATOMcmp(b->ttype, high, nilptr) == 0) {
329 24 : high = low;
330 24 : nhi = 0;
331 : }
332 1377 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
333 7387 : nanti = 1;
334 : }
335 : }
336 :
337 7387 : bn = BATselect(b, s, low, high, nli, nhi, nanti);
338 7376 : BBPunfix(b->batCacheid);
339 7383 : BBPreclaim(s);
340 7383 : if (bn == NULL)
341 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
342 7383 : *result = bn->batCacheid;
343 7383 : BBPkeepref(bn);
344 7383 : return MAL_SUCCEED;
345 : }
346 :
347 : static str
348 103078 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
349 : const bit *li, const bit *hi, const bit *anti)
350 : {
351 103078 : return ALGselect2(result, bid, NULL, low, high, li, hi, anti);
352 : }
353 :
354 : static str
355 312 : 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 312 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown);
359 : }
360 :
361 : static str
362 490610 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
363 : const char **op)
364 : {
365 490610 : BAT *b, *s = NULL, *bn;
366 :
367 490610 : if ((b = BATdescriptor(*bid)) == NULL) {
368 0 : throw(MAL, "algebra.thetaselect",
369 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
370 : }
371 492817 : 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 493024 : derefStr(b, val);
377 493024 : bn = BATthetaselect(b, s, val, *op);
378 490564 : BBPunfix(b->batCacheid);
379 492601 : BBPreclaim(s);
380 492636 : if (bn == NULL)
381 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
382 492636 : *result = bn->batCacheid;
383 492636 : BBPkeepref(bn);
384 492636 : 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 1587 : ALGselectNotNil(bat *result, const bat *bid)
585 : {
586 1587 : BAT *b;
587 :
588 1587 : if ((b = BATdescriptor(*bid)) == NULL)
589 0 : throw(MAL, "algebra.selectNotNil",
590 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
591 :
592 1587 : MT_lock_set(&b->theaplock);
593 1587 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
594 1587 : MT_lock_unset(&b->theaplock);
595 1587 : if (!bnonil) {
596 123 : BAT *s;
597 123 : s = BATselect(b, NULL, ATOMnilptr(b->ttype), NULL, true, true, true);
598 120 : if (s) {
599 120 : BAT *bn = BATproject(s, b);
600 121 : BBPunfix(s->batCacheid);
601 123 : if (bn) {
602 123 : BBPunfix(b->batCacheid);
603 123 : *result = bn->batCacheid;
604 123 : BBPkeepref(bn);
605 123 : 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 1464 : *result = b->batCacheid;
613 1464 : BBPkeepref(b);
614 1464 : return MAL_SUCCEED;
615 : }
616 :
617 : static str
618 642466 : 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 642466 : BAT *left = NULL, *right = NULL, *right2 = NULL;
638 642466 : BAT *candleft = NULL, *candright = NULL;
639 642466 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
640 642466 : BUN est;
641 642466 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
642 :
643 642466 : assert(r2id == NULL || rangefunc != NULL);
644 :
645 642466 : if ((left = BATdescriptor(*lid)) == NULL)
646 0 : goto fail;
647 648791 : if ((right = BATdescriptor(*rid)) == NULL)
648 0 : goto fail;
649 648802 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
650 0 : goto fail;
651 648806 : if (srid && !is_bat_nil(*srid)
652 0 : && (candright = BATdescriptor(*srid)) == NULL)
653 0 : goto fail;
654 648806 : 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 648806 : err = NULL; /* most likely error now is GDK_EXCEPTION */
661 :
662 648806 : if (thetafunc) {
663 51329 : assert(joinfunc == NULL);
664 51329 : assert(semifunc == NULL);
665 51329 : assert(markfunc == NULL);
666 51329 : assert(bandfunc == NULL);
667 51329 : assert(rangefunc == NULL);
668 51329 : assert(difffunc == NULL);
669 51329 : assert(interfunc == NULL);
670 51329 : if ((*thetafunc)
671 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
672 51329 : op, *nil_matches, est) != GDK_SUCCEED)
673 0 : goto fail;
674 597477 : } else if (joinfunc) {
675 409101 : assert(semifunc == NULL);
676 409101 : assert(markfunc == NULL);
677 409101 : assert(bandfunc == NULL);
678 409101 : assert(rangefunc == NULL);
679 409101 : assert(difffunc == NULL);
680 409101 : assert(interfunc == NULL);
681 409101 : if ((*joinfunc)
682 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
683 409101 : *nil_matches, est) != GDK_SUCCEED)
684 1 : goto fail;
685 188376 : } 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 188044 : } else if (markfunc) {
696 19118 : assert(bandfunc == NULL);
697 19118 : assert(rangefunc == NULL);
698 19118 : assert(difffunc == NULL);
699 19118 : assert(interfunc == NULL);
700 38231 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
701 : left, right, candleft, candright, est) != GDK_SUCCEED)
702 0 : goto fail;
703 168926 : } 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 168926 : } else if (rangefunc) {
712 151 : assert(difffunc == NULL);
713 151 : assert(interfunc == NULL);
714 151 : if ((right2 = BATdescriptor(*r2id)) == NULL) {
715 0 : err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
716 0 : goto fail;
717 : }
718 176 : 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 148 : BBPunfix(right2->batCacheid);
723 168775 : } else if (difffunc) {
724 159510 : assert(r2 == NULL);
725 159510 : assert(interfunc == NULL);
726 159369 : if ((result1 = (*difffunc) (left, right, candleft, candright,
727 159510 : *nil_matches, *not_in, est)) == NULL)
728 0 : goto fail;
729 : } else {
730 9265 : assert(r2 == NULL);
731 9244 : if ((result1 = (*interfunc) (left, right, candleft, candright,
732 9265 : *nil_matches, *max_one, est)) == NULL)
733 1 : goto fail;
734 : }
735 644686 : *r1 = result1->batCacheid;
736 644686 : BBPkeepref(result1);
737 646924 : if (r2) {
738 374076 : *r2 = result2->batCacheid;
739 374076 : BBPkeepref(result2);
740 : }
741 647526 : if (r3) {
742 19046 : *r3 = result3->batCacheid;
743 19046 : BBPkeepref(result3);
744 : }
745 647559 : BBPunfix(left->batCacheid);
746 648176 : BBPunfix(right->batCacheid);
747 648579 : BBPreclaim(candleft);
748 648613 : 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 363300 : 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 363300 : 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 42192 : 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 42192 : 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 19059 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
837 : const bat *slid, const bat *srid, const lng *estimate)
838 : {
839 19059 : 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 7711 : 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 7711 : 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 41416 : 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 41416 : 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 122 : 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 248 : return do_join(r1, r2, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
905 122 : *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 24 : 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 49 : return do_join(r1, NULL, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
916 24 : *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 159450 : 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 159450 : 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 9266 : 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 9266 : 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 1614 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
954 : {
955 1614 : bat *ret1, *ret2 = NULL;
956 1614 : bat bid, sid, gid;
957 1614 : BAT *b, *s = NULL, *g = NULL;
958 1614 : BAT *bn = NULL, *gn = NULL;
959 1614 : lng n;
960 1614 : bit asc, nilslast, distinct;
961 1614 : gdk_return rc;
962 :
963 1614 : (void) cntxt;
964 1614 : (void) mb;
965 :
966 1614 : assert(pci->retc == 1 || pci->retc == 2);
967 1614 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
968 :
969 1614 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
970 1614 : if (n < 0)
971 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
972 1614 : if (n > (lng) BUN_MAX)
973 : n = BUN_MAX;
974 1614 : ret1 = getArgReference_bat(stk, pci, 0);
975 1614 : if (pci->retc == 2)
976 527 : ret2 = getArgReference_bat(stk, pci, 1);
977 1614 : bid = *getArgReference_bat(stk, pci, pci->retc);
978 1614 : if ((b = BATdescriptor(bid)) == NULL)
979 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
980 1614 : if (pci->argc - pci->retc > 5) {
981 1614 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
982 1614 : 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 1615 : if (pci->argc - pci->retc > 6) {
988 1615 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
989 1615 : 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 1615 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
998 1615 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
999 1615 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
1000 2702 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
1001 : distinct);
1002 1611 : BBPunfix(b->batCacheid);
1003 1616 : BBPreclaim(s);
1004 1615 : BBPreclaim(g);
1005 1616 : if (rc != GDK_SUCCEED)
1006 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
1007 1616 : *ret1 = bn->batCacheid;
1008 1616 : BBPkeepref(bn);
1009 1616 : if (ret2) {
1010 527 : *ret2 = gn->batCacheid;
1011 527 : 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 72 : ALGunique(bat *result, const bat *bid, const bat *sid)
1047 : {
1048 72 : BAT *b, *s = NULL, *bn = NULL;
1049 :
1050 72 : 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 73 : BBPunfix(b->batCacheid);
1059 73 : BBPreclaim(s);
1060 73 : if (bn == NULL)
1061 0 : throw(MAL, "algebra.unique", GDK_EXCEPTION);
1062 73 : *result = bn->batCacheid;
1063 73 : BBPkeepref(bn);
1064 73 : return MAL_SUCCEED;
1065 : }
1066 :
1067 : static str
1068 44787 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1069 : const bat *slid, const bat *srid, const bit *max_one)
1070 : {
1071 44787 : BAT *L, *R, *bn1, *bn2 = NULL;
1072 44787 : BAT *sl = NULL, *sr = NULL;
1073 44787 : gdk_return ret;
1074 :
1075 44787 : L = BATdescriptor(*left);
1076 46170 : R = BATdescriptor(*right);
1077 46241 : 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 46241 : 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 47992 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1093 46241 : max_one && !is_bit_nil(*max_one) && *max_one);
1094 45747 : BBPunfix(L->batCacheid);
1095 46130 : BBPunfix(R->batCacheid);
1096 46239 : BBPreclaim(sl);
1097 46239 : BBPreclaim(sr);
1098 46243 : if (ret != GDK_SUCCEED)
1099 86 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1100 46157 : *l = bn1->batCacheid;
1101 46157 : BBPkeepref(bn1);
1102 46097 : if (r) {
1103 44362 : *r = bn2->batCacheid;
1104 44362 : BBPkeepref(bn2);
1105 : }
1106 : return MAL_SUCCEED;
1107 : }
1108 :
1109 : static str
1110 1703 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1111 : {
1112 1703 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1113 : }
1114 :
1115 : static str
1116 43144 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1117 : const bit *max_one)
1118 : {
1119 43144 : 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 1972559 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1177 : {
1178 1972559 : BAT *l, *r1, *r2 = NULL, *bn;
1179 :
1180 1972559 : if ((l = BATdescriptor(*lid)) == NULL) {
1181 0 : throw(MAL, "algebra.projection",
1182 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1183 : }
1184 1984206 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1185 0 : BBPunfix(l->batCacheid);
1186 0 : throw(MAL, "algebra.projection",
1187 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1188 : }
1189 1983215 : 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 1983215 : bn = BATproject2(l, r1, r2);
1196 1959091 : BBPunfix(l->batCacheid);
1197 1979937 : BBPunfix(r1->batCacheid);
1198 1982983 : BBPreclaim(r2);
1199 1983154 : if (bn == NULL)
1200 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1201 1983154 : *result = bn->batCacheid;
1202 1983154 : BBPkeepref(bn);
1203 1983154 : return MAL_SUCCEED;
1204 : }
1205 :
1206 : str
1207 1974851 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1208 : {
1209 1974851 : return ALGprojection2(result, lid, rid, NULL);
1210 : }
1211 :
1212 : static str
1213 24063 : 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 24063 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1218 24063 : BAT *b = NULL, *o = NULL, *g = NULL;
1219 :
1220 24063 : if ((b = BATdescriptor(*bid)) == NULL)
1221 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1222 24065 : 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 24065 : 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 27666 : if (BATsort(result ? &bn : NULL,
1232 : norder ? &on : NULL,
1233 : ngroup ? &gn : NULL,
1234 24065 : 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 24065 : BBPunfix(b->batCacheid);
1241 24065 : BBPreclaim(o);
1242 24065 : BBPreclaim(g);
1243 24065 : if (result) {
1244 24065 : *result = bn->batCacheid;
1245 24065 : BBPkeepref(bn);
1246 : }
1247 24065 : if (norder) {
1248 20464 : *norder = on->batCacheid;
1249 20464 : BBPkeepref(on);
1250 : }
1251 24065 : if (ngroup) {
1252 13608 : *ngroup = gn->batCacheid;
1253 13608 : BBPkeepref(gn);
1254 : }
1255 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : static str
1259 4118 : 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 4118 : return ALGsort33(result, norder, NULL, bid, order, group, reverse, nilslast,
1264 : stable);
1265 : }
1266 :
1267 : static str
1268 1959 : ALGsort31(bat *result, const bat *bid, const bat *order, const bat *group,
1269 : const bit *reverse, const bit *nilslast, const bit *stable)
1270 : {
1271 1959 : 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 6332 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1302 : const bit *reverse, const bit *nilslast, const bit *stable)
1303 : {
1304 6332 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1305 : stable);
1306 : }
1307 :
1308 : static str
1309 2738 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1310 : const bit *nilslast, const bit *stable)
1311 : {
1312 2738 : return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast,
1313 : stable);
1314 : }
1315 :
1316 : static str
1317 1642 : ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast,
1318 : const bit *stable)
1319 : {
1320 1642 : return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast,
1321 : stable);
1322 : }
1323 :
1324 : static str
1325 70116 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1326 : const bit *ignore_nils)
1327 : {
1328 70116 : BAT *b, *s = NULL;
1329 :
1330 70116 : if ((b = BATdescriptor(*bid)) == NULL) {
1331 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1332 : }
1333 70359 : 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 70359 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1338 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1339 70329 : } else if (*ignore_nils) {
1340 1787 : *result = (lng) BATcount_no_nil(b, s);
1341 : } else {
1342 68542 : struct canditer ci;
1343 68542 : canditer_init(&ci, b, s);
1344 68583 : *result = (lng) ci.ncand;
1345 : }
1346 70400 : BBPreclaim(s);
1347 70400 : BBPunfix(b->batCacheid);
1348 70400 : return MAL_SUCCEED;
1349 : }
1350 :
1351 : static str
1352 1786 : ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils)
1353 : {
1354 1786 : 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 68340 : ALGcount_bat(lng *result, const bat *bid)
1365 : {
1366 68340 : 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 17225 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1430 : {
1431 17225 : BAT *b, *bn;
1432 17225 : BUN s, e;
1433 :
1434 17225 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1435 0 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1436 17226 : if ((b = BBPquickdesc(*bid)) == NULL)
1437 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1438 17225 : s = (BUN) *start;
1439 17225 : if (s > BATcount(b))
1440 : s = BATcount(b);
1441 17225 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1442 17225 : if (e > BATcount(b))
1443 : e = BATcount(b);
1444 17225 : if (e < s)
1445 : e = s;
1446 17225 : bn = BATdense(0, b->hseqbase + s, e - s);
1447 17227 : if (bn == NULL)
1448 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1449 17227 : *ret = bn->batCacheid;
1450 17227 : BBPkeepref(bn);
1451 17227 : 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 291059 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1577 : {
1578 291059 : bat *ret = getArgReference_bat(stk, pci, 0);
1579 291059 : bat bid = *getArgReference_bat(stk, pci, 1);
1580 291059 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1581 291059 : BAT *b, *bn;
1582 :
1583 291059 : (void) cntxt;
1584 291059 : (void) mb;
1585 291059 : if (isaBatType(getArgType(mb, pci, 2)))
1586 0 : throw(MAL, "algebra.project", "Scalar value expected");
1587 291059 : if ((b = BBPquickdesc(bid)) == NULL)
1588 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1589 290959 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1590 291160 : if (bn == NULL) {
1591 0 : *ret = bat_nil;
1592 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1593 : }
1594 291160 : *ret = bn->batCacheid;
1595 291160 : BBPkeepref(bn);
1596 291160 : 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 4 : ALGcovariance(dbl *res, const bat *bid1, const bat *bid2)
1708 : {
1709 4 : BAT *b1, *b2;
1710 4 : dbl covariance;
1711 :
1712 4 : 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 18 : ALGcorr(dbl *res, const bat *bid1, const bat *bid2)
1755 : {
1756 18 : BAT *b1, *b2;
1757 18 : dbl covariance;
1758 :
1759 18 : 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 18 : 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 321 : LIB_STARTUP_FUNC(init_algebra_mal)
1860 321 : { mal_module("algebra", NULL, algebra_init_funcs); }
|