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