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 knowlegde 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 2361 : CMDgen_group(BAT **result, BAT *gids, BAT *cnts)
60 : {
61 2361 : BUN j;
62 2361 : BATiter gi = bat_iterator(gids);
63 2361 : BAT *r = COLnew(0, TYPE_oid, gi.count * 2, TRANSIENT);
64 :
65 2361 : if (r == NULL) {
66 0 : bat_iterator_end(&gi);
67 0 : return GDK_FAIL;
68 : }
69 2361 : BATiter ci = bat_iterator(cnts);
70 2361 : if (gi.type == TYPE_void) {
71 1022 : oid id = gi.tseq;
72 1022 : lng *cnt = (lng *) ci.base;
73 46312 : for (j = 0; j < gi.count; j++) {
74 45290 : lng i, sz = cnt[j];
75 90526 : for (i = 0; i < sz; i++) {
76 45236 : 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 45290 : id ++;
84 : }
85 : } else {
86 1339 : oid *id = (oid *) gi.base;
87 1339 : lng *cnt = (lng *) ci.base;
88 140533 : for (j = 0; j < gi.count; j++) {
89 139194 : lng i, sz = cnt[j];
90 274900 : for (i = 0; i < sz; i++) {
91 135706 : 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 139194 : id ++;
99 : }
100 : }
101 2361 : bat_iterator_end(&ci);
102 2361 : r->tkey = false;
103 2361 : r->tseqbase = oid_nil;
104 2361 : r->tsorted = gi.sorted;
105 2361 : r->trevsorted = gi.revsorted;
106 2361 : r->tnonil = gi.nonil;
107 2361 : bat_iterator_end(&gi);
108 2361 : *result = r;
109 2361 : 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 627 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 627 : BAT *b;
143 627 : ptr p;
144 627 : str msg = MAL_SUCCEED;
145 :
146 627 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
147 0 : throw(MAL, "algebra.min", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 :
149 627 : 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 627 : if (ATOMextern(b->ttype)) {
155 26 : *(ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil);
156 : } else {
157 601 : p = BATmin_skipnil(b, result, *skipnil);
158 601 : if (p != result)
159 0 : msg = createException(MAL, "algebra.min",
160 : SQLSTATE(HY002) "INTERNAL ERROR");
161 : }
162 627 : if (msg == MAL_SUCCEED && p == NULL)
163 0 : msg = createException(MAL, "algebra.min", GDK_EXCEPTION);
164 : }
165 627 : BBPunfix(b->batCacheid);
166 627 : return msg;
167 : }
168 :
169 : static str
170 627 : ALGminany(ptr result, const bat *bid)
171 : {
172 627 : bit skipnil = TRUE;
173 627 : return ALGminany_skipnil(result, bid, &skipnil);
174 : }
175 :
176 : static str
177 632 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 632 : BAT *b;
180 632 : ptr p;
181 632 : str msg = MAL_SUCCEED;
182 :
183 632 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 633 : 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 633 : if (ATOMextern(b->ttype)) {
192 51 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 582 : p = BATmax_skipnil(b, result, *skipnil);
195 582 : if (p != result)
196 0 : msg = createException(MAL, "algebra.max",
197 : SQLSTATE(HY002) "INTERNAL ERROR");
198 : }
199 633 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 633 : BBPunfix(b->batCacheid);
203 633 : return msg;
204 : }
205 :
206 : static str
207 632 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 632 : bit skipnil = TRUE;
210 632 : return ALGmaxany_skipnil(result, bid, &skipnil);
211 : }
212 :
213 : static str
214 2361 : ALGgroupby(bat *res, const bat *gids, const bat *cnts)
215 : {
216 2361 : BAT *bn, *g, *c;
217 :
218 2361 : g = BATdescriptor(*gids);
219 2361 : if (g == NULL) {
220 0 : throw(MAL, "algebra.groupby", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
221 : }
222 2361 : c = BATdescriptor(*cnts);
223 2361 : if (c == NULL) {
224 0 : BBPunfix(g->batCacheid);
225 0 : throw(MAL, "algebra.groupby", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
226 : }
227 2361 : 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 2361 : *res = bn->batCacheid;
233 2361 : BBPkeepref(bn);
234 2361 : BBPunfix(g->batCacheid);
235 2361 : BBPunfix(c->batCacheid);
236 2361 : 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 136622 : 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 136622 : BAT *b, *s = NULL, *bn;
264 136622 : const void *nilptr;
265 :
266 136622 : if ((*li != 0 && *li != 1) ||
267 136622 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 136767 : if ((b = BATdescriptor(*bid)) == NULL) {
271 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
272 : }
273 137500 : 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 137512 : derefStr(b, low);
278 137512 : derefStr(b, high);
279 137512 : nilptr = ATOMnilptr(b->ttype);
280 274214 : if (*li == 1 && *hi == 1 && nilptr != NULL &&
281 164866 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
282 27568 : ATOMcmp(b->ttype, high, nilptr) == 0) {
283 : /* special case: equi-select for NIL */
284 136916 : high = NULL;
285 : }
286 136916 : bn = BATselect(b, s, low, high, *li, *hi, *anti);
287 135985 : BBPunfix(b->batCacheid);
288 136952 : BBPreclaim(s);
289 137189 : if (bn == NULL)
290 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
291 137189 : *result = bn->batCacheid;
292 137189 : BBPkeepref(bn);
293 137189 : return MAL_SUCCEED;
294 : }
295 :
296 : static str
297 7339 : 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 7339 : BAT *b, *s = NULL, *bn;
302 7339 : bit nanti = *anti, nli = *li, nhi = *hi;
303 :
304 7339 : if (!*unknown)
305 0 : return ALGselect2(result, bid, sid, low, high, li, hi, anti);
306 :
307 7339 : if ((nli != 0 && nli != 1) ||
308 7339 : (nhi != 0 && nhi != 1) || (nanti != 0 && nanti != 1)) {
309 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
310 : }
311 7340 : if ((b = BATdescriptor(*bid)) == NULL) {
312 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
313 : }
314 7363 : 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 7368 : derefStr(b, low);
319 7368 : derefStr(b, high);
320 : /* here we don't need open ended parts with nil */
321 7368 : if (!nanti) {
322 1362 : const void *nilptr = ATOMnilptr(b->ttype);
323 1362 : if (nilptr) {
324 1362 : if (nli == 1 && ATOMcmp(b->ttype, low, nilptr) == 0) {
325 22 : low = high;
326 22 : nli = 0;
327 : }
328 1360 : if (nhi == 1 && ATOMcmp(b->ttype, high, nilptr) == 0) {
329 25 : high = low;
330 25 : nhi = 0;
331 : }
332 1359 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
333 7367 : nanti = 1;
334 : }
335 : }
336 :
337 7367 : bn = BATselect(b, s, low, high, nli, nhi, nanti);
338 7357 : BBPunfix(b->batCacheid);
339 7361 : BBPreclaim(s);
340 7363 : if (bn == NULL)
341 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
342 7363 : *result = bn->batCacheid;
343 7363 : BBPkeepref(bn);
344 7363 : return MAL_SUCCEED;
345 : }
346 :
347 : static str
348 83672 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
349 : const bit *li, const bit *hi, const bit *anti)
350 : {
351 83672 : return ALGselect2(result, bid, NULL, low, high, li, hi, anti);
352 : }
353 :
354 : static str
355 324 : 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 324 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown);
359 : }
360 :
361 : static str
362 380815 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
363 : const char **op)
364 : {
365 380815 : BAT *b, *s = NULL, *bn;
366 :
367 380815 : if ((b = BATdescriptor(*bid)) == NULL) {
368 0 : throw(MAL, "algebra.thetaselect",
369 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
370 : }
371 382858 : 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 383256 : derefStr(b, val);
377 383256 : bn = BATthetaselect(b, s, val, *op);
378 380356 : BBPunfix(b->batCacheid);
379 382437 : BBPreclaim(s);
380 382596 : if (bn == NULL)
381 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
382 382596 : *result = bn->batCacheid;
383 382596 : BBPkeepref(bn);
384 382596 : return MAL_SUCCEED;
385 : }
386 :
387 : static str
388 383 : ALGmarkselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
389 : {
390 383 : BAT *g = BATdescriptor(*gid); /* oid */
391 383 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
392 383 : BAT *p = BATdescriptor(*pid); /* bit */
393 383 : BAT *res1 = NULL, *res2 = NULL;
394 383 : bit any = *Any; /* any or normal comparision semantics */
395 :
396 383 : 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 383 : BUN nr = BATcount(g), q = 0;
403 :
404 383 : 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 383 : assert(g->tsorted);
412 383 : oid *ri1 = Tloc(res1, 0);
413 383 : bit *ri2 = Tloc(res2, 0);
414 383 : bit *mi = Tloc(m, 0);
415 383 : bit *pi = Tloc(p, 0);
416 383 : oid cur = oid_nil;
417 :
418 383 : if (g->ttype == TYPE_void) { /* void case ? */
419 30 : oid c = g->hseqbase;
420 113 : for (BUN n = 0; n < nr; n++, c++) {
421 83 : ri1[q] = c;
422 83 : ri2[q] = FALSE;
423 83 : if (pi[n] == TRUE && mi[n] == TRUE)
424 7 : ri2[q] = TRUE;
425 76 : 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 83 : q++;
428 : }
429 : } else {
430 353 : oid *gi = Tloc(g, 0);
431 353 : oid c = g->hseqbase;
432 353 : if (nr)
433 353 : cur = gi[0];
434 : bit m = FALSE;
435 : bool has_nil = false;
436 233385 : for (BUN n = 0; n < nr; n++, c++) {
437 233032 : if (c && cur != gi[n]) {
438 8030 : ri1[q] = c-1;
439 8030 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
440 8030 : q++;
441 8030 : cur = gi[n];
442 8030 : m = FALSE;
443 8030 : has_nil = false;
444 : }
445 233032 : if (m == TRUE)
446 192102 : continue;
447 :
448 40930 : if (pi[n] == TRUE && mi[n] == TRUE)
449 : m = TRUE;
450 33923 : else if ((mi[n] == bit_nil && pi[n] != bit_nil && !any) || (mi[n] != FALSE && pi[n] == bit_nil && any))
451 233032 : has_nil = true;
452 : }
453 353 : if (nr) {
454 353 : ri1[q] = c-1;
455 353 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
456 : }
457 353 : q++;
458 : }
459 383 : BATsetcount(res1, q);
460 383 : BATsetcount(res2, q);
461 383 : res1->tsorted = true;
462 383 : res1->tkey = true;
463 383 : res1->trevsorted = false;
464 383 : res2->tsorted = false;
465 383 : res2->trevsorted = false;
466 383 : res1->tnil = false;
467 383 : res1->tnonil = true;
468 383 : res2->tnonil = false;
469 383 : res2->tkey = false;
470 :
471 383 : BBPreclaim(g);
472 383 : BBPreclaim(m);
473 383 : BBPreclaim(p);
474 :
475 383 : BBPkeepref(res1);
476 383 : BBPkeepref(res2);
477 383 : *r1 = res1->batCacheid;
478 383 : *r2 = res2->batCacheid;
479 383 : return MAL_SUCCEED;
480 : }
481 :
482 : static str
483 36 : ALGouterselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
484 : {
485 36 : BAT *g = BATdescriptor(*gid); /* oid */
486 36 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
487 36 : BAT *p = BATdescriptor(*pid); /* bit */
488 36 : BAT *res1 = NULL, *res2 = NULL;
489 36 : bit any = *Any; /* any or normal comparision semantics */
490 :
491 36 : 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 36 : BUN nr = BATcount(g), q = 0;
498 :
499 36 : 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 36 : assert(g->tsorted);
507 36 : oid *ri1 = Tloc(res1, 0);
508 36 : bit *ri2 = Tloc(res2, 0);
509 36 : bit *mi = Tloc(m, 0);
510 36 : bit *pi = Tloc(p, 0);
511 36 : oid cur = oid_nil;
512 :
513 36 : 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 24 : oid *gi = Tloc(g, 0);
522 24 : oid c = g->hseqbase;
523 24 : if (nr)
524 24 : cur = gi[0];
525 : bool used = false;
526 597 : for (BUN n = 0; n < nr; n++, c++) {
527 573 : 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 573 : if (mi[n] == TRUE && pi[n] == TRUE) {
537 319 : ri1[q] = c;
538 319 : ri2[q] = TRUE;
539 319 : used = true;
540 319 : 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 24 : if (nr && !used) {
554 1 : ri1[q] = c-1;
555 1 : ri2[q] = FALSE;
556 1 : q++;
557 : }
558 : }
559 36 : BATsetcount(res1, q);
560 36 : BATsetcount(res2, q);
561 36 : res1->tsorted = true;
562 36 : res1->tkey = true;
563 36 : res1->trevsorted = false;
564 36 : res2->tsorted = false;
565 36 : res2->trevsorted = false;
566 36 : res1->tnil = false;
567 36 : res1->tnonil = true;
568 36 : res2->tnonil = false;
569 36 : res2->tkey = false;
570 :
571 36 : BBPreclaim(g);
572 36 : BBPreclaim(m);
573 36 : BBPreclaim(p);
574 :
575 36 : BBPkeepref(res1);
576 36 : BBPkeepref(res2);
577 36 : *r1 = res1->batCacheid;
578 36 : *r2 = res2->batCacheid;
579 36 : return MAL_SUCCEED;
580 : }
581 :
582 :
583 : static str
584 1540 : ALGselectNotNil(bat *result, const bat *bid)
585 : {
586 1540 : BAT *b;
587 :
588 1540 : if ((b = BATdescriptor(*bid)) == NULL)
589 0 : throw(MAL, "algebra.selectNotNil",
590 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
591 :
592 1540 : MT_lock_set(&b->theaplock);
593 1540 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
594 1540 : MT_lock_unset(&b->theaplock);
595 1540 : if (!bnonil) {
596 557 : BAT *s;
597 557 : s = BATselect(b, NULL, ATOMnilptr(b->ttype), NULL, true, true, true);
598 556 : if (s) {
599 556 : BAT *bn = BATproject(s, b);
600 557 : BBPunfix(s->batCacheid);
601 556 : if (bn) {
602 556 : BBPunfix(b->batCacheid);
603 557 : *result = bn->batCacheid;
604 557 : BBPkeepref(bn);
605 557 : 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 983 : *result = b->batCacheid;
613 983 : BBPkeepref(b);
614 983 : return MAL_SUCCEED;
615 : }
616 :
617 : static str
618 479855 : 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 479855 : BAT *left = NULL, *right = NULL, *right2 = NULL;
638 479855 : BAT *candleft = NULL, *candright = NULL;
639 479855 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
640 479855 : BUN est;
641 479855 : const char *err = RUNTIME_OBJECT_MISSING;
642 :
643 479855 : assert(r2id == NULL || rangefunc != NULL);
644 :
645 479855 : if ((left = BATdescriptor(*lid)) == NULL)
646 0 : goto fail;
647 485661 : if ((right = BATdescriptor(*rid)) == NULL)
648 0 : goto fail;
649 485894 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
650 0 : goto fail;
651 485900 : if (srid && !is_bat_nil(*srid)
652 0 : && (candright = BATdescriptor(*srid)) == NULL)
653 0 : goto fail;
654 485900 : 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 485900 : err = NULL; /* most likely error now is GDK_EXCEPTION */
661 :
662 485900 : if (thetafunc) {
663 50998 : assert(joinfunc == NULL);
664 50998 : assert(semifunc == NULL);
665 50998 : assert(markfunc == NULL);
666 50998 : assert(bandfunc == NULL);
667 50998 : assert(rangefunc == NULL);
668 50998 : assert(difffunc == NULL);
669 50998 : assert(interfunc == NULL);
670 50998 : if ((*thetafunc)
671 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
672 50998 : op, *nil_matches, est) != GDK_SUCCEED)
673 0 : goto fail;
674 434902 : } else if (joinfunc) {
675 336561 : assert(semifunc == NULL);
676 336561 : assert(markfunc == NULL);
677 336561 : assert(bandfunc == NULL);
678 336561 : assert(rangefunc == NULL);
679 336561 : assert(difffunc == NULL);
680 336561 : assert(interfunc == NULL);
681 336561 : if ((*joinfunc)
682 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
683 336561 : *nil_matches, est) != GDK_SUCCEED)
684 1 : goto fail;
685 98341 : } else if (semifunc) {
686 264 : assert(markfunc == NULL);
687 264 : assert(bandfunc == NULL);
688 264 : assert(rangefunc == NULL);
689 264 : assert(difffunc == NULL);
690 264 : assert(interfunc == NULL);
691 264 : if ((*semifunc)
692 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
693 264 : *nil_matches, *max_one, est) != GDK_SUCCEED)
694 40 : goto fail;
695 98077 : } else if (markfunc) {
696 4022 : assert(bandfunc == NULL);
697 4022 : assert(rangefunc == NULL);
698 4022 : assert(difffunc == NULL);
699 4022 : assert(interfunc == NULL);
700 8039 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
701 : left, right, candleft, candright, est) != GDK_SUCCEED)
702 0 : goto fail;
703 94055 : } 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 94055 : } else if (rangefunc) {
712 138 : assert(difffunc == NULL);
713 138 : assert(interfunc == NULL);
714 138 : if ((right2 = BATdescriptor(*r2id)) == NULL) {
715 0 : err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
716 0 : goto fail;
717 : }
718 164 : 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 133 : BBPunfix(right2->batCacheid);
723 93917 : } else if (difffunc) {
724 86574 : assert(r2 == NULL);
725 86574 : assert(interfunc == NULL);
726 86527 : if ((result1 = (*difffunc) (left, right, candleft, candright,
727 86574 : *nil_matches, *not_in, est)) == NULL)
728 0 : goto fail;
729 : } else {
730 7343 : assert(r2 == NULL);
731 7326 : if ((result1 = (*interfunc) (left, right, candleft, candright,
732 7343 : *nil_matches, *max_one, est)) == NULL)
733 1 : goto fail;
734 : }
735 481478 : *r1 = result1->batCacheid;
736 481478 : BBPkeepref(result1);
737 482074 : if (r2) {
738 301091 : *r2 = result2->batCacheid;
739 301091 : BBPkeepref(result2);
740 : }
741 483301 : if (r3) {
742 4008 : *r3 = result3->batCacheid;
743 4008 : BBPkeepref(result3);
744 : }
745 483310 : BBPunfix(left->batCacheid);
746 484210 : BBPunfix(right->batCacheid);
747 485280 : BBPreclaim(candleft);
748 485337 : BBPreclaim(candright);
749 : return MAL_SUCCEED;
750 :
751 42 : fail:
752 42 : BBPreclaim(left);
753 42 : BBPreclaim(right);
754 42 : BBPreclaim(right2);
755 42 : BBPreclaim(candleft);
756 42 : BBPreclaim(candright);
757 42 : if (err == NULL)
758 42 : throw(MAL, funcname, GDK_EXCEPTION);
759 0 : throw(MAL, funcname, "%s", err);
760 : }
761 :
762 : static str
763 291348 : 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 291348 : 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 41386 : 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 41386 : 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 72 : 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 72 : 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 191 : 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 191 : 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 3990 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
837 : const bat *slid, const bat *srid, const lng *estimate)
838 : {
839 3990 : 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 7525 : 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 7525 : 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 41162 : 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 41162 : 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 220 : 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 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 86532 : 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 86532 : 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 7341 : 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 7341 : 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 1744 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
954 : {
955 1744 : bat *ret1, *ret2 = NULL;
956 1744 : bat bid, sid, gid;
957 1744 : BAT *b, *s = NULL, *g = NULL;
958 1744 : BAT *bn = NULL, *gn = NULL;
959 1744 : lng n;
960 1744 : bit asc, nilslast, distinct;
961 1744 : gdk_return rc;
962 :
963 1744 : (void) cntxt;
964 1744 : (void) mb;
965 :
966 1744 : assert(pci->retc == 1 || pci->retc == 2);
967 1744 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
968 :
969 1744 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
970 1744 : if (n < 0)
971 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
972 1744 : if (n > (lng) BUN_MAX)
973 : n = BUN_MAX;
974 1744 : ret1 = getArgReference_bat(stk, pci, 0);
975 1744 : if (pci->retc == 2)
976 599 : ret2 = getArgReference_bat(stk, pci, 1);
977 1744 : bid = *getArgReference_bat(stk, pci, pci->retc);
978 1744 : if ((b = BATdescriptor(bid)) == NULL)
979 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
980 1745 : if (pci->argc - pci->retc > 5) {
981 1746 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
982 1746 : 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 1746 : if (pci->argc - pci->retc > 6) {
988 1746 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
989 1746 : 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 1745 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
998 1745 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
999 1745 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
1000 2891 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
1001 : distinct);
1002 1741 : BBPunfix(b->batCacheid);
1003 1738 : BBPreclaim(s);
1004 1738 : BBPreclaim(g);
1005 1740 : if (rc != GDK_SUCCEED)
1006 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1007 1740 : *ret1 = bn->batCacheid;
1008 1740 : BBPkeepref(bn);
1009 1735 : if (ret2) {
1010 597 : *ret2 = gn->batCacheid;
1011 597 : 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 65 : ALGunique(bat *result, const bat *bid, const bat *sid)
1047 : {
1048 65 : BAT *b, *s = NULL, *bn = NULL;
1049 :
1050 65 : if ((b = BATdescriptor(*bid)) == NULL) {
1051 0 : throw(MAL, "algebra.unique", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1052 : }
1053 65 : 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 65 : bn = BATunique(b, s);
1058 65 : BBPunfix(b->batCacheid);
1059 65 : BBPreclaim(s);
1060 65 : if (bn == NULL)
1061 0 : throw(MAL, "algebra.unique", GDK_EXCEPTION);
1062 65 : *result = bn->batCacheid;
1063 65 : BBPkeepref(bn);
1064 65 : return MAL_SUCCEED;
1065 : }
1066 :
1067 : static str
1068 44147 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1069 : const bat *slid, const bat *srid, const bit *max_one)
1070 : {
1071 44147 : BAT *L, *R, *bn1, *bn2 = NULL;
1072 44147 : BAT *sl = NULL, *sr = NULL;
1073 44147 : gdk_return ret;
1074 :
1075 44147 : L = BATdescriptor(*left);
1076 45569 : R = BATdescriptor(*right);
1077 45678 : 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 45678 : 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 47285 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1093 45678 : max_one && !is_bit_nil(*max_one) && *max_one);
1094 44881 : BBPunfix(L->batCacheid);
1095 45414 : BBPunfix(R->batCacheid);
1096 45660 : BBPreclaim(sl);
1097 45661 : BBPreclaim(sr);
1098 45651 : if (ret != GDK_SUCCEED)
1099 79 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1100 45572 : *l = bn1->batCacheid;
1101 45572 : BBPkeepref(bn1);
1102 45429 : if (r) {
1103 43832 : *r = bn2->batCacheid;
1104 43832 : BBPkeepref(bn2);
1105 : }
1106 : return MAL_SUCCEED;
1107 : }
1108 :
1109 : static str
1110 1550 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1111 : {
1112 1550 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1113 : }
1114 :
1115 : static str
1116 42666 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1117 : const bit *max_one)
1118 : {
1119 42666 : 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 409 : ALGoutercrossproduct3(bat *l, bat *r, const bat *left, const bat *right, const bat *slid, const bat *srid, const bit *max_one)
1138 : {
1139 409 : BAT *L, *R, *bn1, *bn2 = NULL;
1140 409 : BAT *sl = NULL, *sr = NULL;
1141 409 : gdk_return ret;
1142 :
1143 409 : L = BATdescriptor(*left);
1144 409 : R = BATdescriptor(*right);
1145 409 : 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 409 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1151 409 : (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 409 : ret = BAToutercross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1159 409 : max_one && !is_bit_nil(*max_one) && *max_one);
1160 409 : BBPunfix(L->batCacheid);
1161 409 : BBPunfix(R->batCacheid);
1162 409 : BBPreclaim(sl);
1163 409 : BBPreclaim(sr);
1164 409 : if (ret != GDK_SUCCEED)
1165 0 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1166 409 : *l = bn1->batCacheid;
1167 409 : BBPkeepref(bn1);
1168 409 : if (r) {
1169 409 : *r = bn2->batCacheid;
1170 409 : BBPkeepref(bn2);
1171 : }
1172 : return MAL_SUCCEED;
1173 : }
1174 :
1175 : static str
1176 1578629 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1177 : {
1178 1578629 : BAT *l, *r1, *r2 = NULL, *bn;
1179 :
1180 1578629 : if ((l = BATdescriptor(*lid)) == NULL) {
1181 0 : throw(MAL, "algebra.projection",
1182 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1183 : }
1184 1590193 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1185 0 : BBPunfix(l->batCacheid);
1186 0 : throw(MAL, "algebra.projection",
1187 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1188 : }
1189 1589657 : 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 1589657 : bn = BATproject2(l, r1, r2);
1196 1565717 : BBPunfix(l->batCacheid);
1197 1584673 : BBPunfix(r1->batCacheid);
1198 1588238 : BBPreclaim(r2);
1199 1588823 : if (bn == NULL)
1200 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1201 1588823 : *result = bn->batCacheid;
1202 1588823 : BBPkeepref(bn);
1203 1588823 : return MAL_SUCCEED;
1204 : }
1205 :
1206 : str
1207 1580492 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1208 : {
1209 1580492 : return ALGprojection2(result, lid, rid, NULL);
1210 : }
1211 :
1212 : static str
1213 22478 : 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 22478 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1218 22478 : BAT *b = NULL, *o = NULL, *g = NULL;
1219 :
1220 22478 : if ((b = BATdescriptor(*bid)) == NULL)
1221 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1222 22478 : 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 22478 : 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 26070 : if (BATsort(result ? &bn : NULL,
1232 : norder ? &on : NULL,
1233 : ngroup ? &gn : NULL,
1234 22478 : 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 22478 : BBPunfix(b->batCacheid);
1241 22478 : BBPreclaim(o);
1242 22478 : BBPreclaim(g);
1243 22478 : if (result) {
1244 22478 : *result = bn->batCacheid;
1245 22478 : BBPkeepref(bn);
1246 : }
1247 22478 : if (norder) {
1248 18886 : *norder = on->batCacheid;
1249 18886 : BBPkeepref(on);
1250 : }
1251 22478 : if (ngroup) {
1252 12528 : *ngroup = gn->batCacheid;
1253 12528 : BBPkeepref(gn);
1254 : }
1255 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : static str
1259 3746 : 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 3746 : return ALGsort33(result, norder, NULL, bid, order, group, reverse, nilslast,
1264 : stable);
1265 : }
1266 :
1267 : static str
1268 1937 : ALGsort31(bat *result, const bat *bid, const bat *order, const bat *group,
1269 : const bit *reverse, const bit *nilslast, const bit *stable)
1270 : {
1271 1937 : 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 5931 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1302 : const bit *reverse, const bit *nilslast, const bit *stable)
1303 : {
1304 5931 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1305 : stable);
1306 : }
1307 :
1308 : static str
1309 2612 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1310 : const bit *nilslast, const bit *stable)
1311 : {
1312 2612 : return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast,
1313 : stable);
1314 : }
1315 :
1316 : static str
1317 1655 : ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast,
1318 : const bit *stable)
1319 : {
1320 1655 : return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast,
1321 : stable);
1322 : }
1323 :
1324 : static str
1325 68112 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1326 : const bit *ignore_nils)
1327 : {
1328 68112 : BAT *b, *s = NULL;
1329 :
1330 68112 : if ((b = BATdescriptor(*bid)) == NULL) {
1331 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1332 : }
1333 68326 : 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 68326 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1338 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1339 68296 : } else if (*ignore_nils) {
1340 1933 : *result = (lng) BATcount_no_nil(b, s);
1341 : } else {
1342 66363 : struct canditer ci;
1343 66363 : canditer_init(&ci, b, s);
1344 66401 : *result = (lng) ci.ncand;
1345 : }
1346 68364 : BBPreclaim(s);
1347 68364 : BBPunfix(b->batCacheid);
1348 68364 : return MAL_SUCCEED;
1349 : }
1350 :
1351 : static str
1352 1931 : ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils)
1353 : {
1354 1931 : 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 66185 : ALGcount_bat(lng *result, const bat *bid)
1365 : {
1366 66185 : 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 17227 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1430 : {
1431 17227 : BAT *b, *bn;
1432 17227 : BUN s, e;
1433 :
1434 17227 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1435 0 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1436 17227 : if ((b = BBPquickdesc(*bid)) == NULL)
1437 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1438 17229 : s = (BUN) *start;
1439 17229 : if (s > BATcount(b))
1440 : s = BATcount(b);
1441 17229 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1442 17229 : if (e > BATcount(b))
1443 : e = BATcount(b);
1444 17229 : if (e < s)
1445 : e = s;
1446 17229 : bn = BATdense(0, b->hseqbase + s, e - s);
1447 17228 : if (bn == NULL)
1448 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1449 17228 : *ret = bn->batCacheid;
1450 17228 : BBPkeepref(bn);
1451 17228 : return MAL_SUCCEED;
1452 : }
1453 :
1454 : /*
1455 : * BUN Get/Fetch
1456 : */
1457 :
1458 : static str
1459 87801 : doALGfetch(ptr ret, BAT *b, BUN pos)
1460 : {
1461 87801 : assert(pos <= BUN_MAX);
1462 87801 : BATiter bi = bat_iterator(b);
1463 87801 : if (ATOMextern(b->ttype)) {
1464 150 : ptr _src = BUNtail(bi, pos);
1465 150 : size_t _len = ATOMlen(b->ttype, _src);
1466 150 : ptr _dst = GDKmalloc(_len);
1467 150 : if (_dst == NULL) {
1468 0 : bat_iterator_end(&bi);
1469 0 : throw(MAL, "doAlgFetch", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1470 : }
1471 150 : memcpy(_dst, _src, _len);
1472 150 : *(ptr *) ret = _dst;
1473 : } else {
1474 87651 : size_t _s = ATOMsize(ATOMtype(b->ttype));
1475 87651 : 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 87651 : } else if (_s == 4) {
1480 87573 : *(int *) ret = ((int *) bi.base)[pos];
1481 : } else if (_s == 1) {
1482 3 : *(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 74 : *(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 87801 : bat_iterator_end(&bi);
1496 87801 : return MAL_SUCCEED;
1497 : }
1498 :
1499 : static str
1500 87803 : ALGfetch(ptr ret, const bat *bid, const lng *pos)
1501 : {
1502 87803 : BAT *b;
1503 87803 : str msg;
1504 :
1505 87803 : if ((b = BATdescriptor(*bid)) == NULL) {
1506 0 : throw(MAL, "algebra.fetch", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1507 : }
1508 87803 : 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 87803 : 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 87801 : 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 87801 : msg = doALGfetch(ret, b, (BUN) *pos);
1525 87801 : BBPunfix(b->batCacheid);
1526 87801 : return msg;
1527 : }
1528 :
1529 : str
1530 87803 : ALGfetchoid(ptr ret, const bat *bid, const oid *pos)
1531 : {
1532 87803 : lng o = *pos;
1533 :
1534 87803 : 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 147074 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1577 : {
1578 147074 : bat *ret = getArgReference_bat(stk, pci, 0);
1579 147074 : bat bid = *getArgReference_bat(stk, pci, 1);
1580 147074 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1581 147074 : BAT *b, *bn;
1582 :
1583 147074 : (void) cntxt;
1584 147074 : (void) mb;
1585 147074 : if (isaBatType(getArgType(mb, pci, 2)))
1586 0 : throw(MAL, "algebra.project", "Scalar value expected");
1587 147074 : if ((b = BBPquickdesc(bid)) == NULL)
1588 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1589 147050 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1590 147077 : if (bn == NULL) {
1591 0 : *ret = bat_nil;
1592 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1593 : }
1594 147077 : *ret = bn->batCacheid;
1595 147077 : BBPkeepref(bn);
1596 147077 : 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 3 : ALGvariancep(dbl *res, const bat *bid)
1689 : {
1690 3 : BAT *b;
1691 3 : dbl variance;
1692 :
1693 3 : if ((b = BATdescriptor(*bid)) == NULL)
1694 0 : throw(MAL, "aggr.variancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1695 3 : variance = BATcalcvariance_population(NULL, b);
1696 3 : BBPunfix(b->batCacheid);
1697 3 : if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0])
1698 1 : throw(MAL, "aggr.variancep", GDK_EXCEPTION);
1699 2 : *res = variance;
1700 2 : 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 8 : ALGcovariancep(dbl *res, const bat *bid1, const bat *bid2)
1730 : {
1731 8 : BAT *b1, *b2;
1732 8 : dbl covariance;
1733 :
1734 8 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1735 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1736 8 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1737 0 : BBPunfix(b1->batCacheid);
1738 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1739 : }
1740 :
1741 8 : covariance = BATcalccovariance_population(b1, b2);
1742 8 : BBPunfix(b1->batCacheid);
1743 8 : BBPunfix(b2->batCacheid);
1744 8 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1745 1 : throw(MAL, "aggr.covariancep", GDK_EXCEPTION);
1746 7 : *res = covariance;
1747 7 : 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 atleast 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 334 : LIB_STARTUP_FUNC(init_algebra_mal)
1860 334 : { mal_module("algebra", NULL, algebra_init_funcs); }
|