1 | /* |
2 | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
5 | * |
6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | /* |
10 | * (c) Peter Boncz, Martin Kersten, Niels Nes, Sjoerd Mullender |
11 | * BAT Algebra |
12 | * This modules contains the most common algebraic BAT manipulation |
13 | * commands. We call them algebra, because all operations take |
14 | * values as parameters, and produce new result values, but |
15 | * do not modify their parameters. |
16 | * |
17 | * Unlike the previous Monet versions, we reduce the number |
18 | * of functions returning a BAT reference. This was previously needed |
19 | * to simplify recursive bat-expression and manage reference counts. |
20 | * In the current version we return only a BAT identifier when a new |
21 | * bat is being created. |
22 | * |
23 | * All parameters to the modules are passed by reference. |
24 | * In particular, this means that |
25 | * string values are passed to the module layer as (str *) |
26 | * and we have to de-reference them before entering the gdk library. |
27 | * This calls for knowlegde on the underlying BAT typs`s |
28 | */ |
29 | #define derefStr(b, v) \ |
30 | do { \ |
31 | int _tpe= ATOMstorage((b)->ttype); \ |
32 | if (_tpe >= TYPE_str) { \ |
33 | if ((v) == 0 || *(str*) (v) == 0) \ |
34 | (v) = (str) str_nil; \ |
35 | else \ |
36 | (v) = *(str *) (v); \ |
37 | } \ |
38 | } while (0) |
39 | |
40 | #include "monetdb_config.h" |
41 | #include "algebra.h" |
42 | #include <math.h> |
43 | |
44 | /* |
45 | * Command Implementations in C |
46 | * This module contains just a wrapper implementations; since all described |
47 | * operations are part of the GDK kernel. |
48 | * |
49 | * BAT sum operation |
50 | * The sum aggregate only works for int and float fields. |
51 | * The routines below assumes that the caller knows what type |
52 | * is large enough to prevent overflow. |
53 | */ |
54 | |
55 | static gdk_return |
56 | CMDgen_group(BAT **result, BAT *gids, BAT *cnts ) |
57 | { |
58 | lng j, gcnt = BATcount(gids); |
59 | BAT *r = COLnew(0, TYPE_oid, BATcount(gids)*2, TRANSIENT); |
60 | |
61 | if (r == NULL) |
62 | return GDK_FAIL; |
63 | if (gids->ttype == TYPE_void) { |
64 | oid id = gids->tseqbase; |
65 | lng *cnt = (lng*)Tloc(cnts, 0); |
66 | for(j = 0; j < gcnt; j++) { |
67 | lng i, sz = cnt[j]; |
68 | for(i = 0; i < sz; i++) { |
69 | if (BUNappend(r, &id, false) != GDK_SUCCEED) { |
70 | BBPreclaim(r); |
71 | return GDK_FAIL; |
72 | } |
73 | } |
74 | id++; |
75 | } |
76 | } else { |
77 | oid *id = (oid*)Tloc(gids, 0); |
78 | lng *cnt = (lng*)Tloc(cnts, 0); |
79 | for(j = 0; j < gcnt; j++) { |
80 | lng i, sz = cnt[j]; |
81 | for(i = 0; i < sz; i++) { |
82 | if (BUNappend(r, id, false) != GDK_SUCCEED) { |
83 | BBPreclaim(r); |
84 | return GDK_FAIL; |
85 | } |
86 | } |
87 | id++; |
88 | } |
89 | } |
90 | r -> tkey = false; |
91 | r -> tseqbase = oid_nil; |
92 | r -> tsorted = BATtordered(gids); |
93 | r -> trevsorted = BATtrevordered(gids); |
94 | r -> tnonil = gids->tnonil; |
95 | *result = r; |
96 | return GDK_SUCCEED; |
97 | } |
98 | |
99 | |
100 | static gdk_return |
101 | slice(BAT **retval, BAT *b, lng start, lng end) |
102 | { |
103 | /* the internal BATslice requires exclusive end */ |
104 | if (start < 0) { |
105 | GDKerror("CMDslice: start position of slice should >= 0\n" ); |
106 | return GDK_FAIL; |
107 | } |
108 | if (is_lng_nil(end)) |
109 | end = BATcount(b); |
110 | if (start > (lng) BUN_MAX || end >= (lng) BUN_MAX) { |
111 | GDKerror("CMDslice: argument out of range\n" ); |
112 | return GDK_FAIL; |
113 | } |
114 | |
115 | return (*retval = BATslice(b, (BUN) start, (BUN) end + 1)) ? GDK_SUCCEED : GDK_FAIL; |
116 | } |
117 | /* |
118 | * |
119 | * The remainder of this file contains the wrapper around the V4 code base |
120 | * The BAT identifiers passed through this module may indicate |
121 | * that the 'reverse' view applies. This should be taken into |
122 | * account while resolving them. |
123 | * |
124 | * The sum aggregate only works for int and float fields. |
125 | * The routines below assumes that the caller knows what type |
126 | * is large enough to prevent overflow. |
127 | */ |
128 | |
129 | str |
130 | ALGminany_skipnil(ptr result, const bat *bid, const bit *skipnil) |
131 | { |
132 | BAT *b; |
133 | ptr p; |
134 | str msg = MAL_SUCCEED; |
135 | |
136 | if (result == NULL || (b = BATdescriptor(*bid)) == NULL) |
137 | throw(MAL, "algebra.min" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
138 | |
139 | if (!ATOMlinear(b->ttype)) { |
140 | msg = createException(MAL, "algebra.min" , |
141 | "atom '%s' cannot be ordered linearly" , |
142 | ATOMname(b->ttype)); |
143 | } else { |
144 | if (ATOMextern(b->ttype)) { |
145 | * (ptr *) result = p = BATmin_skipnil(b, NULL, *skipnil); |
146 | } else { |
147 | p = BATmin_skipnil(b, result, *skipnil); |
148 | if ( p != result ) |
149 | msg = createException(MAL, "algebra.min" , SQLSTATE(HY002) "INTERNAL ERROR" ); |
150 | } |
151 | if (msg == MAL_SUCCEED && p == NULL) |
152 | msg = createException(MAL, "algebra.min" , GDK_EXCEPTION); |
153 | } |
154 | BBPunfix(b->batCacheid); |
155 | return msg; |
156 | } |
157 | |
158 | str |
159 | ALGminany(ptr result, const bat *bid) |
160 | { |
161 | bit skipnil = TRUE; |
162 | return ALGminany_skipnil(result, bid, &skipnil); |
163 | } |
164 | |
165 | str |
166 | ALGmaxany_skipnil(ptr result, const bat *bid, const bit *skipnil) |
167 | { |
168 | BAT *b; |
169 | ptr p; |
170 | str msg = MAL_SUCCEED; |
171 | |
172 | if (result == NULL || (b = BATdescriptor(*bid)) == NULL) |
173 | throw(MAL, "algebra.max" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
174 | |
175 | if (!ATOMlinear(b->ttype)) { |
176 | msg = createException(MAL, "algebra.max" , |
177 | "atom '%s' cannot be ordered linearly" , |
178 | ATOMname(b->ttype)); |
179 | } else { |
180 | if (ATOMextern(b->ttype)) { |
181 | * (ptr *) result = p = BATmax_skipnil(b, NULL, *skipnil); |
182 | } else { |
183 | p = BATmax_skipnil(b, result, *skipnil); |
184 | if ( p != result ) |
185 | msg = createException(MAL, "algebra.max" , SQLSTATE(HY002) "INTERNAL ERROR" ); |
186 | } |
187 | if ( msg == MAL_SUCCEED && p == NULL) |
188 | msg = createException(MAL, "algebra.max" , GDK_EXCEPTION); |
189 | } |
190 | BBPunfix(b->batCacheid); |
191 | return msg; |
192 | } |
193 | |
194 | str |
195 | ALGmaxany(ptr result, const bat *bid) |
196 | { |
197 | bit skipnil = TRUE; |
198 | return ALGmaxany_skipnil(result, bid, &skipnil); |
199 | } |
200 | |
201 | str |
202 | ALGgroupby(bat *res, const bat *gids, const bat *cnts) |
203 | { |
204 | BAT *bn, *g, *c; |
205 | |
206 | g = BATdescriptor(*gids); |
207 | if (g == NULL) { |
208 | throw(MAL, "algebra.groupby" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
209 | } |
210 | c = BATdescriptor(*cnts); |
211 | if (c == NULL) { |
212 | BBPunfix(g->batCacheid); |
213 | throw(MAL, "algebra.groupby" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
214 | } |
215 | if( CMDgen_group(&bn, g, c) != GDK_SUCCEED){ |
216 | BBPunfix(g->batCacheid); |
217 | BBPunfix(c->batCacheid); |
218 | throw(MAL, "algebra.groupby" ,GDK_EXCEPTION); |
219 | } |
220 | *res = bn->batCacheid; |
221 | BBPkeepref(bn->batCacheid); |
222 | BBPunfix(g->batCacheid); |
223 | BBPunfix(c->batCacheid); |
224 | return MAL_SUCCEED; |
225 | } |
226 | |
227 | str |
228 | ALGcard(lng *result, const bat *bid) |
229 | { |
230 | BAT *b, *en; |
231 | |
232 | if ((b = BATdescriptor(*bid)) == NULL) { |
233 | throw(MAL, "algebra.card" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
234 | } |
235 | en = BATunique(b, NULL); |
236 | BBPunfix(b->batCacheid); |
237 | if (en == NULL) { |
238 | throw(MAL, "algebra.card" , GDK_EXCEPTION); |
239 | } |
240 | *result = BATcount(en); |
241 | BBPunfix(en->batCacheid); |
242 | return MAL_SUCCEED; |
243 | } |
244 | |
245 | str |
246 | ALGselect2(bat *result, const bat *bid, const bat *sid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti) |
247 | { |
248 | BAT *b, *s = NULL, *bn; |
249 | const void *nilptr; |
250 | |
251 | if ((*li != 0 && *li != 1) || |
252 | (*hi != 0 && *hi != 1) || |
253 | (*anti != 0 && *anti != 1)) { |
254 | throw(MAL, "algebra.select" , ILLEGAL_ARGUMENT); |
255 | } |
256 | if ((b = BATdescriptor(*bid)) == NULL) { |
257 | throw(MAL, "algebra.select" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
258 | } |
259 | if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) { |
260 | BBPunfix(b->batCacheid); |
261 | throw(MAL, "algebra.select" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
262 | } |
263 | derefStr(b, low); |
264 | derefStr(b, high); |
265 | nilptr = ATOMnilptr(b->ttype); |
266 | if (*li == 1 && *hi == 1 && |
267 | ATOMcmp(b->ttype, low, nilptr) == 0 && |
268 | ATOMcmp(b->ttype, high, nilptr) == 0) { |
269 | /* special case: equi-select for NIL */ |
270 | high = NULL; |
271 | } |
272 | bn = BATselect(b, s, low, high, *li, *hi, *anti); |
273 | BBPunfix(b->batCacheid); |
274 | if (s) |
275 | BBPunfix(s->batCacheid); |
276 | if (bn == NULL) |
277 | throw(MAL, "algebra.select" , GDK_EXCEPTION); |
278 | *result = bn->batCacheid; |
279 | BBPkeepref(bn->batCacheid); |
280 | return MAL_SUCCEED; |
281 | } |
282 | |
283 | str |
284 | ALGselect2nil(bat *result, const bat *bid, const bat *sid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown) |
285 | { |
286 | BAT *b, *s = NULL, *bn; |
287 | const void *nilptr; |
288 | |
289 | if (!*unknown) |
290 | return ALGselect2(result, bid, sid, low, high, li, hi, anti); |
291 | |
292 | if ((*li != 0 && *li != 1) || |
293 | (*hi != 0 && *hi != 1) || |
294 | (*anti != 0 && *anti != 1)) { |
295 | throw(MAL, "algebra.select" , ILLEGAL_ARGUMENT); |
296 | } |
297 | if ((b = BATdescriptor(*bid)) == NULL) { |
298 | throw(MAL, "algebra.select" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
299 | } |
300 | if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) { |
301 | BBPunfix(b->batCacheid); |
302 | throw(MAL, "algebra.select" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
303 | } |
304 | derefStr(b, low); |
305 | derefStr(b, high); |
306 | /* here we don't need open ended parts with nil */ |
307 | nilptr = ATOMnilptr(b->ttype); |
308 | if (*li == 1 && ATOMcmp(b->ttype, low, nilptr) == 0) |
309 | low = high; |
310 | else if (*hi == 1 && ATOMcmp(b->ttype, high, nilptr) == 0) |
311 | high = low; |
312 | bn = BATselect(b, s, low, high, *li, *hi, *anti); |
313 | BBPunfix(b->batCacheid); |
314 | if (s) |
315 | BBPunfix(s->batCacheid); |
316 | if (bn == NULL) |
317 | throw(MAL, "algebra.select" , GDK_EXCEPTION); |
318 | *result = bn->batCacheid; |
319 | BBPkeepref(bn->batCacheid); |
320 | return MAL_SUCCEED; |
321 | } |
322 | |
323 | str |
324 | ALGselect1(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti) |
325 | { |
326 | return ALGselect2(result, bid, NULL, low, high, li, hi, anti); |
327 | } |
328 | |
329 | str |
330 | ALGselect1nil(bat *result, const bat *bid, const void *low, const void *high, const bit *li, const bit *hi, const bit *anti, const bit *unknown) |
331 | { |
332 | return ALGselect2nil(result, bid, NULL, low, high, li, hi, anti, unknown); |
333 | } |
334 | |
335 | str |
336 | ALGthetaselect2(bat *result, const bat *bid, const bat *sid, const void *val, const char **op) |
337 | { |
338 | BAT *b, *s = NULL, *bn; |
339 | |
340 | if ((b = BATdescriptor(*bid)) == NULL) { |
341 | throw(MAL, "algebra.thetaselect" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
342 | } |
343 | if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) { |
344 | BBPunfix(b->batCacheid); |
345 | throw(MAL, "algebra.thetaselect" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
346 | } |
347 | derefStr(b, val); |
348 | bn = BATthetaselect(b, s, val, *op); |
349 | BBPunfix(b->batCacheid); |
350 | if (s) |
351 | BBPunfix(s->batCacheid); |
352 | if (bn == NULL) |
353 | throw(MAL, "algebra.select" , GDK_EXCEPTION); |
354 | *result = bn->batCacheid; |
355 | BBPkeepref(bn->batCacheid); |
356 | return MAL_SUCCEED; |
357 | } |
358 | |
359 | str |
360 | ALGthetaselect1(bat *result, const bat *bid, const void *val, const char **op) |
361 | { |
362 | return ALGthetaselect2(result, bid, NULL, val, op); |
363 | } |
364 | |
365 | str |
366 | ALGselectNotNil(bat *result, const bat *bid) |
367 | { |
368 | BAT *b, *bn = NULL; |
369 | |
370 | if ((b = BATdescriptor(*bid)) == NULL) |
371 | throw(MAL, "algebra.selectNotNil" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
372 | |
373 | if( BATcount_no_nil(b) != BATcount(b) ){ |
374 | BAT *s = NULL; |
375 | |
376 | s = BATselect(b, s, ATOMnilptr(b->ttype), NULL, true, true, true); |
377 | if (s) { |
378 | bn = BATproject(s, b); |
379 | BBPunfix(s->batCacheid); |
380 | } |
381 | BBPunfix(b->batCacheid); |
382 | if (bn) { |
383 | *result = bn->batCacheid; |
384 | BBPkeepref(*result); |
385 | return MAL_SUCCEED; |
386 | } |
387 | throw(MAL, "algebra.selectNotNil" , GDK_EXCEPTION); |
388 | } |
389 | /* just pass on the result */ |
390 | *result = b->batCacheid; |
391 | BBPkeepref(*result); |
392 | return MAL_SUCCEED; |
393 | } |
394 | |
395 | static str |
396 | do_join(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *r2id, |
397 | const bat *slid, const bat *srid, |
398 | int op, const void *c1, const void *c2, bool li, bool hi, |
399 | bool anti, bool symmetric, /* these two only for rangejoin */ |
400 | const bit *nil_matches, const bit *not_in, const lng *estimate, |
401 | gdk_return (*joinfunc)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *, |
402 | bool, BUN), |
403 | gdk_return (*thetafunc)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *, |
404 | int, bool, BUN), |
405 | gdk_return (*bandfunc)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *, |
406 | const void *, const void *, bool, bool, BUN), |
407 | gdk_return (*rangefunc)(BAT **, BAT **, BAT *, BAT *, BAT *, |
408 | BAT *, BAT *, bool, bool, bool, bool, BUN), |
409 | BAT *(*difffunc)(BAT *, BAT *, BAT *, BAT *, bool, bool, BUN), |
410 | BAT *(*interfunc)(BAT *, BAT *, BAT *, BAT *, bool, BUN), |
411 | const char *funcname) |
412 | { |
413 | BAT *left = NULL, *right = NULL, *right2 = NULL; |
414 | BAT *candleft = NULL, *candright = NULL; |
415 | BAT *result1, *result2; |
416 | BUN est; |
417 | const char *err = RUNTIME_OBJECT_MISSING; |
418 | |
419 | assert(r2id == NULL || rangefunc != NULL); |
420 | |
421 | if ((left = BATdescriptor(*lid)) == NULL) |
422 | goto fail; |
423 | if ((right = BATdescriptor(*rid)) == NULL) |
424 | goto fail; |
425 | if (slid && !is_bat_nil(*slid) && (candleft = BATdescriptor(*slid)) == NULL) |
426 | goto fail; |
427 | if (srid && !is_bat_nil(*srid) && (candright = BATdescriptor(*srid)) == NULL) |
428 | goto fail; |
429 | if (estimate == NULL || *estimate < 0 || is_lng_nil(*estimate) || *estimate > (lng) BUN_MAX) |
430 | est = BUN_NONE; |
431 | else |
432 | est = (BUN) *estimate; |
433 | |
434 | err = NULL; /* most likely error now is GDK_EXCEPTION */ |
435 | |
436 | if (thetafunc) { |
437 | assert(joinfunc == NULL); |
438 | assert(bandfunc == NULL); |
439 | assert(rangefunc == NULL); |
440 | assert(difffunc == NULL); |
441 | assert(interfunc == NULL); |
442 | if ((*thetafunc)(&result1, r2 ? &result2 : NULL, left, right, candleft, candright, op, *nil_matches, est) != GDK_SUCCEED) |
443 | goto fail; |
444 | } else if (joinfunc) { |
445 | assert(bandfunc == NULL); |
446 | assert(rangefunc == NULL); |
447 | assert(difffunc == NULL); |
448 | assert(interfunc == NULL); |
449 | result2 = NULL; |
450 | if ((*joinfunc)(&result1, r2 ? &result2 : NULL, left, right, candleft, candright, *nil_matches, est) != GDK_SUCCEED) |
451 | goto fail; |
452 | } else if (bandfunc) { |
453 | assert(rangefunc == NULL); |
454 | assert(difffunc == NULL); |
455 | assert(interfunc == NULL); |
456 | if ((*bandfunc)(&result1, r2 ? &result2 : NULL, left, right, candleft, candright, c1, c2, li, hi, est) != GDK_SUCCEED) |
457 | goto fail; |
458 | } else if (rangefunc) { |
459 | assert(difffunc == NULL); |
460 | assert(interfunc == NULL); |
461 | if ((right2 = BATdescriptor(*r2id)) == NULL) { |
462 | err = SQLSTATE(HY002) RUNTIME_OBJECT_MISSING; |
463 | goto fail; |
464 | } |
465 | if ((*rangefunc)(&result1, r2 ? &result2 : NULL, left, right, right2, candleft, candright, li, hi, anti, symmetric, est) != GDK_SUCCEED) |
466 | goto fail; |
467 | BBPunfix(right2->batCacheid); |
468 | } else if (difffunc) { |
469 | assert(r2 == NULL); |
470 | assert(interfunc == NULL); |
471 | if ((result1 = (*difffunc)(left, right, candleft, candright, *nil_matches, *not_in, est)) == NULL) |
472 | goto fail; |
473 | result2 = NULL; |
474 | } else { |
475 | assert(r2 == NULL); |
476 | if ((result1 = (*interfunc)(left, right, candleft, candright, *nil_matches, est)) == NULL) |
477 | goto fail; |
478 | result2 = NULL; |
479 | } |
480 | *r1 = result1->batCacheid; |
481 | BBPkeepref(*r1); |
482 | if (r2) { |
483 | *r2 = result2->batCacheid; |
484 | BBPkeepref(*r2); |
485 | } |
486 | BBPunfix(left->batCacheid); |
487 | BBPunfix(right->batCacheid); |
488 | if (candleft) |
489 | BBPunfix(candleft->batCacheid); |
490 | if (candright) |
491 | BBPunfix(candright->batCacheid); |
492 | return MAL_SUCCEED; |
493 | |
494 | fail: |
495 | if (left) |
496 | BBPunfix(left->batCacheid); |
497 | if (right) |
498 | BBPunfix(right->batCacheid); |
499 | if (right2) |
500 | BBPunfix(right2->batCacheid); |
501 | if (candleft) |
502 | BBPunfix(candleft->batCacheid); |
503 | if (candright) |
504 | BBPunfix(candright->batCacheid); |
505 | if (err == NULL) |
506 | throw(MAL, funcname, GDK_EXCEPTION); |
507 | throw(MAL, funcname, "%s" , err); |
508 | } |
509 | |
510 | str |
511 | ALGjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
512 | const bit *nil_matches, const lng *estimate) |
513 | { |
514 | return do_join(r1, r2, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
515 | false, false, false, false, nil_matches, NULL, estimate, |
516 | BATjoin, NULL, NULL, NULL, NULL, NULL, "algebra.join" ); |
517 | } |
518 | |
519 | str |
520 | ALGjoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
521 | const bit *nil_matches, const lng *estimate) |
522 | { |
523 | return do_join(r1, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
524 | false, false, false, false, nil_matches, NULL, estimate, |
525 | BATjoin, NULL, NULL, NULL, NULL, NULL, "algebra.join" ); |
526 | } |
527 | |
528 | str |
529 | ALGleftjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
530 | const bit *nil_matches, const lng *estimate) |
531 | { |
532 | return do_join(r1, r2, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
533 | false, false, false, false, nil_matches, NULL, estimate, |
534 | BATleftjoin, NULL, NULL, NULL, NULL, NULL, "algebra.leftjoin" ); |
535 | } |
536 | |
537 | str |
538 | ALGleftjoin1(bat *r1, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
539 | const bit *nil_matches, const lng *estimate) |
540 | { |
541 | return do_join(r1, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
542 | false, false, false, false, nil_matches, NULL, estimate, |
543 | BATleftjoin, NULL, NULL, NULL, NULL, NULL, "algebra.leftjoin" ); |
544 | } |
545 | |
546 | str |
547 | ALGouterjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
548 | const bit *nil_matches, const lng *estimate) |
549 | { |
550 | return do_join(r1, r2, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
551 | false, false, false, false, nil_matches, NULL, estimate, |
552 | BATouterjoin, NULL, NULL, NULL, NULL, NULL, "algebra.outerjoin" ); |
553 | } |
554 | |
555 | str |
556 | ALGsemijoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
557 | const bit *nil_matches, const lng *estimate) |
558 | { |
559 | return do_join(r1, r2, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
560 | false, false, false, false, nil_matches, NULL, estimate, |
561 | BATsemijoin, NULL, NULL, NULL, NULL, NULL, "algebra.semijoin" ); |
562 | } |
563 | |
564 | str |
565 | ALGthetajoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
566 | const int *op, const bit *nil_matches, const lng *estimate) |
567 | { |
568 | return do_join(r1, r2, lid, rid, NULL, slid, srid, *op, NULL, NULL, |
569 | false, false, false, false, nil_matches, NULL, estimate, |
570 | NULL, BATthetajoin, NULL, NULL, NULL, NULL, "algebra.thetajoin" ); |
571 | } |
572 | |
573 | str |
574 | ALGbandjoin(bat *r1, bat *r2, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
575 | const void *c1, const void *c2, const bit *li, const bit *hi, |
576 | const lng *estimate) |
577 | { |
578 | return do_join(r1, r2, lid, rid, NULL, slid, srid, 0, c1, c2, |
579 | *li, *hi, false, false, NULL, NULL, estimate, |
580 | NULL, NULL, BATbandjoin, NULL, NULL, NULL, "algebra.bandjoin" ); |
581 | } |
582 | |
583 | str |
584 | ALGrangejoin(bat *r1, bat *r2, const bat *lid, const bat *rlid, const bat *rhid, const bat *slid, const bat *srid, const bit *li, const bit *hi, const bit *anti, const bit *symmetric, const lng *estimate) |
585 | { |
586 | return do_join(r1, r2, lid, rlid, rhid, slid, srid, 0, NULL, NULL, |
587 | *li, *hi, *anti, *symmetric, NULL, NULL, estimate, |
588 | NULL, NULL, NULL, BATrangejoin, NULL, NULL, "algebra.rangejoin" ); |
589 | } |
590 | |
591 | str |
592 | ALGdifference(bat *r1, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
593 | const bit *nil_matches, const bit *not_in, const lng *estimate) |
594 | { |
595 | return do_join(r1, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
596 | false, false, false, false, nil_matches, not_in, estimate, |
597 | NULL, NULL, NULL, NULL, BATdiff, NULL, "algebra.difference" ); |
598 | } |
599 | |
600 | str |
601 | ALGintersect(bat *r1, const bat *lid, const bat *rid, const bat *slid, const bat *srid, |
602 | const bit *nil_matches, const lng *estimate) |
603 | { |
604 | return do_join(r1, NULL, lid, rid, NULL, slid, srid, 0, NULL, NULL, |
605 | false, false, false, false, nil_matches, NULL, estimate, |
606 | NULL, NULL, NULL, NULL, NULL, BATintersect, "algebra.intersect" ); |
607 | } |
608 | |
609 | /* algebra.firstn(b:bat[:any], |
610 | * [ s:bat[:oid], |
611 | * [ g:bat[:oid], ] ] |
612 | * n:lng, |
613 | * asc:bit, |
614 | * nilslast:bit, |
615 | * distinct:bit) |
616 | * returns :bat[:oid] [ , :bat[:oid] ] |
617 | */ |
618 | str |
619 | ALGfirstn(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
620 | { |
621 | bat *ret1, *ret2 = NULL; |
622 | bat bid, sid, gid; |
623 | BAT *b, *s = NULL, *g = NULL; |
624 | BAT *bn, *gn; |
625 | lng n; |
626 | bit asc, nilslast, distinct; |
627 | gdk_return rc; |
628 | |
629 | (void) cntxt; |
630 | (void) mb; |
631 | |
632 | assert(pci->retc == 1 || pci->retc == 2); |
633 | assert(pci->argc - pci->retc >= 5 && pci->argc - pci->retc <= 7); |
634 | |
635 | n = * getArgReference_lng(stk, pci, pci->argc - 4); |
636 | if (n < 0 || (lng) n >= (lng) BUN_MAX) |
637 | throw(MAL, "algebra.firstn" , ILLEGAL_ARGUMENT); |
638 | ret1 = getArgReference_bat(stk, pci, 0); |
639 | if (pci->retc == 2) |
640 | ret2 = getArgReference_bat(stk, pci, 1); |
641 | bid = *getArgReference_bat(stk, pci, pci->retc); |
642 | if ((b = BATdescriptor(bid)) == NULL) |
643 | throw(MAL, "algebra.firstn" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
644 | if (pci->argc - pci->retc > 5) { |
645 | sid = *getArgReference_bat(stk, pci, pci->retc + 1); |
646 | if ((s = BATdescriptor(sid)) == NULL) { |
647 | BBPunfix(bid); |
648 | throw(MAL, "algebra.firstn" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
649 | } |
650 | if (pci->argc - pci->retc > 6) { |
651 | gid = *getArgReference_bat(stk, pci, pci->retc + 2); |
652 | if ((g = BATdescriptor(gid)) == NULL) { |
653 | BBPunfix(bid); |
654 | BBPunfix(sid); |
655 | throw(MAL, "algebra.firstn" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
656 | } |
657 | } |
658 | } |
659 | asc = * getArgReference_bit(stk, pci, pci->argc - 3); |
660 | nilslast = * getArgReference_bit(stk, pci, pci->argc - 2); |
661 | distinct = * getArgReference_bit(stk, pci, pci->argc - 1); |
662 | rc = BATfirstn(&bn, ret2 ? &gn : NULL, b, s, g, (BUN) n, asc, nilslast, distinct); |
663 | BBPunfix(b->batCacheid); |
664 | if (s) |
665 | BBPunfix(s->batCacheid); |
666 | if (g) |
667 | BBPunfix(g->batCacheid); |
668 | if (rc != GDK_SUCCEED) |
669 | throw(MAL, "algebra.firstn" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
670 | BBPkeepref(*ret1 = bn->batCacheid); |
671 | if (ret2) |
672 | BBPkeepref(*ret2 = gn->batCacheid); |
673 | return MAL_SUCCEED; |
674 | } |
675 | |
676 | static str |
677 | ALGunary(bat *result, const bat *bid, BAT *(*func)(BAT *), const char *name) |
678 | { |
679 | BAT *b,*bn; |
680 | |
681 | if ((b= BATdescriptor(*bid)) == NULL) { |
682 | throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
683 | } |
684 | bn = (*func)(b); |
685 | BBPunfix(b->batCacheid); |
686 | if (bn == NULL) |
687 | throw(MAL, name, GDK_EXCEPTION); |
688 | *result = bn->batCacheid; |
689 | BBPkeepref(*result); |
690 | return MAL_SUCCEED; |
691 | } |
692 | |
693 | static str |
694 | ALGbinary(bat *result, const bat *lid, const bat *rid, BAT *(*func)(BAT *, BAT *), const char *name) |
695 | { |
696 | BAT *left, *right,*bn= NULL; |
697 | |
698 | if ((left = BATdescriptor(*lid)) == NULL) { |
699 | throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
700 | } |
701 | if ((right = BATdescriptor(*rid)) == NULL) { |
702 | BBPunfix(left->batCacheid); |
703 | throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
704 | } |
705 | bn = (*func)(left, right); |
706 | BBPunfix(left->batCacheid); |
707 | BBPunfix(right->batCacheid); |
708 | if (bn == NULL) |
709 | throw(MAL, name, GDK_EXCEPTION); |
710 | *result = bn->batCacheid; |
711 | BBPkeepref(*result); |
712 | return MAL_SUCCEED; |
713 | } |
714 | |
715 | static BAT * |
716 | BATwcopy(BAT *b) |
717 | { |
718 | return COLcopy(b, b->ttype, true, TRANSIENT); |
719 | } |
720 | |
721 | str |
722 | ALGcopy(bat *result, const bat *bid) |
723 | { |
724 | return ALGunary(result, bid, BATwcopy, "algebra.copy" ); |
725 | } |
726 | |
727 | str |
728 | ALGunique2(bat *result, const bat *bid, const bat *sid) |
729 | { |
730 | BAT *b, *s = NULL, *bn = NULL; |
731 | |
732 | if ((b = BATdescriptor(*bid)) == NULL) { |
733 | throw(MAL, "algebra.unique" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
734 | } |
735 | if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) { |
736 | BBPunfix(b->batCacheid); |
737 | throw(MAL, "algebra.unique" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
738 | } |
739 | bn = BATunique(b, s); |
740 | BBPunfix(b->batCacheid); |
741 | if (s) |
742 | BBPunfix(s->batCacheid); |
743 | if (bn == NULL) |
744 | throw(MAL, "algebra.unique" , GDK_EXCEPTION); |
745 | *result = bn->batCacheid; |
746 | BBPkeepref(*result); |
747 | return MAL_SUCCEED; |
748 | } |
749 | |
750 | str |
751 | ALGunique1(bat *result, const bat *bid) |
752 | { |
753 | return ALGunique2(result, bid, NULL); |
754 | } |
755 | |
756 | str |
757 | ALGcrossproduct2( bat *l, bat *r, const bat *left, const bat *right) |
758 | { |
759 | BAT *L, *R, *bn1, *bn2; |
760 | gdk_return ret; |
761 | |
762 | if ((L = BATdescriptor(*left)) == NULL) { |
763 | throw(MAL, "algebra.crossproduct" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
764 | } |
765 | if ((R = BATdescriptor(*right)) == NULL) { |
766 | BBPunfix(L->batCacheid); |
767 | throw(MAL, "algebra.crossproduct" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
768 | } |
769 | ret = BATsubcross(&bn1, &bn2, L, R, NULL, NULL); |
770 | BBPunfix(L->batCacheid); |
771 | BBPunfix(R->batCacheid); |
772 | if (ret != GDK_SUCCEED) |
773 | throw(MAL, "algebra.crossproduct" , GDK_EXCEPTION); |
774 | BBPkeepref(*l = bn1->batCacheid); |
775 | BBPkeepref(*r = bn2->batCacheid); |
776 | return MAL_SUCCEED; |
777 | } |
778 | |
779 | str |
780 | ALGprojection(bat *result, const bat *lid, const bat *rid) |
781 | { |
782 | return ALGbinary(result, lid, rid, BATproject, "algebra.projection" ); |
783 | } |
784 | |
785 | str |
786 | ALGsort33(bat *result, bat *norder, bat *ngroup, const bat *bid, const bat *order, const bat *group, const bit *reverse, const bit *nilslast, const bit *stable) |
787 | { |
788 | BAT *bn = NULL, *on = NULL, *gn = NULL; |
789 | BAT *b = NULL, *o = NULL, *g = NULL; |
790 | |
791 | if ((b = BATdescriptor(*bid)) == NULL) |
792 | throw(MAL, "algebra.sort" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
793 | if (order && !is_bat_nil(*order) && (o = BATdescriptor(*order)) == NULL) { |
794 | BBPunfix(b->batCacheid); |
795 | throw(MAL, "algebra.sort" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
796 | } |
797 | if (group && !is_bat_nil(*group) && (g = BATdescriptor(*group)) == NULL) { |
798 | if (o) |
799 | BBPunfix(o->batCacheid); |
800 | BBPunfix(b->batCacheid); |
801 | throw(MAL, "algebra.sort" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
802 | } |
803 | if (BATsort(result ? &bn : NULL, |
804 | norder ? &on : NULL, |
805 | ngroup ? &gn : NULL, |
806 | b, o, g, *reverse, *nilslast, *stable) != GDK_SUCCEED) { |
807 | if (o) |
808 | BBPunfix(o->batCacheid); |
809 | if (g) |
810 | BBPunfix(g->batCacheid); |
811 | BBPunfix(b->batCacheid); |
812 | throw(MAL, "algebra.sort" , OPERATION_FAILED); |
813 | } |
814 | BBPunfix(b->batCacheid); |
815 | if (o) |
816 | BBPunfix(o->batCacheid); |
817 | if (g) |
818 | BBPunfix(g->batCacheid); |
819 | if (result) |
820 | BBPkeepref(*result = bn->batCacheid); |
821 | if (norder) |
822 | BBPkeepref(*norder = on->batCacheid); |
823 | if (ngroup) |
824 | BBPkeepref(*ngroup = gn->batCacheid); |
825 | return MAL_SUCCEED; |
826 | } |
827 | |
828 | str |
829 | ALGsort32(bat *result, bat *norder, const bat *bid, const bat *order, const bat *group, const bit *reverse, const bit *nilslast, const bit *stable) |
830 | { |
831 | return ALGsort33(result, norder, NULL, bid, order, group, reverse, nilslast, stable); |
832 | } |
833 | |
834 | str |
835 | ALGsort31(bat *result, const bat *bid, const bat *order, const bat *group, const bit *reverse, const bit *nilslast, const bit *stable) |
836 | { |
837 | return ALGsort33(result, NULL, NULL, bid, order, group, reverse, nilslast, stable); |
838 | } |
839 | |
840 | str |
841 | ALGsort23(bat *result, bat *norder, bat *ngroup, const bat *bid, const bat *order, const bit *reverse, const bit *nilslast, const bit *stable) |
842 | { |
843 | return ALGsort33(result, norder, ngroup, bid, order, NULL, reverse, nilslast, stable); |
844 | } |
845 | |
846 | str |
847 | ALGsort22(bat *result, bat *norder, const bat *bid, const bat *order, const bit *reverse, const bit *nilslast, const bit *stable) |
848 | { |
849 | return ALGsort33(result, norder, NULL, bid, order, NULL, reverse, nilslast, stable); |
850 | } |
851 | |
852 | str |
853 | ALGsort21(bat *result, const bat *bid, const bat *order, const bit *reverse, const bit *nilslast, const bit *stable) |
854 | { |
855 | return ALGsort33(result, NULL, NULL, bid, order, NULL, reverse, nilslast, stable); |
856 | } |
857 | |
858 | str |
859 | ALGsort13(bat *result, bat *norder, bat *ngroup, const bat *bid, const bit *reverse, const bit *nilslast, const bit *stable) |
860 | { |
861 | return ALGsort33(result, norder, ngroup, bid, NULL, NULL, reverse, nilslast, stable); |
862 | } |
863 | |
864 | str |
865 | ALGsort12(bat *result, bat *norder, const bat *bid, const bit *reverse, const bit *nilslast, const bit *stable) |
866 | { |
867 | return ALGsort33(result, norder, NULL, bid, NULL, NULL, reverse, nilslast, stable); |
868 | } |
869 | |
870 | str |
871 | ALGsort11(bat *result, const bat *bid, const bit *reverse, const bit *nilslast, const bit *stable) |
872 | { |
873 | return ALGsort33(result, NULL, NULL, bid, NULL, NULL, reverse, nilslast, stable); |
874 | } |
875 | |
876 | str |
877 | ALGcount_bat(lng *result, const bat *bid) |
878 | { |
879 | BAT *b; |
880 | |
881 | if ((b = BATdescriptor(*bid)) == NULL) { |
882 | throw(MAL, "aggr.count" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
883 | } |
884 | *result = (lng) BATcount(b); |
885 | BBPunfix(b->batCacheid); |
886 | return MAL_SUCCEED; |
887 | } |
888 | |
889 | str |
890 | ALGcount_nil(lng *result, const bat *bid, const bit *ignore_nils) |
891 | { |
892 | BAT *b; |
893 | BUN cnt; |
894 | |
895 | if ((b = BATdescriptor(*bid)) == NULL) { |
896 | throw(MAL, "aggr.count" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
897 | } |
898 | if (*ignore_nils) |
899 | cnt = BATcount_no_nil(b); |
900 | else |
901 | cnt = BATcount(b); |
902 | *result = (lng) cnt; |
903 | BBPunfix(b->batCacheid); |
904 | return MAL_SUCCEED; |
905 | } |
906 | |
907 | str |
908 | ALGcount_no_nil(lng *result, const bat *bid) |
909 | { |
910 | bit ignore_nils = 1; |
911 | |
912 | return ALGcount_nil(result, bid, &ignore_nils); |
913 | } |
914 | |
915 | str |
916 | ALGcountCND_bat(lng *result, const bat *bid, const bat *cnd) |
917 | { |
918 | BAT *b; |
919 | |
920 | if ( *cnd) { |
921 | if ((b = BATdescriptor(*cnd)) == NULL) { |
922 | throw(MAL, "aggr.count" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
923 | } |
924 | *result = (lng) BATcount(b); |
925 | BBPunfix(b->batCacheid); |
926 | return MAL_SUCCEED; |
927 | } |
928 | if ((b = BATdescriptor(*bid)) == NULL) { |
929 | throw(MAL, "aggr.count" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
930 | } |
931 | *result = (lng) BATcount(b); |
932 | BBPunfix(b->batCacheid); |
933 | return MAL_SUCCEED; |
934 | } |
935 | |
936 | str |
937 | ALGcountCND_nil(lng *result, const bat *bid, const bat *cnd, const bit *ignore_nils) |
938 | { |
939 | BAT *b; |
940 | BUN cnt; |
941 | |
942 | if (*ignore_nils){ |
943 | if ((b = BATdescriptor(*bid)) == NULL) { |
944 | throw(MAL, "aggr.count" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
945 | } |
946 | cnt = BATcount_no_nil(b); |
947 | } else{ |
948 | if ( *cnd) { |
949 | if ((b = BATdescriptor(*cnd)) == NULL) { |
950 | throw(MAL, "aggr.count" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
951 | } |
952 | *result = (lng) BATcount(b); |
953 | BBPunfix(b->batCacheid); |
954 | return MAL_SUCCEED; |
955 | } |
956 | if ((b = BATdescriptor(*bid)) == NULL) { |
957 | throw(MAL, "aggr.count" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
958 | } |
959 | cnt = BATcount(b); |
960 | } |
961 | *result = (lng) cnt; |
962 | BBPunfix(b->batCacheid); |
963 | return MAL_SUCCEED; |
964 | } |
965 | |
966 | str |
967 | ALGcountCND_no_nil(lng *result, const bat *bid, const bat *cnd) |
968 | { |
969 | bit ignore_nils = 1; |
970 | |
971 | return ALGcountCND_nil(result, bid, cnd, &ignore_nils); |
972 | } |
973 | |
974 | str |
975 | ALGslice(bat *ret, const bat *bid, const lng *start, const lng *end) |
976 | { |
977 | BAT *b, *bn = NULL; |
978 | |
979 | if ((b = BATdescriptor(*bid)) == NULL) { |
980 | throw(MAL, "algebra.slice" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
981 | } |
982 | if (slice(&bn, b, *start, *end) == GDK_SUCCEED) { |
983 | *ret = bn->batCacheid; |
984 | BBPkeepref(*ret); |
985 | BBPunfix(b->batCacheid); |
986 | return MAL_SUCCEED; |
987 | } |
988 | BBPunfix(b->batCacheid); |
989 | throw(MAL, "algebra.slice" , GDK_EXCEPTION); |
990 | } |
991 | |
992 | str |
993 | ALGslice_int(bat *ret, const bat *bid, const int *start, const int *end) |
994 | { |
995 | lng s = *start; |
996 | lng e = (is_int_nil(*end) ? lng_nil : *end); |
997 | |
998 | return ALGslice(ret, bid, &s, &e); |
999 | } |
1000 | |
1001 | str |
1002 | ALGslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end) |
1003 | { |
1004 | lng s = *start; |
1005 | lng e = *end; |
1006 | |
1007 | return ALGslice(ret, bid, &s, &e); |
1008 | } |
1009 | |
1010 | /* carve out a slice based on the OIDs */ |
1011 | /* beware that BATs may have different OID bases */ |
1012 | str |
1013 | ALGslice_oid(bat *ret, const bat *bid, const oid *start, const oid *end) |
1014 | { |
1015 | lng s = (lng) (is_oid_nil(*start) ? 0 : (lng) *start); |
1016 | lng e = (is_oid_nil(*end) ? lng_nil : (lng) *end); |
1017 | |
1018 | return ALGslice(ret, bid, &s, &e) ; |
1019 | } |
1020 | |
1021 | str |
1022 | ALGsubslice_lng(bat *ret, const bat *bid, const lng *start, const lng *end) |
1023 | { |
1024 | BAT *b, *bn; |
1025 | BUN s, e; |
1026 | |
1027 | if (*start < 0 || *start > (lng) BUN_MAX || |
1028 | (*end < 0 && !is_lng_nil(*end)) || *end >= (lng) BUN_MAX) |
1029 | throw(MAL, "algebra.subslice" , ILLEGAL_ARGUMENT); |
1030 | if ((b = BATdescriptor(*bid)) == NULL) |
1031 | throw(MAL, "algebra.subslice" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1032 | s = (BUN) *start; |
1033 | if (s > BATcount(b)) |
1034 | s = BATcount(b); |
1035 | e = is_lng_nil(*end) ? BATcount(b) : (BUN) *end + 1; |
1036 | if (e > BATcount(b)) |
1037 | e = BATcount(b); |
1038 | if (e < s) |
1039 | e = s; |
1040 | bn = BATdense(0, b->hseqbase + s, e - s); |
1041 | BBPunfix(*bid); |
1042 | if (bn == NULL) |
1043 | throw(MAL, "algebra.subslice" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1044 | *ret = bn->batCacheid; |
1045 | BBPkeepref(*ret); |
1046 | return MAL_SUCCEED; |
1047 | } |
1048 | |
1049 | /* |
1050 | * BUN Get/Fetch |
1051 | */ |
1052 | |
1053 | static str |
1054 | doALGfetch(ptr ret, BAT *b, BUN pos) |
1055 | { |
1056 | BATiter bi = bat_iterator(b); |
1057 | |
1058 | assert(pos <= BUN_MAX); |
1059 | if (ATOMextern(b->ttype)) { |
1060 | ptr _src = BUNtail(bi,pos); |
1061 | size_t _len = ATOMlen(b->ttype, _src); |
1062 | ptr _dst = GDKmalloc(_len); |
1063 | if( _dst == NULL) |
1064 | throw(MAL,"doAlgFetch" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1065 | memcpy(_dst, _src, _len); |
1066 | *(ptr*) ret = _dst; |
1067 | } else { |
1068 | size_t _s = ATOMsize(ATOMtype(b->ttype)); |
1069 | if (b->ttype == TYPE_void) { |
1070 | *(oid*) ret = b->tseqbase; |
1071 | if (!is_oid_nil(b->tseqbase)) |
1072 | *(oid*)ret += pos; |
1073 | } else if (_s == 4) { |
1074 | *(int*) ret = *(int*) Tloc(b, pos); |
1075 | } else if (_s == 1) { |
1076 | *(bte*) ret = *(bte*) Tloc(b, pos); |
1077 | } else if (_s == 2) { |
1078 | *(sht*) ret = *(sht*) Tloc(b, pos); |
1079 | } else if (_s == 8) { |
1080 | *(lng*) ret = *(lng*) Tloc(b, pos); |
1081 | #ifdef HAVE_HGE |
1082 | } else if (_s == 16) { |
1083 | *(hge*) ret = *(hge*) Tloc(b, pos); |
1084 | #endif |
1085 | } else { |
1086 | memcpy(ret, Tloc(b, pos), _s); |
1087 | } |
1088 | } |
1089 | return MAL_SUCCEED; |
1090 | } |
1091 | |
1092 | static str |
1093 | ALGfetch(ptr ret, const bat *bid, const lng *pos) |
1094 | { |
1095 | BAT *b; |
1096 | str msg; |
1097 | |
1098 | if ((b = BATdescriptor(*bid)) == NULL) { |
1099 | throw(MAL, "algebra.fetch" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1100 | } |
1101 | if ((*pos < (lng) 0) || (*pos >= (lng) BUNlast(b))) { |
1102 | BBPunfix(b->batCacheid); |
1103 | throw(MAL, "algebra.fetch" , ILLEGAL_ARGUMENT " Idx out of range\n" ); |
1104 | } |
1105 | msg = doALGfetch(ret, b, (BUN) *pos); |
1106 | BBPunfix(b->batCacheid); |
1107 | return msg; |
1108 | } |
1109 | |
1110 | str |
1111 | ALGfetchoid(ptr ret, const bat *bid, const oid *pos) |
1112 | { |
1113 | lng o = *pos; |
1114 | |
1115 | return ALGfetch(ret, bid, &o); |
1116 | } |
1117 | |
1118 | str |
1119 | ALGexist(bit *ret, const bat *bid, const void *val) |
1120 | { |
1121 | BAT *b; |
1122 | BUN q; |
1123 | |
1124 | if ((b = BATdescriptor(*bid)) == NULL) { |
1125 | throw(MAL, "algebra.exist" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1126 | } |
1127 | derefStr(b, val); |
1128 | q = BUNfnd(b, val); |
1129 | *ret = (q != BUN_NONE); |
1130 | BBPunfix(b->batCacheid); |
1131 | return MAL_SUCCEED; |
1132 | } |
1133 | |
1134 | str |
1135 | ALGfind(oid *ret, const bat *bid, ptr val) |
1136 | { |
1137 | BAT *b; |
1138 | BUN q; |
1139 | str msg= MAL_SUCCEED; |
1140 | |
1141 | if ((b = BATdescriptor(*bid)) == NULL) { |
1142 | throw(MAL, "algebra.find" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1143 | } |
1144 | derefStr(b, val); |
1145 | q = BUNfnd(b, val); |
1146 | |
1147 | if (q == BUN_NONE){ |
1148 | *ret = oid_nil; |
1149 | } else |
1150 | *ret = (oid) q; |
1151 | BBPunfix(b->batCacheid); |
1152 | return msg; |
1153 | } |
1154 | |
1155 | |
1156 | str |
1157 | ALGprojecttail(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
1158 | { |
1159 | bat *ret = getArgReference_bat(stk, pci, 0); |
1160 | bat bid = * getArgReference_bat(stk, pci, 1); |
1161 | const ValRecord *v = &stk->stk[getArg(pci, 2)]; |
1162 | BAT *b, *bn; |
1163 | |
1164 | (void) cntxt; |
1165 | (void) mb; |
1166 | if( isaBatType(getArgType(mb,pci,2)) ) |
1167 | throw(MAL,"algebra.project" ,"Scalar value expected" ); |
1168 | if ((b = BATdescriptor(bid)) == NULL) |
1169 | throw(MAL, "algebra.project" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1170 | bn = BATconstant(b->hseqbase, v->vtype, VALptr(v), BATcount(b), TRANSIENT); |
1171 | BBPunfix(b->batCacheid); |
1172 | if (bn == NULL) { |
1173 | *ret = bat_nil; |
1174 | throw(MAL, "algebra.project" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1175 | } |
1176 | *ret= bn->batCacheid; |
1177 | BBPkeepref(bn->batCacheid); |
1178 | return MAL_SUCCEED; |
1179 | } |
1180 | |
1181 | |
1182 | str ALGreuse(bat *ret, const bat *bid) |
1183 | { |
1184 | BAT *b,*bn; |
1185 | if ((b = BATdescriptor(*bid)) == NULL) |
1186 | throw(MAL, "algebra.reuse" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1187 | |
1188 | if( !b->batTransient || b->batRestricted != BAT_WRITE){ |
1189 | if( ATOMvarsized(b->ttype) ){ |
1190 | bn= BATwcopy(b); |
1191 | if (bn == NULL) { |
1192 | BBPunfix(b->batCacheid); |
1193 | throw(MAL, "algebra.reuse" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1194 | } |
1195 | } else { |
1196 | bn = COLnew(b->hseqbase, b->ttype, BATcount(b), TRANSIENT); |
1197 | if (bn == NULL) { |
1198 | BBPunfix(b->batCacheid); |
1199 | throw(MAL, "algebra.reuse" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1200 | } |
1201 | BATsetcount(bn,BATcount(b)); |
1202 | bn->tsorted = false; |
1203 | bn->trevsorted = false; |
1204 | BATkey(bn, false); |
1205 | } |
1206 | BBPkeepref(*ret= bn->batCacheid); |
1207 | BBPunfix(b->batCacheid); |
1208 | } else |
1209 | BBPkeepref(*ret = *bid); |
1210 | return MAL_SUCCEED; |
1211 | } |
1212 | |
1213 | /* |
1214 | * BAT standard deviation |
1215 | */ |
1216 | str |
1217 | ALGstdev(dbl *res, const bat *bid) |
1218 | { |
1219 | BAT *b; |
1220 | dbl stdev; |
1221 | |
1222 | if ((b = BATdescriptor(*bid)) == NULL) |
1223 | throw(MAL, "aggr.stdev" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1224 | stdev = BATcalcstdev_sample(NULL, b); |
1225 | BBPunfix(b->batCacheid); |
1226 | if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0]) |
1227 | throw(MAL, "aggr.stdev" , SEMANTIC_TYPE_MISMATCH); |
1228 | *res = stdev; |
1229 | return MAL_SUCCEED; |
1230 | } |
1231 | |
1232 | str |
1233 | ALGstdevp(dbl *res, const bat *bid) |
1234 | { |
1235 | BAT *b; |
1236 | dbl stdev; |
1237 | |
1238 | if ((b = BATdescriptor(*bid)) == NULL) |
1239 | throw(MAL, "aggr.stdevp" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1240 | stdev = BATcalcstdev_population(NULL, b); |
1241 | BBPunfix(b->batCacheid); |
1242 | if (is_dbl_nil(stdev) && GDKerrbuf && GDKerrbuf[0]) |
1243 | throw(MAL, "aggr.stdevp" , SEMANTIC_TYPE_MISMATCH); |
1244 | *res = stdev; |
1245 | return MAL_SUCCEED; |
1246 | } |
1247 | |
1248 | /* |
1249 | * BAT variance |
1250 | */ |
1251 | str |
1252 | ALGvariance(dbl *res, const bat *bid) |
1253 | { |
1254 | BAT *b; |
1255 | dbl variance; |
1256 | |
1257 | if ((b = BATdescriptor(*bid)) == NULL) |
1258 | throw(MAL, "aggr.variance" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1259 | variance = BATcalcvariance_sample(NULL, b); |
1260 | BBPunfix(b->batCacheid); |
1261 | if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0]) |
1262 | throw(MAL, "aggr.variance" , SEMANTIC_TYPE_MISMATCH); |
1263 | *res = variance; |
1264 | return MAL_SUCCEED; |
1265 | } |
1266 | |
1267 | str |
1268 | ALGvariancep(dbl *res, const bat *bid) |
1269 | { |
1270 | BAT *b; |
1271 | dbl variance; |
1272 | |
1273 | if ((b = BATdescriptor(*bid)) == NULL) |
1274 | throw(MAL, "aggr.variancep" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1275 | variance = BATcalcvariance_population(NULL, b); |
1276 | BBPunfix(b->batCacheid); |
1277 | if (is_dbl_nil(variance) && GDKerrbuf && GDKerrbuf[0]) |
1278 | throw(MAL, "aggr.variancep" , SEMANTIC_TYPE_MISMATCH); |
1279 | *res = variance; |
1280 | return MAL_SUCCEED; |
1281 | } |
1282 | |