| 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 | |