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