Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * (c) Peter Boncz, Martin Kersten, Niels Nes, Sjoerd Mullender
15 : * BAT Algebra
16 : * This modules contains the most common algebraic BAT manipulation
17 : * commands. We call them algebra, because all operations take
18 : * values as parameters, and produce new result values, but
19 : * do not modify their parameters.
20 : *
21 : * Unlike the previous Monet versions, we reduce the number
22 : * of functions returning a BAT reference. This was previously needed
23 : * to simplify recursive bat-expression and manage reference counts.
24 : * In the current version we return only a BAT identifier when a new
25 : * bat is being created.
26 : *
27 : * All parameters to the modules are passed by reference.
28 : * In particular, this means that
29 : * string values are passed to the module layer as (str *)
30 : * and we have to de-reference them before entering the gdk library.
31 : * This calls for knowledge on the underlying BAT typs`s
32 : */
33 : #define derefStr(b, v) \
34 : do { \
35 : int _tpe= ATOMstorage((b)->ttype); \
36 : if (_tpe >= TYPE_str) { \
37 : if ((v) == 0 || *(str*) (v) == 0) \
38 : (v) = (str) str_nil; \
39 : else \
40 : (v) = *(str *) (v); \
41 : } \
42 : } while (0)
43 :
44 : #include "monetdb_config.h"
45 : #include "algebra.h"
46 :
47 : /*
48 : * Command Implementations in C
49 : * This module contains just a wrapper implementations; since all described
50 : * operations are part of the GDK kernel.
51 : *
52 : * BAT sum operation
53 : * The sum aggregate only works for int and float fields.
54 : * The routines below assumes that the caller knows what type
55 : * is large enough to prevent overflow.
56 : */
57 :
58 : static gdk_return
59 2388 : CMDgen_group(BAT **result, BAT *gids, BAT *cnts)
60 : {
61 2388 : BUN j;
62 2388 : BATiter gi = bat_iterator(gids);
63 2388 : BAT *r = COLnew(0, TYPE_oid, gi.count * 2, TRANSIENT);
64 :
65 2388 : if (r == NULL) {
66 0 : bat_iterator_end(&gi);
67 0 : return GDK_FAIL;
68 : }
69 2388 : BATiter ci = bat_iterator(cnts);
70 2388 : if (gi.type == TYPE_void) {
71 1049 : oid id = gi.tseq;
72 1049 : lng *cnt = (lng *) ci.base;
73 96195 : for (j = 0; j < gi.count; j++) {
74 95146 : lng i, sz = cnt[j];
75 190236 : for (i = 0; i < sz; i++) {
76 95090 : if (BUNappend(r, &id, false) != GDK_SUCCEED) {
77 0 : BBPreclaim(r);
78 0 : bat_iterator_end(&ci);
79 0 : bat_iterator_end(&gi);
80 0 : return GDK_FAIL;
81 : }
82 : }
83 95146 : id ++;
84 : }
85 : } else {
86 1339 : oid *id = (oid *) gi.base;
87 1339 : lng *cnt = (lng *) ci.base;
88 140494 : for (j = 0; j < gi.count; j++) {
89 139155 : lng i, sz = cnt[j];
90 274814 : for (i = 0; i < sz; i++) {
91 135659 : if (BUNappend(r, id, false) != GDK_SUCCEED) {
92 0 : BBPreclaim(r);
93 0 : bat_iterator_end(&ci);
94 0 : bat_iterator_end(&gi);
95 0 : return GDK_FAIL;
96 : }
97 : }
98 139155 : id ++;
99 : }
100 : }
101 2388 : bat_iterator_end(&ci);
102 2388 : r->tkey = false;
103 2388 : r->tseqbase = oid_nil;
104 2388 : r->tsorted = gi.sorted;
105 2388 : r->trevsorted = gi.revsorted;
106 2388 : r->tnonil = gi.nonil;
107 2388 : bat_iterator_end(&gi);
108 2388 : *result = r;
109 2388 : return GDK_SUCCEED;
110 : }
111 :
112 :
113 : static gdk_return
114 6 : slice(BAT **retval, BAT *b, lng start, lng end)
115 : {
116 : /* the internal BATslice requires exclusive end */
117 6 : if (start < 0) {
118 0 : GDKerror("start position of slice should >= 0\n");
119 0 : return GDK_FAIL;
120 : }
121 6 : if (is_lng_nil(end))
122 3 : end = BATcount(b);
123 :
124 6 : return (*retval = BATslice(b, (BUN) start, (BUN) end + 1)) ? GDK_SUCCEED : GDK_FAIL;
125 : }
126 :
127 : /*
128 : *
129 : * The remainder of this file contains the wrapper around the V4 code base
130 : * The BAT identifiers passed through this module may indicate
131 : * that the 'reverse' view applies. This should be taken into
132 : * account while resolving them.
133 : *
134 : * The sum aggregate only works for int and float fields.
135 : * The routines below assumes that the caller knows what type
136 : * is large enough to prevent overflow.
137 : */
138 :
139 : static str
140 772 : ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil)
141 : {
142 772 : BAT *b;
143 772 : ptr p;
144 772 : str msg = MAL_SUCCEED;
145 :
146 772 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
147 0 : throw(MAL, "algebra.min", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
148 :
149 773 : 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 773 : if (ATOMextern(b->ttype)) {
155 42 : *(ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil);
156 : } else {
157 731 : p = BATmin_skipnil(b, result, *skipnil);
158 731 : if (p != result)
159 0 : msg = createException(MAL, "algebra.min",
160 : SQLSTATE(HY002) "INTERNAL ERROR");
161 : }
162 773 : if (msg == MAL_SUCCEED && p == NULL)
163 0 : msg = createException(MAL, "algebra.min", GDK_EXCEPTION);
164 : }
165 773 : BBPunfix(b->batCacheid);
166 773 : return msg;
167 : }
168 :
169 : static str
170 772 : ALGminany(ptr result, const bat *bid)
171 : {
172 772 : bit skipnil = TRUE;
173 772 : return ALGminany_skipnil(result, bid, &skipnil);
174 : }
175 :
176 : static str
177 537 : ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil)
178 : {
179 537 : BAT *b;
180 537 : ptr p;
181 537 : str msg = MAL_SUCCEED;
182 :
183 537 : if (result == NULL || (b = BATdescriptor(*bid)) == NULL)
184 0 : throw(MAL, "algebra.max", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
185 :
186 542 : 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 542 : if (ATOMextern(b->ttype)) {
192 67 : *(ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil);
193 : } else {
194 475 : p = BATmax_skipnil(b, result, *skipnil);
195 476 : if (p != result)
196 0 : msg = createException(MAL, "algebra.max",
197 : SQLSTATE(HY002) "INTERNAL ERROR");
198 : }
199 543 : if (msg == MAL_SUCCEED && p == NULL)
200 0 : msg = createException(MAL, "algebra.max", GDK_EXCEPTION);
201 : }
202 543 : BBPunfix(b->batCacheid);
203 543 : return msg;
204 : }
205 :
206 : static str
207 537 : ALGmaxany(ptr result, const bat *bid)
208 : {
209 537 : bit skipnil = TRUE;
210 537 : 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 154008 : 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 154008 : BAT *b, *s = NULL, *bn;
264 154008 : const void *nilptr;
265 :
266 154008 : if ((*li != 0 && *li != 1) ||
267 154008 : (*hi != 0 && *hi != 1) || (*anti != 0 && *anti != 1)) {
268 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
269 : }
270 154138 : if ((b = BATdescriptor(*bid)) == NULL) {
271 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
272 : }
273 154860 : 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 154889 : derefStr(b, low);
278 154889 : derefStr(b, high);
279 154889 : nilptr = ATOMnilptr(b->ttype);
280 309109 : if (*li == 1 && *hi == 1 && nilptr != NULL &&
281 182124 : ATOMcmp(b->ttype, low, nilptr) == 0 &&
282 27506 : ATOMcmp(b->ttype, high, nilptr) == 0) {
283 : /* special case: equi-select for NIL */
284 154499 : high = NULL;
285 : }
286 154499 : bn = BATselect(b, s, low, high, *li, *hi, *anti);
287 153858 : BBPunfix(b->batCacheid);
288 154639 : BBPreclaim(s);
289 154723 : if (bn == NULL)
290 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
291 154723 : *result = bn->batCacheid;
292 154723 : BBPkeepref(bn);
293 154723 : return MAL_SUCCEED;
294 : }
295 :
296 : static str
297 7355 : 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 7355 : BAT *b, *s = NULL, *bn;
302 7355 : bit nanti = *anti, nli = *li, nhi = *hi;
303 :
304 7355 : if (!*unknown)
305 0 : return ALGselect2(result, bid, sid, low, high, li, hi, anti);
306 :
307 7355 : if ((nli != 0 && nli != 1) ||
308 7355 : (nhi != 0 && nhi != 1) || (nanti != 0 && nanti != 1)) {
309 0 : throw(MAL, "algebra.select", ILLEGAL_ARGUMENT);
310 : }
311 7358 : if ((b = BATdescriptor(*bid)) == NULL) {
312 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
313 : }
314 7382 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
315 0 : BBPunfix(b->batCacheid);
316 0 : throw(MAL, "algebra.select", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
317 : }
318 7386 : derefStr(b, low);
319 7386 : derefStr(b, high);
320 : /* here we don't need open ended parts with nil */
321 7386 : if (!nanti) {
322 1378 : const void *nilptr = ATOMnilptr(b->ttype);
323 1378 : if (nilptr) {
324 1378 : if (nli == 1 && ATOMcmp(b->ttype, low, nilptr) == 0) {
325 22 : low = high;
326 22 : nli = 0;
327 : }
328 1375 : if (nhi == 1 && ATOMcmp(b->ttype, high, nilptr) == 0) {
329 24 : high = low;
330 24 : nhi = 0;
331 : }
332 1376 : if (ATOMcmp(b->ttype, low, high) == 0 && ATOMcmp(b->ttype, high, nilptr) == 0) /* ugh sql nil != nil */
333 7385 : nanti = 1;
334 : }
335 : }
336 :
337 7385 : bn = BATselect(b, s, low, high, nli, nhi, nanti);
338 7369 : BBPunfix(b->batCacheid);
339 7381 : BBPreclaim(s);
340 7382 : if (bn == NULL)
341 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
342 7382 : *result = bn->batCacheid;
343 7382 : BBPkeepref(bn);
344 7382 : return MAL_SUCCEED;
345 : }
346 :
347 : static str
348 102952 : ALGselect1(bat *result, const bat *bid, const void *low, const void *high,
349 : const bit *li, const bit *hi, const bit *anti)
350 : {
351 102952 : return ALGselect2(result, bid, NULL, low, high, li, hi, anti);
352 : }
353 :
354 : static str
355 310 : 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 310 : return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown);
359 : }
360 :
361 : static str
362 489931 : ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val,
363 : const char **op)
364 : {
365 489931 : BAT *b, *s = NULL, *bn;
366 :
367 489931 : if ((b = BATdescriptor(*bid)) == NULL) {
368 0 : throw(MAL, "algebra.thetaselect",
369 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
370 : }
371 491950 : 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 492178 : derefStr(b, val);
377 492178 : bn = BATthetaselect(b, s, val, *op);
378 489618 : BBPunfix(b->batCacheid);
379 491720 : BBPreclaim(s);
380 491731 : if (bn == NULL)
381 0 : throw(MAL, "algebra.select", GDK_EXCEPTION);
382 491731 : *result = bn->batCacheid;
383 491731 : BBPkeepref(bn);
384 491731 : return MAL_SUCCEED;
385 : }
386 :
387 : static str
388 396 : ALGmarkselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
389 : {
390 396 : BAT *g = BATdescriptor(*gid); /* oid */
391 396 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
392 396 : BAT *p = BATdescriptor(*pid); /* bit */
393 396 : BAT *res1 = NULL, *res2 = NULL;
394 396 : bit any = *Any; /* any or normal comparison semantics */
395 :
396 396 : if (!g || !m || !p) {
397 0 : if (g) BBPreclaim(g);
398 0 : if (m) BBPreclaim(m);
399 0 : if (p) BBPreclaim(p);
400 0 : throw(MAL, "algebra.markselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
401 : }
402 396 : BUN nr = BATcount(g), q = 0;
403 :
404 396 : if ((res1 = COLnew(0, TYPE_oid, nr, TRANSIENT)) == NULL || (res2 = COLnew(0, TYPE_bit, nr, TRANSIENT)) == NULL) {
405 : BBPreclaim(g);
406 0 : BBPreclaim(m);
407 0 : BBPreclaim(p);
408 0 : if (res1) BBPreclaim(res1);
409 0 : throw(MAL, "algebra.markselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
410 : }
411 396 : assert(g->tsorted);
412 396 : oid *ri1 = Tloc(res1, 0);
413 396 : bit *ri2 = Tloc(res2, 0);
414 396 : bit *mi = Tloc(m, 0);
415 396 : bit *pi = Tloc(p, 0);
416 396 : oid cur = oid_nil;
417 :
418 396 : if (g->ttype == TYPE_void) { /* void case ? */
419 31 : oid c = g->hseqbase;
420 127 : for (BUN n = 0; n < nr; n++, c++) {
421 96 : ri1[q] = c;
422 96 : ri2[q] = FALSE;
423 96 : if (pi[n] == TRUE && mi[n] == TRUE)
424 7 : ri2[q] = TRUE;
425 89 : else if ((mi[n] == bit_nil && pi[n] != bit_nil && !any) || (mi[n] != FALSE && pi[n] == bit_nil && any))
426 7 : ri2[q] = bit_nil;
427 96 : q++;
428 : }
429 : } else {
430 365 : oid *gi = Tloc(g, 0);
431 365 : oid c = g->hseqbase;
432 365 : if (nr)
433 365 : cur = gi[0];
434 : bit m = FALSE;
435 : bool has_nil = false;
436 332661 : for (BUN n = 0; n < nr; n++, c++) {
437 332296 : if (c && cur != gi[n]) {
438 57735 : ri1[q] = c-1;
439 57735 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
440 57735 : q++;
441 57735 : cur = gi[n];
442 57735 : m = FALSE;
443 57735 : has_nil = false;
444 : }
445 332296 : if (m == TRUE)
446 191843 : continue;
447 :
448 140453 : if (pi[n] == TRUE && mi[n] == TRUE)
449 : m = TRUE;
450 133526 : else if ((mi[n] == bit_nil && pi[n] != bit_nil && !any) || (mi[n] != FALSE && pi[n] == bit_nil && any))
451 332296 : has_nil = true;
452 : }
453 365 : if (nr) {
454 365 : ri1[q] = c-1;
455 365 : ri2[q] = (m == TRUE)?TRUE:(has_nil)?bit_nil:FALSE;
456 : }
457 365 : q++;
458 : }
459 396 : BATsetcount(res1, q);
460 396 : BATsetcount(res2, q);
461 396 : res1->tsorted = true;
462 396 : res1->tkey = true;
463 396 : res1->trevsorted = false;
464 396 : res2->tsorted = false;
465 396 : res2->trevsorted = false;
466 396 : res1->tnil = false;
467 396 : res1->tnonil = true;
468 396 : res2->tnonil = false;
469 396 : res2->tkey = false;
470 :
471 396 : BBPreclaim(g);
472 396 : BBPreclaim(m);
473 396 : BBPreclaim(p);
474 :
475 396 : BBPkeepref(res1);
476 396 : BBPkeepref(res2);
477 396 : *r1 = res1->batCacheid;
478 396 : *r2 = res2->batCacheid;
479 396 : return MAL_SUCCEED;
480 : }
481 :
482 : static str
483 38 : ALGouterselect(bat *r1, bat *r2, const bat *gid, const bat *mid, const bat *pid, const bit *Any)
484 : {
485 38 : BAT *g = BATdescriptor(*gid); /* oid */
486 38 : BAT *m = BATdescriptor(*mid); /* bit, true: match, false: empty set, nil: nil on left */
487 38 : BAT *p = BATdescriptor(*pid); /* bit */
488 38 : BAT *res1 = NULL, *res2 = NULL;
489 38 : bit any = *Any; /* any or normal comparison semantics */
490 :
491 38 : if (!g || !m || !p) {
492 0 : if (g) BBPreclaim(g);
493 0 : if (m) BBPreclaim(m);
494 0 : if (p) BBPreclaim(p);
495 0 : throw(MAL, "algebra.outerselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
496 : }
497 38 : BUN nr = BATcount(g), q = 0;
498 :
499 38 : if ((res1 = COLnew(0, TYPE_oid, nr, TRANSIENT)) == NULL || (res2 = COLnew(0, TYPE_bit, nr, TRANSIENT)) == NULL) {
500 : BBPreclaim(g);
501 0 : BBPreclaim(m);
502 0 : BBPreclaim(p);
503 0 : if (res1) BBPreclaim(res1);
504 0 : throw(MAL, "algebra.outerselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
505 : }
506 38 : assert(g->tsorted);
507 38 : oid *ri1 = Tloc(res1, 0);
508 38 : bit *ri2 = Tloc(res2, 0);
509 38 : bit *mi = Tloc(m, 0);
510 38 : bit *pi = Tloc(p, 0);
511 38 : oid cur = oid_nil;
512 :
513 38 : if (g->ttype == TYPE_void) { /* void case ? */
514 12 : oid c = g->hseqbase;
515 101 : for (BUN n = 0; n < nr; n++, c++) {
516 89 : ri1[q] = c;
517 161 : ri2[q] = (any && (mi[n] == bit_nil || pi[n] == bit_nil))?bit_nil:(mi[n] == TRUE && pi[n] == TRUE)?TRUE:FALSE;
518 89 : q++;
519 : }
520 : } else {
521 26 : oid *gi = Tloc(g, 0);
522 26 : oid c = g->hseqbase;
523 26 : if (nr)
524 26 : cur = gi[0];
525 : bool used = false;
526 602 : for (BUN n = 0; n < nr; n++, c++) {
527 576 : if (c && cur != gi[n]) {
528 159 : if (!used) {
529 3 : ri1[q] = c-1;
530 3 : ri2[q] = false;
531 3 : q++;
532 : }
533 159 : used = false;
534 159 : cur = gi[n];
535 : }
536 576 : if (mi[n] == TRUE && pi[n] == TRUE) {
537 322 : ri1[q] = c;
538 322 : ri2[q] = TRUE;
539 322 : used = true;
540 322 : q++;
541 254 : } else if (mi[n] == FALSE) { /* empty */
542 55 : ri1[q] = c;
543 55 : ri2[q] = FALSE;
544 55 : used = true;
545 55 : q++;
546 199 : } else if (any && (mi[n] == bit_nil /* ie has nil */ || pi[n] == bit_nil)) {
547 6 : ri1[q] = c;
548 6 : ri2[q] = bit_nil;
549 6 : used = true;
550 6 : q++;
551 : }
552 : }
553 26 : if (nr && !used) {
554 1 : ri1[q] = c-1;
555 1 : ri2[q] = FALSE;
556 1 : q++;
557 : }
558 : }
559 38 : BATsetcount(res1, q);
560 38 : BATsetcount(res2, q);
561 38 : res1->tsorted = true;
562 38 : res1->tkey = true;
563 38 : res1->trevsorted = false;
564 38 : res2->tsorted = false;
565 38 : res2->trevsorted = false;
566 38 : res1->tnil = false;
567 38 : res1->tnonil = true;
568 38 : res2->tnonil = false;
569 38 : res2->tkey = false;
570 :
571 38 : BBPreclaim(g);
572 38 : BBPreclaim(m);
573 38 : BBPreclaim(p);
574 :
575 38 : BBPkeepref(res1);
576 38 : BBPkeepref(res2);
577 38 : *r1 = res1->batCacheid;
578 38 : *r2 = res2->batCacheid;
579 38 : return MAL_SUCCEED;
580 : }
581 :
582 :
583 : static str
584 1586 : ALGselectNotNil(bat *result, const bat *bid)
585 : {
586 1586 : BAT *b;
587 :
588 1586 : if ((b = BATdescriptor(*bid)) == NULL)
589 0 : throw(MAL, "algebra.selectNotNil",
590 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
591 :
592 1588 : MT_lock_set(&b->theaplock);
593 1588 : bool bnonil = b->tnonil || b->ttype == TYPE_msk;
594 1588 : MT_lock_unset(&b->theaplock);
595 1588 : if (!bnonil) {
596 123 : BAT *s;
597 123 : s = BATselect(b, NULL, ATOMnilptr(b->ttype), NULL, true, true, true);
598 123 : if (s) {
599 123 : BAT *bn = BATproject(s, b);
600 123 : BBPunfix(s->batCacheid);
601 122 : if (bn) {
602 122 : BBPunfix(b->batCacheid);
603 123 : *result = bn->batCacheid;
604 123 : BBPkeepref(bn);
605 123 : return MAL_SUCCEED;
606 : }
607 : }
608 0 : BBPunfix(b->batCacheid);
609 0 : throw(MAL, "algebra.selectNotNil", GDK_EXCEPTION);
610 : }
611 : /* just pass on the result */
612 1465 : *result = b->batCacheid;
613 1465 : BBPkeepref(b);
614 1465 : return MAL_SUCCEED;
615 : }
616 :
617 : static str
618 642246 : 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 642246 : BAT *left = NULL, *right = NULL, *right2 = NULL;
638 642246 : BAT *candleft = NULL, *candright = NULL;
639 642246 : BAT *result1 = NULL, *result2 = NULL, *result3 = NULL;
640 642246 : BUN est;
641 642246 : const char *err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
642 :
643 642246 : assert(r2id == NULL || rangefunc != NULL);
644 :
645 642246 : if ((left = BATdescriptor(*lid)) == NULL)
646 0 : goto fail;
647 647862 : if ((right = BATdescriptor(*rid)) == NULL)
648 0 : goto fail;
649 647890 : if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL)
650 0 : goto fail;
651 647893 : if (srid && !is_bat_nil(*srid)
652 0 : && (candright = BATdescriptor(*srid)) == NULL)
653 0 : goto fail;
654 647893 : 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 647893 : err = NULL; /* most likely error now is GDK_EXCEPTION */
661 :
662 647893 : if (thetafunc) {
663 51332 : assert(joinfunc == NULL);
664 51332 : assert(semifunc == NULL);
665 51332 : assert(markfunc == NULL);
666 51332 : assert(bandfunc == NULL);
667 51332 : assert(rangefunc == NULL);
668 51332 : assert(difffunc == NULL);
669 51332 : assert(interfunc == NULL);
670 51332 : if ((*thetafunc)
671 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
672 51332 : op, *nil_matches, est) != GDK_SUCCEED)
673 0 : goto fail;
674 596561 : } else if (joinfunc) {
675 408379 : assert(semifunc == NULL);
676 408379 : assert(markfunc == NULL);
677 408379 : assert(bandfunc == NULL);
678 408379 : assert(rangefunc == NULL);
679 408379 : assert(difffunc == NULL);
680 408379 : assert(interfunc == NULL);
681 408379 : if ((*joinfunc)
682 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
683 408379 : *nil_matches, est) != GDK_SUCCEED)
684 1 : goto fail;
685 188182 : } else if (semifunc) {
686 332 : assert(markfunc == NULL);
687 332 : assert(bandfunc == NULL);
688 332 : assert(rangefunc == NULL);
689 332 : assert(difffunc == NULL);
690 332 : assert(interfunc == NULL);
691 332 : if ((*semifunc)
692 : (&result1, r2 ? &result2 : NULL, left, right, candleft, candright,
693 332 : *nil_matches, *max_one, est) != GDK_SUCCEED)
694 42 : goto fail;
695 187850 : } else if (markfunc) {
696 19103 : assert(bandfunc == NULL);
697 19103 : assert(rangefunc == NULL);
698 19103 : assert(difffunc == NULL);
699 19103 : assert(interfunc == NULL);
700 38201 : if ((*markfunc) (&result1, r2 ? &result2 : NULL, &result3,
701 : left, right, candleft, candright, est) != GDK_SUCCEED)
702 0 : goto fail;
703 168747 : } 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 168747 : } else if (rangefunc) {
712 151 : assert(difffunc == NULL);
713 151 : assert(interfunc == NULL);
714 151 : if ((right2 = BATdescriptor(*r2id)) == NULL) {
715 0 : err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING;
716 0 : goto fail;
717 : }
718 176 : if ((*rangefunc)
719 : (&result1, r2 ? &result2 : NULL, left, right, right2, candleft,
720 : candright, li, hi, anti, symmetric, est) != GDK_SUCCEED)
721 0 : goto fail;
722 147 : BBPunfix(right2->batCacheid);
723 168596 : } else if (difffunc) {
724 159339 : assert(r2 == NULL);
725 159339 : assert(interfunc == NULL);
726 159136 : if ((result1 = (*difffunc) (left, right, candleft, candright,
727 159339 : *nil_matches, *not_in, est)) == NULL)
728 0 : goto fail;
729 : } else {
730 9257 : assert(r2 == NULL);
731 9236 : if ((result1 = (*interfunc) (left, right, candleft, candright,
732 9257 : *nil_matches, *max_one, est)) == NULL)
733 1 : goto fail;
734 : }
735 644062 : *r1 = result1->batCacheid;
736 644062 : BBPkeepref(result1);
737 645959 : if (r2) {
738 373465 : *r2 = result2->batCacheid;
739 373465 : BBPkeepref(result2);
740 : }
741 646556 : if (r3) {
742 19032 : *r3 = result3->batCacheid;
743 19032 : BBPkeepref(result3);
744 : }
745 646588 : BBPunfix(left->batCacheid);
746 647212 : BBPunfix(right->batCacheid);
747 647672 : BBPreclaim(candleft);
748 647715 : BBPreclaim(candright);
749 : return MAL_SUCCEED;
750 :
751 44 : fail:
752 44 : BBPreclaim(left);
753 44 : BBPreclaim(right);
754 44 : BBPreclaim(right2);
755 44 : BBPreclaim(candleft);
756 44 : BBPreclaim(candright);
757 44 : if (err == NULL)
758 44 : throw(MAL, funcname, GDK_EXCEPTION);
759 0 : throw(MAL, funcname, "%s", err);
760 : }
761 :
762 : static str
763 362893 : 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 362893 : 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 42071 : 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 42071 : 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 120 : 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 120 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
808 : false, false, false, false, nil_matches, NULL, match_one,
809 : estimate, NULL, BATouterjoin, NULL, NULL, NULL, NULL, NULL, NULL,
810 : "algebra.outerjoin");
811 : }
812 :
813 : static str
814 0 : ALGouterjoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid,
815 : const bat *srid, const bit *nil_matches, const bit *match_one,
816 : const lng *estimate)
817 : {
818 0 : return do_join(r1, NULL, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
819 : false, false, false, false, nil_matches, NULL, match_one,
820 : estimate, NULL, BATouterjoin, NULL, NULL, NULL, NULL, NULL, NULL,
821 : "algebra.outerjoin");
822 : }
823 :
824 : static str
825 209 : ALGsemijoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid,
826 : const bat *srid, const bit *nil_matches, const bit *max_one,
827 : const lng *estimate)
828 : {
829 209 : return do_join(r1, r2, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL,
830 : false, false, false, false, nil_matches, NULL, max_one,
831 : estimate, NULL, BATsemijoin, NULL, NULL, NULL, NULL, NULL, NULL,
832 : "algebra.semijoin");
833 : }
834 :
835 : static str
836 19011 : ALGmark2join(bat *r1, bat *r3, const bat *lid, const bat *rid,
837 : const bat *slid, const bat *srid, const lng *estimate)
838 : {
839 19011 : 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 8027 : 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 8027 : 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 41707 : 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 41707 : 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 117 : 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 243 : return do_join(r1, r2, NULL, lid, rlid, rhid, slid, srid, 0, NULL, NULL,
905 117 : *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 159265 : 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 159265 : 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 9251 : 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 9251 : 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 1610 : ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
954 : {
955 1610 : bat *ret1, *ret2 = NULL;
956 1610 : bat bid, sid, gid;
957 1610 : BAT *b, *s = NULL, *g = NULL;
958 1610 : BAT *bn = NULL, *gn = NULL;
959 1610 : lng n;
960 1610 : bit asc, nilslast, distinct;
961 1610 : gdk_return rc;
962 :
963 1610 : (void) cntxt;
964 1610 : (void) mb;
965 :
966 1610 : assert(pci->retc == 1 || pci->retc == 2);
967 1610 : assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7);
968 :
969 1610 : n = *getArgReference_lng(stk, pci, pci->argc - 4);
970 1610 : if (n < 0)
971 0 : throw(MAL, "algebra.firstn", ILLEGAL_ARGUMENT);
972 1610 : if (n > (lng) BUN_MAX)
973 : n = BUN_MAX;
974 1610 : ret1 = getArgReference_bat(stk, pci, 0);
975 1610 : if (pci->retc == 2)
976 527 : ret2 = getArgReference_bat(stk, pci, 1);
977 1610 : bid = *getArgReference_bat(stk, pci, pci->retc);
978 1610 : if ((b = BATdescriptor(bid)) == NULL)
979 0 : throw(MAL, "algebra.firstn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
980 1611 : if (pci->argc - pci->retc > 5) {
981 1612 : sid = *getArgReference_bat(stk, pci, pci->retc + 1);
982 1612 : 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 1614 : if (pci->argc - pci->retc > 6) {
988 1614 : gid = *getArgReference_bat(stk, pci, pci->retc + 2);
989 1614 : 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 1613 : asc = *getArgReference_bit(stk, pci, pci->argc - 3);
998 1613 : nilslast = *getArgReference_bit(stk, pci, pci->argc - 2);
999 1613 : distinct = *getArgReference_bit(stk, pci, pci->argc - 1);
1000 2702 : rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast,
1001 : distinct);
1002 1613 : BBPunfix(b->batCacheid);
1003 1611 : BBPreclaim(s);
1004 1610 : BBPreclaim(g);
1005 1614 : if (rc != GDK_SUCCEED)
1006 0 : throw(MAL, "algebra.firstn", GDK_EXCEPTION);
1007 1614 : *ret1 = bn->batCacheid;
1008 1614 : BBPkeepref(bn);
1009 1612 : if (ret2) {
1010 526 : *ret2 = gn->batCacheid;
1011 526 : BBPkeepref(gn);
1012 : }
1013 : return MAL_SUCCEED;
1014 : }
1015 :
1016 : static str
1017 9 : ALGunary(bat *result, const bat *bid, BAT *(*func)(BAT *), const char *name)
1018 : {
1019 9 : BAT *b, *bn;
1020 :
1021 9 : if ((b = BATdescriptor(*bid)) == NULL) {
1022 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1023 : }
1024 9 : bn = (*func) (b);
1025 9 : BBPunfix(b->batCacheid);
1026 9 : if (bn == NULL)
1027 0 : throw(MAL, name, GDK_EXCEPTION);
1028 9 : *result = bn->batCacheid;
1029 9 : BBPkeepref(bn);
1030 9 : return MAL_SUCCEED;
1031 : }
1032 :
1033 : static inline BAT *
1034 9 : BATwcopy(BAT *b)
1035 : {
1036 9 : return COLcopy(b, b->ttype, true, TRANSIENT);
1037 : }
1038 :
1039 : static str
1040 9 : ALGcopy(bat *result, const bat *bid)
1041 : {
1042 9 : return ALGunary(result, bid, BATwcopy, "algebra.copy");
1043 : }
1044 :
1045 : static str
1046 74 : ALGunique(bat *result, const bat *bid, const bat *sid)
1047 : {
1048 74 : BAT *b, *s = NULL, *bn = NULL;
1049 :
1050 74 : if ((b = BATdescriptor(*bid)) == NULL) {
1051 0 : throw(MAL, "algebra.unique", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1052 : }
1053 74 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
1054 0 : BBPunfix(b->batCacheid);
1055 0 : throw(MAL, "algebra.unique", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1056 : }
1057 74 : bn = BATunique(b, s);
1058 74 : BBPunfix(b->batCacheid);
1059 74 : BBPreclaim(s);
1060 74 : if (bn == NULL)
1061 0 : throw(MAL, "algebra.unique", GDK_EXCEPTION);
1062 74 : *result = bn->batCacheid;
1063 74 : BBPkeepref(bn);
1064 74 : return MAL_SUCCEED;
1065 : }
1066 :
1067 : static str
1068 44900 : ALGcrossproduct(bat *l, bat *r, const bat *left, const bat *right,
1069 : const bat *slid, const bat *srid, const bit *max_one)
1070 : {
1071 44900 : BAT *L, *R, *bn1, *bn2 = NULL;
1072 44900 : BAT *sl = NULL, *sr = NULL;
1073 44900 : gdk_return ret;
1074 :
1075 44900 : L = BATdescriptor(*left);
1076 46166 : R = BATdescriptor(*right);
1077 46215 : 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 46215 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1084 1 : (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 47967 : ret = BATsubcross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1093 46215 : max_one && !is_bit_nil(*max_one) && *max_one);
1094 45707 : BBPunfix(L->batCacheid);
1095 46120 : BBPunfix(R->batCacheid);
1096 46208 : BBPreclaim(sl);
1097 46210 : BBPreclaim(sr);
1098 46209 : if (ret != GDK_SUCCEED)
1099 86 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1100 46123 : *l = bn1->batCacheid;
1101 46123 : BBPkeepref(bn1);
1102 46085 : if (r) {
1103 44345 : *r = bn2->batCacheid;
1104 44345 : BBPkeepref(bn2);
1105 : }
1106 : return MAL_SUCCEED;
1107 : }
1108 :
1109 : static str
1110 1684 : ALGcrossproduct1(bat *l, const bat *left, const bat *right, const bit *max_one)
1111 : {
1112 1684 : return ALGcrossproduct(l, NULL, left, right, NULL, NULL, max_one);
1113 : }
1114 :
1115 : static str
1116 43277 : ALGcrossproduct2(bat *l, bat *r, const bat *left, const bat *right,
1117 : const bit *max_one)
1118 : {
1119 43277 : return ALGcrossproduct(l, r, left, right, NULL, NULL, max_one);
1120 : }
1121 :
1122 : static str
1123 0 : ALGcrossproduct3(bat *l, bat *r, const bat *left, const bat *right,
1124 : const bat *sl, const bat *sr, const bit *max_one)
1125 : {
1126 0 : return ALGcrossproduct(l, r, left, right, sl, sr, max_one);
1127 : }
1128 :
1129 : static str
1130 0 : ALGcrossproduct4(bat *l, const bat *left, const bat *right, const bat *sl,
1131 : const bat *sr, const bit *max_one)
1132 : {
1133 0 : return ALGcrossproduct(l, NULL, left, right, sl, sr, max_one);
1134 : }
1135 :
1136 : static str
1137 425 : ALGoutercrossproduct3(bat *l, bat *r, const bat *left, const bat *right, const bat *slid, const bat *srid, const bit *max_one)
1138 : {
1139 425 : BAT *L, *R, *bn1, *bn2 = NULL;
1140 425 : BAT *sl = NULL, *sr = NULL;
1141 425 : gdk_return ret;
1142 :
1143 425 : L = BATdescriptor(*left);
1144 425 : R = BATdescriptor(*right);
1145 425 : if (L == NULL || R == NULL) {
1146 0 : BBPreclaim(L);
1147 0 : BBPreclaim(R);
1148 0 : throw(MAL, "algebra.crossproduct", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1149 : }
1150 425 : if ((slid && !is_bat_nil(*slid) && (sl = BATdescriptor(*slid)) == NULL) ||
1151 425 : (srid && !is_bat_nil(*srid) && (sr = BATdescriptor(*srid)) == NULL)) {
1152 0 : BBPunfix(L->batCacheid);
1153 0 : BBPunfix(R->batCacheid);
1154 0 : BBPreclaim(sl);
1155 : /* sr == NULL, so no need to unfix */
1156 0 : throw(MAL, "algebra.crossproduct", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1157 : }
1158 425 : ret = BAToutercross(&bn1, r ? &bn2 : NULL, L, R, sl, sr,
1159 425 : max_one && !is_bit_nil(*max_one) && *max_one);
1160 425 : BBPunfix(L->batCacheid);
1161 425 : BBPunfix(R->batCacheid);
1162 425 : BBPreclaim(sl);
1163 425 : BBPreclaim(sr);
1164 425 : if (ret != GDK_SUCCEED)
1165 0 : throw(MAL, "algebra.crossproduct", GDK_EXCEPTION);
1166 425 : *l = bn1->batCacheid;
1167 425 : BBPkeepref(bn1);
1168 425 : if (r) {
1169 425 : *r = bn2->batCacheid;
1170 425 : BBPkeepref(bn2);
1171 : }
1172 : return MAL_SUCCEED;
1173 : }
1174 :
1175 : static str
1176 1968593 : ALGprojection2(bat *result, const bat *lid, const bat *r1id, const bat *r2id)
1177 : {
1178 1968593 : BAT *l, *r1, *r2 = NULL, *bn;
1179 :
1180 1968593 : if ((l = BATdescriptor(*lid)) == NULL) {
1181 0 : throw(MAL, "algebra.projection",
1182 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1183 : }
1184 1981345 : if ((r1 = BATdescriptor(*r1id)) == NULL) {
1185 0 : BBPunfix(l->batCacheid);
1186 0 : throw(MAL, "algebra.projection",
1187 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1188 : }
1189 1980226 : 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 1980226 : bn = BATproject2(l, r1, r2);
1196 1954988 : BBPunfix(l->batCacheid);
1197 1976714 : BBPunfix(r1->batCacheid);
1198 1979969 : BBPreclaim(r2);
1199 1980150 : if (bn == NULL)
1200 0 : throw(MAL, "algebra.projection", GDK_EXCEPTION);
1201 1980150 : *result = bn->batCacheid;
1202 1980150 : BBPkeepref(bn);
1203 1980150 : return MAL_SUCCEED;
1204 : }
1205 :
1206 : str
1207 1971142 : ALGprojection(bat *result, const bat *lid, const bat *rid)
1208 : {
1209 1971142 : return ALGprojection2(result, lid, rid, NULL);
1210 : }
1211 :
1212 : static str
1213 23994 : 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 23994 : BAT *bn = NULL, *on = NULL, *gn = NULL;
1218 23994 : BAT *b = NULL, *o = NULL, *g = NULL;
1219 :
1220 23994 : if ((b = BATdescriptor(*bid)) == NULL)
1221 0 : throw(MAL, "algebra.sort", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1222 23994 : 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 23994 : 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 27593 : if (BATsort(result ? &bn : NULL,
1232 : norder ? &on : NULL,
1233 : ngroup ? &gn : NULL,
1234 23994 : 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 23994 : BBPunfix(b->batCacheid);
1241 23994 : BBPreclaim(o);
1242 23994 : BBPreclaim(g);
1243 23994 : if (result) {
1244 23994 : *result = bn->batCacheid;
1245 23994 : BBPkeepref(bn);
1246 : }
1247 23994 : if (norder) {
1248 20395 : *norder = on->batCacheid;
1249 20395 : BBPkeepref(on);
1250 : }
1251 23994 : if (ngroup) {
1252 13572 : *ngroup = gn->batCacheid;
1253 13572 : BBPkeepref(gn);
1254 : }
1255 : return MAL_SUCCEED;
1256 : }
1257 :
1258 : static str
1259 4099 : 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 4099 : return ALGsort33(result, norder, NULL, bid, order, group, reverse, nilslast,
1264 : stable);
1265 : }
1266 :
1267 : static str
1268 1958 : ALGsort31(bat *result, const bat *bid, const bat *order, const bat *group,
1269 : const bit *reverse, const bit *nilslast, const bit *stable)
1270 : {
1271 1958 : return ALGsort33(result, NULL, NULL, bid, order, group, reverse, nilslast,
1272 : stable);
1273 : }
1274 :
1275 : static str
1276 0 : ALGsort23(bat *result, bat *norder, bat *ngroup, const bat *bid,
1277 : const bat *order, const bit *reverse, const bit *nilslast,
1278 : const bit *stable)
1279 : {
1280 0 : return ALGsort33(result, norder, ngroup, bid, order, NULL, reverse,
1281 : nilslast, stable);
1282 : }
1283 :
1284 : static str
1285 0 : ALGsort22(bat *result, bat *norder, const bat *bid, const bat *order,
1286 : const bit *reverse, const bit *nilslast, const bit *stable)
1287 : {
1288 0 : return ALGsort33(result, norder, NULL, bid, order, NULL, reverse, nilslast,
1289 : stable);
1290 : }
1291 :
1292 : static str
1293 0 : ALGsort21(bat *result, const bat *bid, const bat *order, const bit *reverse,
1294 : const bit *nilslast, const bit *stable)
1295 : {
1296 0 : return ALGsort33(result, NULL, NULL, bid, order, NULL, reverse, nilslast,
1297 : stable);
1298 : }
1299 :
1300 : static str
1301 6312 : ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid,
1302 : const bit *reverse, const bit *nilslast, const bit *stable)
1303 : {
1304 6312 : return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast,
1305 : stable);
1306 : }
1307 :
1308 : static str
1309 2724 : ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse,
1310 : const bit *nilslast, const bit *stable)
1311 : {
1312 2724 : return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast,
1313 : stable);
1314 : }
1315 :
1316 : static str
1317 1641 : ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast,
1318 : const bit *stable)
1319 : {
1320 1641 : return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast,
1321 : stable);
1322 : }
1323 :
1324 : static str
1325 70084 : ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd,
1326 : const bit *ignore_nils)
1327 : {
1328 70084 : BAT *b, *s = NULL;
1329 :
1330 70084 : if ((b = BATdescriptor(*bid)) == NULL) {
1331 0 : throw(MAL, "aggr.count", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1332 : }
1333 70288 : 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 70288 : if (b->ttype == TYPE_msk || mask_cand(b)) {
1338 30 : BATsum(result, TYPE_lng, b, s, *ignore_nils, false);
1339 70258 : } else if (*ignore_nils) {
1340 1770 : *result = (lng) BATcount_no_nil(b, s);
1341 : } else {
1342 68488 : struct canditer ci;
1343 68488 : canditer_init(&ci, b, s);
1344 68529 : *result = (lng) ci.ncand;
1345 : }
1346 70327 : BBPreclaim(s);
1347 70327 : BBPunfix(b->batCacheid);
1348 70327 : return MAL_SUCCEED;
1349 : }
1350 :
1351 : static str
1352 1769 : ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils)
1353 : {
1354 1769 : 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 68328 : ALGcount_bat(lng *result, const bat *bid)
1365 : {
1366 68328 : 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 17184 : ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end)
1430 : {
1431 17184 : BAT *b, *bn;
1432 17184 : BUN s, e;
1433 :
1434 17184 : if (*start < 0 || (*end < 0 && !is_lng_nil(*end)))
1435 0 : throw(MAL, "algebra.subslice", ILLEGAL_ARGUMENT);
1436 17184 : if ((b = BBPquickdesc(*bid)) == NULL)
1437 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1438 17183 : s = (BUN) *start;
1439 17183 : if (s > BATcount(b))
1440 : s = BATcount(b);
1441 17183 : e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1;
1442 17183 : if (e > BATcount(b))
1443 : e = BATcount(b);
1444 17183 : if (e < s)
1445 : e = s;
1446 17183 : bn = BATdense(0, b->hseqbase + s, e - s);
1447 17183 : if (bn == NULL)
1448 0 : throw(MAL, "algebra.subslice", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1449 17183 : *ret = bn->batCacheid;
1450 17183 : BBPkeepref(bn);
1451 17183 : return MAL_SUCCEED;
1452 : }
1453 :
1454 : /*
1455 : * BUN Get/Fetch
1456 : */
1457 :
1458 : static str
1459 88509 : doALGfetch(ptr ret, BAT *b, BUN pos)
1460 : {
1461 88509 : assert(pos <= BUN_MAX);
1462 88509 : BATiter bi = bat_iterator(b);
1463 88510 : if (ATOMextern(b->ttype)) {
1464 190 : ptr _src = BUNtail(bi, pos);
1465 190 : size_t _len = ATOMlen(b->ttype, _src);
1466 190 : ptr _dst = GDKmalloc(_len);
1467 190 : if (_dst == NULL) {
1468 0 : bat_iterator_end(&bi);
1469 0 : throw(MAL, "doAlgFetch", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1470 : }
1471 190 : memcpy(_dst, _src, _len);
1472 190 : *(ptr *) ret = _dst;
1473 : } else {
1474 88320 : size_t _s = ATOMsize(ATOMtype(b->ttype));
1475 88320 : if (b->ttype == TYPE_void) {
1476 0 : *(oid *) ret = b->tseqbase;
1477 0 : if (!is_oid_nil(b->tseqbase))
1478 0 : *(oid *) ret += pos;
1479 88320 : } else if (_s == 4) {
1480 88233 : *(int *) ret = ((int *) bi.base)[pos];
1481 : } else if (_s == 1) {
1482 11 : *(bte *) ret = ((bte *) bi.base)[pos];
1483 : } else if (_s == 2) {
1484 1 : *(sht *) ret = ((sht *) bi.base)[pos];
1485 : } else if (_s == 8) {
1486 75 : *(lng *) ret = ((lng *) bi.base)[pos];
1487 : #ifdef HAVE_HGE
1488 : } else if (_s == 16) {
1489 0 : *(hge *) ret = ((hge *) bi.base)[pos];
1490 : #endif
1491 : } else {
1492 0 : memcpy(ret, (const char *) bi.base + (pos << bi.shift), _s);
1493 : }
1494 : }
1495 88510 : bat_iterator_end(&bi);
1496 88510 : return MAL_SUCCEED;
1497 : }
1498 :
1499 : static str
1500 88512 : ALGfetch(ptr ret, const bat *bid, const lng *pos)
1501 : {
1502 88512 : BAT *b;
1503 88512 : str msg;
1504 :
1505 88512 : if ((b = BATdescriptor(*bid)) == NULL) {
1506 0 : throw(MAL, "algebra.fetch", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1507 : }
1508 88511 : 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 88511 : 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 88509 : 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 88509 : msg = doALGfetch(ret, b, (BUN) *pos);
1525 88509 : BBPunfix(b->batCacheid);
1526 88509 : return msg;
1527 : }
1528 :
1529 : str
1530 88512 : ALGfetchoid(ptr ret, const bat *bid, const oid *pos)
1531 : {
1532 88512 : lng o = *pos;
1533 :
1534 88512 : return ALGfetch(ret, bid, &o);
1535 : }
1536 :
1537 : static str
1538 0 : ALGexist(bit *ret, const bat *bid, const void *val)
1539 : {
1540 0 : BAT *b;
1541 0 : BUN q;
1542 :
1543 0 : if ((b = BATdescriptor(*bid)) == NULL) {
1544 0 : throw(MAL, "algebra.exist", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1545 : }
1546 0 : derefStr(b, val);
1547 0 : q = BUNfnd(b, val);
1548 0 : *ret = (q != BUN_NONE);
1549 0 : BBPunfix(b->batCacheid);
1550 0 : return MAL_SUCCEED;
1551 : }
1552 :
1553 : static str
1554 9 : ALGfind(oid *ret, const bat *bid, ptr val)
1555 : {
1556 9 : BAT *b;
1557 9 : BUN q;
1558 9 : str msg = MAL_SUCCEED;
1559 :
1560 9 : if ((b = BATdescriptor(*bid)) == NULL) {
1561 0 : throw(MAL, "algebra.find", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1562 : }
1563 9 : derefStr(b, val);
1564 9 : q = BUNfnd(b, val);
1565 :
1566 9 : if (q == BUN_NONE) {
1567 3 : *ret = oid_nil;
1568 : } else
1569 6 : *ret = (oid) q;
1570 9 : BBPunfix(b->batCacheid);
1571 9 : return msg;
1572 : }
1573 :
1574 :
1575 : static str
1576 290716 : ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
1577 : {
1578 290716 : bat *ret = getArgReference_bat(stk, pci, 0);
1579 290716 : bat bid = *getArgReference_bat(stk, pci, 1);
1580 290716 : const ValRecord *v = &stk->stk[getArg(pci, 2)];
1581 290716 : BAT *b, *bn;
1582 :
1583 290716 : (void) cntxt;
1584 290716 : (void) mb;
1585 290716 : if (isaBatType(getArgType(mb, pci, 2)))
1586 0 : throw(MAL, "algebra.project", "Scalar value expected");
1587 290716 : if ((b = BBPquickdesc(bid)) == NULL)
1588 0 : throw(MAL, "algebra.project", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1589 290626 : bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT);
1590 290872 : if (bn == NULL) {
1591 0 : *ret = bat_nil;
1592 0 : throw(MAL, "algebra.project", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1593 : }
1594 290872 : *ret = bn->batCacheid;
1595 290872 : BBPkeepref(bn);
1596 290872 : return MAL_SUCCEED;
1597 : }
1598 :
1599 :
1600 : static str
1601 0 : ALGreuse(bat *ret, const bat *bid)
1602 : {
1603 0 : BAT *b, *bn;
1604 0 : if ((b = BATdescriptor(*bid)) == NULL)
1605 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1606 :
1607 0 : if (!b->batTransient || b->batRestricted != BAT_WRITE) {
1608 0 : if (ATOMvarsized(b->ttype)) {
1609 0 : bn = BATwcopy(b);
1610 0 : if (bn == NULL) {
1611 0 : BBPunfix(b->batCacheid);
1612 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1613 : }
1614 : } else {
1615 0 : bn = COLnew(b->hseqbase, b->ttype, BATcount(b), TRANSIENT);
1616 0 : if (bn == NULL) {
1617 0 : BBPunfix(b->batCacheid);
1618 0 : throw(MAL, "algebra.reuse", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1619 : }
1620 0 : BATsetcount(bn, BATcount(b));
1621 0 : bn->tsorted = false;
1622 0 : bn->trevsorted = false;
1623 0 : BATkey(bn, false);
1624 : }
1625 0 : *ret = bn->batCacheid;
1626 0 : BBPkeepref(bn);
1627 0 : BBPunfix(b->batCacheid);
1628 : } else
1629 0 : BBPkeepref(b);
1630 : return MAL_SUCCEED;
1631 : }
1632 :
1633 : /*
1634 : * BAT standard deviation
1635 : */
1636 : static str
1637 7 : ALGstdev(dbl *res, const bat *bid)
1638 : {
1639 7 : BAT *b;
1640 7 : dbl stdev;
1641 :
1642 7 : if ((b = BATdescriptor(*bid)) == NULL)
1643 0 : throw(MAL, "aggr.stdev", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1644 7 : stdev = BATcalcstdev_sample(NULL, b);
1645 7 : BBPunfix(b->batCacheid);
1646 7 : if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0])
1647 0 : throw(MAL, "aggr.stdev", GDK_EXCEPTION);
1648 7 : *res = stdev;
1649 7 : return MAL_SUCCEED;
1650 : }
1651 :
1652 : static str
1653 13 : ALGstdevp(dbl *res, const bat *bid)
1654 : {
1655 13 : BAT *b;
1656 13 : dbl stdev;
1657 :
1658 13 : if ((b = BATdescriptor(*bid)) == NULL)
1659 0 : throw(MAL, "aggr.stdevp", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1660 13 : stdev = BATcalcstdev_population(NULL, b);
1661 13 : BBPunfix(b->batCacheid);
1662 13 : if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0])
1663 1 : throw(MAL, "aggr.stdevp", GDK_EXCEPTION);
1664 12 : *res = stdev;
1665 12 : return MAL_SUCCEED;
1666 : }
1667 :
1668 : /*
1669 : * BAT variance
1670 : */
1671 : static str
1672 2 : ALGvariance(dbl *res, const bat *bid)
1673 : {
1674 2 : BAT *b;
1675 2 : dbl variance;
1676 :
1677 2 : if ((b = BATdescriptor(*bid)) == NULL)
1678 0 : throw(MAL, "aggr.variance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1679 2 : variance = BATcalcvariance_sample(NULL, b);
1680 2 : BBPunfix(b->batCacheid);
1681 2 : if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0])
1682 0 : throw(MAL, "aggr.variance", GDK_EXCEPTION);
1683 2 : *res = variance;
1684 2 : return MAL_SUCCEED;
1685 : }
1686 :
1687 : static str
1688 5 : ALGvariancep(dbl *res, const bat *bid)
1689 : {
1690 5 : BAT *b;
1691 5 : dbl variance;
1692 :
1693 5 : if ((b = BATdescriptor(*bid)) == NULL)
1694 0 : throw(MAL, "aggr.variancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1695 5 : variance = BATcalcvariance_population(NULL, b);
1696 5 : BBPunfix(b->batCacheid);
1697 5 : if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0])
1698 1 : throw(MAL, "aggr.variancep", GDK_EXCEPTION);
1699 4 : *res = variance;
1700 4 : return MAL_SUCCEED;
1701 : }
1702 :
1703 : /*
1704 : * BAT covariance
1705 : */
1706 : static str
1707 5 : ALGcovariance(dbl *res, const bat *bid1, const bat *bid2)
1708 : {
1709 5 : BAT *b1, *b2;
1710 5 : dbl covariance;
1711 :
1712 5 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1713 0 : throw(MAL, "aggr.covariance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1714 5 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1715 0 : BBPunfix(b1->batCacheid);
1716 0 : throw(MAL, "aggr.covariance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1717 : }
1718 :
1719 5 : covariance = BATcalccovariance_sample(b1, b2);
1720 5 : BBPunfix(b1->batCacheid);
1721 5 : BBPunfix(b2->batCacheid);
1722 5 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1723 0 : throw(MAL, "aggr.covariance", GDK_EXCEPTION);
1724 5 : *res = covariance;
1725 5 : return MAL_SUCCEED;
1726 : }
1727 :
1728 : static str
1729 9 : ALGcovariancep(dbl *res, const bat *bid1, const bat *bid2)
1730 : {
1731 9 : BAT *b1, *b2;
1732 9 : dbl covariance;
1733 :
1734 9 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1735 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1736 9 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1737 0 : BBPunfix(b1->batCacheid);
1738 0 : throw(MAL, "aggr.covariancep", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1739 : }
1740 :
1741 9 : covariance = BATcalccovariance_population(b1, b2);
1742 9 : BBPunfix(b1->batCacheid);
1743 9 : BBPunfix(b2->batCacheid);
1744 9 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1745 1 : throw(MAL, "aggr.covariancep", GDK_EXCEPTION);
1746 8 : *res = covariance;
1747 8 : return MAL_SUCCEED;
1748 : }
1749 :
1750 : /*
1751 : * BAT correlation
1752 : */
1753 : static str
1754 19 : ALGcorr(dbl *res, const bat *bid1, const bat *bid2)
1755 : {
1756 19 : BAT *b1, *b2;
1757 19 : dbl covariance;
1758 :
1759 19 : if ((b1 = BATdescriptor(*bid1)) == NULL)
1760 0 : throw(MAL, "aggr.corr", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1761 19 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
1762 0 : BBPunfix(b1->batCacheid);
1763 0 : throw(MAL, "aggr.corr", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1764 : }
1765 :
1766 19 : covariance = BATcalccorrelation(b1, b2);
1767 18 : BBPunfix(b1->batCacheid);
1768 19 : BBPunfix(b2->batCacheid);
1769 19 : if (is_dbl_nil(covariance) && GDKerrbuf && GDKerrbuf[0])
1770 1 : throw(MAL, "aggr.corr", GDK_EXCEPTION);
1771 18 : *res = covariance;
1772 18 : return MAL_SUCCEED;
1773 : }
1774 :
1775 : #include "mel.h"
1776 : mel_func algebra_init_funcs[] = {
1777 : command("algebra", "groupby", ALGgroupby, false, "Produces a new BAT with groups identified by the head column. The result contains tail times the head value, ie the tail contains the result group sizes.", args(1,3, batarg("",oid),batarg("gids",oid),batarg("cnts",lng))),
1778 : command("algebra", "find", ALGfind, false, "Returns the index position of a value. If no such BUN exists return OID-nil.", args(1,3, arg("",oid),batargany("b",1),argany("t",1))),
1779 : command("algebra", "fetch", ALGfetchoid, false, "Returns the value of the BUN at x-th position with 0 <= x < b.count", args(1,3, argany("",1),batargany("b",1),arg("x",oid))),
1780 : pattern("algebra", "project", ALGprojecttail, false, "Fill the tail with a constant", args(1,3, batargany("",2),batargany("b",1),argany("v",2))),
1781 : command("algebra", "projection", ALGprojection, false, "Project left input onto right input.", args(1,3, batargany("",1),batarg("left",oid),batargany("right",1))),
1782 : command("algebra", "projection", ALGprojection2, false, "Project left input onto right inputs which should be consecutive.", args(1,4, batargany("",1),batarg("left",oid),batargany("right1",1),batargany("right2",1))),
1783 : command("algebra", "copy", ALGcopy, false, "Returns physical copy of a BAT.", args(1,2, batargany("",1),batargany("b",1))),
1784 : command("algebra", "exist", ALGexist, false, "Returns whether 'val' occurs in b.", args(1,3, arg("",bit),batargany("b",1),argany("val",1))),
1785 : command("algebra", "select", ALGselect1, false, "Select all head values for which the tail value is in range.\nInput is a dense-headed BAT, output is a dense-headed BAT with in\nthe tail the head value of the input BAT for which the tail value\nis between the values low and high (inclusive if li respectively\nhi is set). The output BAT is sorted on the tail value. If low\nor high is nil, the boundary is not considered (effectively - and\n+ infinity). If anti is set, the result is the complement. Nil\nvalues in the tail are never matched, unless low=nil, high=nil,\nli=1, hi=1, anti=0. All non-nil values are returned if low=nil,\nhigh=nil, and li, hi are not both 1, or anti=1.\nNote that the output is suitable as second input for the other\nversion of this function.", args(1,7, batarg("",oid),batargany("b",1),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1786 : command("algebra", "select", ALGselect2, false, "Select all head values of the first input BAT for which the tail value\nis in range and for which the head value occurs in the tail of the\nsecond input BAT.\nThe first input is a dense-headed BAT, the second input is a\ndense-headed BAT with sorted tail, output is a dense-headed BAT\nwith in the tail the head value of the input BAT for which the\ntail value is between the values low and high (inclusive if li\nrespectively hi is set). The output BAT is sorted on the tail\nvalue. If low or high is nil, the boundary is not considered\n(effectively - and + infinity). If anti is set, the result is the\ncomplement. Nil values in the tail are never matched, unless\nlow=nil, high=nil, li=1, hi=1, anti=0. All non-nil values are\nreturned if low=nil, high=nil, and li, hi are not both 1, or anti=1.\nNote that the output is suitable as second input for this\nfunction.", args(1,8, batarg("",oid),batargany("b",1),batarg("s",oid),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit))),
1787 : command("algebra", "select", ALGselect1nil, false, "With unknown set, each nil != nil", args(1,8, batarg("",oid),batargany("b",1),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("unknown",bit))),
1788 : command("algebra", "select", ALGselect2nil, false, "With unknown set, each nil != nil", args(1,9, batarg("",oid),batargany("b",1),batarg("s",oid),argany("low",1),argany("high",1),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("unknown",bit))),
1789 : command("algebra", "thetaselect", ALGthetaselect2, false, "Select all head values of the first input BAT for which the tail value\nobeys the relation value OP VAL and for which the head value occurs in\nthe tail of the second input BAT.\nInput is a dense-headed BAT, output is a dense-headed BAT with in\nthe tail the head value of the input BAT for which the\nrelationship holds. The output BAT is sorted on the tail value.", args(1,5, batarg("",oid),batargany("b",1),batarg("s",oid),argany("val",1),arg("op",str))),
1790 : command("algebra", "markselect", ALGmarkselect, false, "Group on group-ids, return aggregated anyequal or allnotequal", args(2,6, batarg("",oid), batarg("", bit), batarg("gid",oid), batarg("m", bit), batarg("p", bit), arg("any", bit))),
1791 : command("algebra", "outerselect", ALGouterselect, false, "Per input lid return at least one row, if none of the predicates (p) hold, return a nil, else 'all' true cases.", args(2,6, batarg("",oid), batarg("", bit), batarg("lid", oid), batarg("rid", bit), batarg("predicate", bit), arg("any", bit))),
1792 : command("algebra", "selectNotNil", ALGselectNotNil, false, "Select all not-nil values", args(1,2, batargany("",1),batargany("b",1))),
1793 : command("algebra", "sort", ALGsort11, false, "Returns a copy of the BAT sorted on tail values.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(1,5, batargany("",1),batargany("b",1),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1794 : command("algebra", "sort", ALGsort12, false, "Returns a copy of the BAT sorted on tail values and a BAT that\nspecifies how the input was reordered.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(2,6, batargany("",1),batarg("",oid),batargany("b",1),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1795 : command("algebra", "sort", ALGsort13, false, "Returns a copy of the BAT sorted on tail values, a BAT that specifies\nhow the input was reordered, and a BAT with group information.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(3,7, batargany("",1),batarg("",oid),batarg("",oid),batargany("b",1),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1796 : command("algebra", "sort", ALGsort21, false, "Returns a copy of the BAT sorted on tail values.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(1,6, batargany("",1),batargany("b",1),batarg("o",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1797 : command("algebra", "sort", ALGsort22, false, "Returns a copy of the BAT sorted on tail values and a BAT that\nspecifies how the input was reordered.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(2,7, batargany("",1),batarg("",oid),batargany("b",1),batarg("o",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1798 : command("algebra", "sort", ALGsort23, false, "Returns a copy of the BAT sorted on tail values, a BAT that specifies\nhow the input was reordered, and a BAT with group information.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(3,8, batargany("",1),batarg("",oid),batarg("",oid),batargany("b",1),batarg("o",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1799 : command("algebra", "sort", ALGsort31, false, "Returns a copy of the BAT sorted on tail values.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(1,7, batargany("",1),batargany("b",1),batarg("o",oid),batarg("g",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1800 : command("algebra", "sort", ALGsort32, false, "Returns a copy of the BAT sorted on tail values and a BAT that\nspecifies how the input was reordered.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(2,8, batargany("",1),batarg("",oid),batargany("b",1),batarg("o",oid),batarg("g",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1801 : command("algebra", "sort", ALGsort33, false, "Returns a copy of the BAT sorted on tail values, a BAT that specifies\nhow the input was reordered, and a BAT with group information.\nThe order is descending if the reverse bit is set.\nThis is a stable sort if the stable bit is set.", args(3,9, batargany("",1),batarg("",oid),batarg("",oid),batargany("b",1),batarg("o",oid),batarg("g",oid),arg("reverse",bit),arg("nilslast",bit),arg("stable",bit))),
1802 : command("algebra", "unique", ALGunique, false, "Select all unique values from the tail of the first input.\nInput is a dense-headed BAT, the second input is a\ndense-headed BAT with sorted tail, output is a dense-headed\nBAT with in the tail the head value of the input BAT that was\nselected. The output BAT is sorted on the tail value. The\nsecond input BAT is a list of candidates.", args(1,3, batarg("",oid),batargany("b",1),batarg("s",oid))),
1803 : command("algebra", "crossproduct", ALGcrossproduct2, false, "Returns 2 columns with all BUNs, consisting of the head-oids\nfrom 'left' and 'right' for which there are BUNs in 'left'\nand 'right' with equal tails", args(2,5, batarg("l",oid),batarg("r",oid),batargany("left",1),batargany("right",2),arg("max_one",bit))),
1804 : command("algebra", "crossproduct", ALGcrossproduct1, false, "Compute the cross product of both input bats; but only produce left output", args(1,4, batarg("",oid),batargany("left",1),batargany("right",2),arg("max_one",bit))),
1805 : command("algebra", "crossproduct", ALGcrossproduct3, false, "Compute the cross product of both input bats", args(2,7, batarg("l",oid),batarg("r",oid),batargany("left",1),batargany("right",2),batarg("sl",oid),batarg("sr",oid),arg("max_one",bit))),
1806 : command("algebra", "crossproduct", ALGcrossproduct4, false, "Compute the cross product of both input bats; but only produce left output", args(1,6, batarg("",oid),batargany("left",1),batargany("right",2),batarg("sl",oid),batarg("sr",oid),arg("max_one",bit))),
1807 : command("algebra", "outercrossproduct", ALGoutercrossproduct3, false, "Compute the outer cross product of both input bats", args(2,7, batarg("l",oid),batarg("r",oid),batargany("left",1),batargany("right",2),batarg("sl",oid),batarg("sr",oid),arg("max_one",bit))),
1808 : command("algebra", "join", ALGjoin, false, "Join", args(2,8, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1809 : command("algebra", "join", ALGjoin1, false, "Join; only produce left output", args(1,7, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1810 : command("algebra", "leftjoin", ALGleftjoin, false, "Left join with candidate lists", args(2,8, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1811 : command("algebra", "leftjoin", ALGleftjoin1, false, "Left join with candidate lists; only produce left output", args(1,7, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("estimate",lng))),
1812 : command("algebra", "outerjoin", ALGouterjoin, false, "Left outer join with candidate lists", args(2,9, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("match_one",bit),arg("estimate",lng))),
1813 : command("algebra", "outerjoin", ALGouterjoin1, false, "Left outer join with candidate lists; only produce left output", args(1,8,batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("match_one",bit),arg("estimate",lng))),
1814 : command("algebra", "semijoin", ALGsemijoin, false, "Semi join with candidate lists", args(2,9, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("max_one",bit),arg("estimate",lng))),
1815 : command("algebra", "markjoin", ALGmark2join, false, "Mark join with candidate lists", args(2,7, batarg("",oid),batarg("",bit),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("estimate",lng))),
1816 : command("algebra", "markjoin", ALGmark3join, false, "Mark join with candidate lists", args(3,8, batarg("",oid),batarg("",oid),batarg("",bit),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("estimate",lng))),
1817 : command("algebra", "thetajoin", ALGthetajoin, false, "Theta join with candidate lists", args(2,9, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("op",int),arg("nil_matches",bit),arg("estimate",lng))),
1818 : command("algebra", "thetajoin", ALGthetajoin1, false, "Theta join with candidate lists; only produce left output", args(1,8, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("op",int),arg("nil_matches",bit),arg("estimate",lng))),
1819 : command("algebra", "bandjoin", ALGbandjoin, false, "Band join: values in l and r match if r - c1 <[=] l <[=] r + c2", args(2,11, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),argany("c1",1),argany("c2",1),arg("li",bit),arg("hi",bit),arg("estimate",lng))),
1820 : command("algebra", "bandjoin", ALGbandjoin1, false, "Band join: values in l and r match if r - c1 <[=] l <[=] r + c2; only produce left output", args(1,10, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),argany("c1",1),argany("c2",1),arg("li",bit),arg("hi",bit),arg("estimate",lng))),
1821 : command("algebra", "rangejoin", ALGrangejoin, false, "Range join: values in l and r1/r2 match if r1 <[=] l <[=] r2", args(2,12, batarg("",oid),batarg("",oid),batargany("l",1),batargany("r1",1),batargany("r2",1),batarg("sl",oid),batarg("sr",oid),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("symmetric",bit),arg("estimate",lng))),
1822 : command("algebra", "rangejoin", ALGrangejoin1, false, "Range join: values in l and r1/r2 match if r1 <[=] l <[=] r2; only produce left output", args(1,11,batarg("",oid),batargany("l",1),batargany("r1",1),batargany("r2",1),batarg("sl",oid),batarg("sr",oid),arg("li",bit),arg("hi",bit),arg("anti",bit),arg("symmetric",bit),arg("estimate",lng))),
1823 : command("algebra", "difference", ALGdifference, false, "Difference of l and r with candidate lists", args(1,8, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("nil_clears",bit),arg("estimate",lng))),
1824 : command("algebra", "intersect", ALGintersect, false, "Intersection of l and r with candidate lists (i.e. half of semi-join)", args(1,8, batarg("",oid),batargany("l",1),batargany("r",1),batarg("sl",oid),batarg("sr",oid),arg("nil_matches",bit),arg("max_one",bit),arg("estimate",lng))),
1825 : pattern("algebra", "firstn", ALGfirstn, false, "Calculate first N values of B with candidate list S", args(1,8, batarg("",oid),batargany("b",0),batarg("s",oid),batarg("g",oid),arg("n",lng),arg("asc",bit),arg("nilslast",bit),arg("distinct",bit))),
1826 : pattern("algebra", "firstn", ALGfirstn, false, "Calculate first N values of B with candidate list S", args(2,9, batarg("",oid),batarg("",oid),batargany("b",0),batarg("s",oid),batarg("g",oid),arg("n",lng),arg("asc",bit),arg("nilslast",bit),arg("distinct",bit))),
1827 : command("algebra", "reuse", ALGreuse, false, "Reuse a temporary BAT if you can. Otherwise,\nallocate enough storage to accept result of an\noperation (not involving the heap)", args(1,2, batargany("",1),batargany("b",1))),
1828 : command("algebra", "slice", ALGslice_oid, false, "Return the slice based on head oid x till y (exclusive).", args(1,4, batargany("",1),batargany("b",1),arg("x",oid),arg("y",oid))),
1829 : command("algebra", "slice", ALGslice_int, false, "Return the slice with the BUNs at position x till y.", args(1,4, batargany("",1),batargany("b",1),arg("x",int),arg("y",int))),
1830 : command("algebra", "slice", ALGslice_lng, false, "Return the slice with the BUNs at position x till y.", args(1,4, batargany("",1),batargany("b",1),arg("x",lng),arg("y",lng))),
1831 : command("algebra", "subslice", ALGsubslice_lng, false, "Return the oids of the slice with the BUNs at position x till y.", args(1,4, batarg("",oid),batargany("b",1),arg("x",lng),arg("y",lng))),
1832 : command("aggr", "count", ALGcount_bat, false, "Return the current size (in number of elements) in a BAT.", args(1,2, arg("",lng),batargany("b",0))),
1833 : command("aggr", "count", ALGcount_nil, false, "Return the number of elements currently in a BAT ignores\nBUNs with nil-tail iff ignore_nils==TRUE.", args(1,3, arg("",lng),batargany("b",0),arg("ignore_nils",bit))),
1834 : command("aggr", "count_no_nil", ALGcount_no_nil, false, "Return the number of elements currently\nin a BAT ignoring BUNs with nil-tail", args(1,2, arg("",lng),batargany("b",2))),
1835 : command("aggr", "count", ALGcountCND_bat, false, "Return the current size (in number of elements) in a BAT.", args(1,3, arg("",lng),batargany("b",0),batarg("cnd",oid))),
1836 : command("aggr", "count", ALGcountCND_nil, false, "Return the number of elements currently in a BAT ignores\nBUNs with nil-tail iff ignore_nils==TRUE.", args(1,4, arg("",lng),batargany("b",0),batarg("cnd",oid),arg("ignore_nils",bit))),
1837 : command("aggr", "count_no_nil", ALGcountCND_no_nil, false, "Return the number of elements currently\nin a BAT ignoring BUNs with nil-tail", args(1,3, arg("",lng),batargany("b",2),batarg("cnd",oid))),
1838 : command("aggr", "cardinality", ALGcard, false, "Return the cardinality of the BAT tail values.", args(1,2, arg("",lng),batargany("b",2))),
1839 : command("aggr", "min", ALGminany, false, "Return the lowest tail value or nil.", args(1,2, argany("",2),batargany("b",2))),
1840 : command("aggr", "min", ALGminany_skipnil, false, "Return the lowest tail value or nil.", args(1,3, argany("",2),batargany("b",2),arg("skipnil",bit))),
1841 : command("aggr", "max", ALGmaxany, false, "Return the highest tail value or nil.", args(1,2, argany("",2),batargany("b",2))),
1842 : command("aggr", "max", ALGmaxany_skipnil, false, "Return the highest tail value or nil.", args(1,3, argany("",2),batargany("b",2),arg("skipnil",bit))),
1843 : command("aggr", "stdev", ALGstdev, false, "Gives the standard deviation of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1844 : command("aggr", "stdevp", ALGstdevp, false, "Gives the standard deviation of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1845 : command("aggr", "variance", ALGvariance, false, "Gives the variance of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1846 : command("aggr", "variancep", ALGvariancep, false, "Gives the variance of all tail values", args(1,2, arg("",dbl),batargany("b",2))),
1847 : command("aggr", "covariance", ALGcovariance, false, "Gives the covariance of all tail values", args(1,3, arg("",dbl),batargany("b1",2),batargany("b2",2))),
1848 : command("aggr", "covariancep", ALGcovariancep, false, "Gives the covariance of all tail values", args(1,3, arg("",dbl),batargany("b1",2),batargany("b2",2))),
1849 : command("aggr", "corr", ALGcorr, false, "Gives the correlation of all tail values", args(1,3, arg("",dbl),batargany("b1",2),batargany("b2",2))),
1850 : // sql
1851 : command("aggr", "exist", ALGexist, false, "", args(1,3, arg("",bit),batargany("b",2),argany("h",1))),
1852 : { .imp=NULL }
1853 : };
1854 : #include "mal_import.h"
1855 : #ifdef _MSC_VER
1856 : #undef read
1857 : #pragma section(".CRT$XCU",read)
1858 : #endif
1859 321 : LIB_STARTUP_FUNC(init_algebra_mal)
1860 321 : { mal_module("algebra", NULL, algebra_init_funcs); }
|