LCOV - code coverage report
Current view: top level - monetdb5/modules/kernel - bat5.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 233 631 36.9 %
Date: 2021-10-13 02:24:04 Functions: 26 49 53.1 %

          Line data    Source code
       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 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * Peter Boncz, M.L. Kersten
      11             :  * Binary Association Tables
      12             :  * This module contains the commands and patterns to manage Binary
      13             :  * Association Tables (BATs). The relational operations you can execute
      14             :  * on BATs have the form of a neat algebra, described in algebra.c
      15             :  *
      16             :  * But a database system needs more that just this algebra, since often it
      17             :  * is crucial to do table-updates (this would not be permitted in a strict
      18             :  * algebra).
      19             :  *
      20             :  * All commands needed for BAT updates, property management, basic I/O,
      21             :  * persistence, and storage options can be found in this module.
      22             :  *
      23             :  * All parameters to the modules are passed by reference.
      24             :  * In particular, this means that string values are passed to the module
      25             :  * layer as (str *)
      26             :  * and we have to de-reference them before entering the gdk library.
      27             :  * (Actual a design error in gdk to differentiate passing int/str)
      28             :  * This calls for knowledge on the underlying BAT types`s
      29             :  */
      30             : 
      31             : #include "monetdb_config.h"
      32             : #include "bat5.h"
      33             : #include "mal_exception.h"
      34             : #include "mal_debugger.h"
      35             : 
      36             : /*
      37             :  * The remainder contains the wrapper code over the mserver version 4
      38             :  * InformationFunctions
      39             :  * In most cases we pass a BAT identifier, which should be unified
      40             :  * with a BAT descriptor. Upon failure we can simply abort the function.
      41             :  *
      42             :  * The logical head type :oid is mapped to a TYPE_void
      43             :  * with sequenceBase. It represents the old fashioned :vid
      44             :  */
      45             : 
      46             : 
      47             : #define derefStr(b, v)                                                  \
      48             :         do {                                                                            \
      49             :                 int _tpe= ATOMstorage((b)->ttype);           \
      50             :                 if (_tpe >= TYPE_str) {                                      \
      51             :                         if ((v) == 0 || *(str*) (v) == 0)       \
      52             :                                 (v) = (str) str_nil;                    \
      53             :                         else                                                            \
      54             :                                 (v) = *(str *) (v);                             \
      55             :                 }                                                                               \
      56             :         } while (0)
      57             : 
      58             : str
      59      187979 : BKCnewBAT(bat *res, const int *tt, const BUN *cap, role_t role)
      60             : {
      61             :         BAT *bn;
      62             : 
      63      187979 :         bn = COLnew(0, *tt, *cap, role);
      64      187930 :         if (bn == NULL)
      65           0 :                 throw(MAL, "bat.new", GDK_EXCEPTION);
      66      187930 :         *res = bn->batCacheid;
      67      187930 :         BATsettrivprop(bn);
      68      187975 :         BBPretain(bn->batCacheid);
      69      187926 :         BBPunfix(bn->batCacheid);
      70      187923 :         return MAL_SUCCEED;
      71             : }
      72             : 
      73             : static str
      74           0 : BKCattach(bat *ret, const int *tt, const char * const *heapfile)
      75             : {
      76             :         BAT *bn;
      77             : 
      78           0 :         bn = BATattach(*tt, *heapfile, TRANSIENT);
      79           0 :         if (bn == NULL)
      80           0 :                 throw(MAL, "bat.attach", GDK_EXCEPTION);
      81           0 :         if( !bn->batTransient)
      82           0 :                 BATmsync(bn);
      83           0 :         *ret = bn->batCacheid;
      84           0 :         BBPkeepref(*ret);
      85           0 :         return MAL_SUCCEED;
      86             : }
      87             : 
      88             : static str
      89           0 : BKCdensebat(bat *ret, const lng *size)
      90             : {
      91             :         BAT *bn;
      92           0 :         lng sz = *size;
      93             : 
      94             :         if (sz < 0)
      95             :                 sz = 0;
      96             :         if (sz > (lng) BUN_MAX)
      97             :                 sz = (lng) BUN_MAX;
      98           0 :         bn = BATdense(0, 0, (BUN) sz);
      99           0 :         if (bn == NULL)
     100           0 :                 throw(MAL, "bat.densebat", GDK_EXCEPTION);
     101           0 :         *ret = bn->batCacheid;
     102           0 :         BBPkeepref(*ret);
     103           0 :         return MAL_SUCCEED;
     104             : }
     105             : 
     106             : str
     107       77991 : BKCmirror(bat *ret, const bat *bid)
     108             : {
     109             :         BAT *b, *bn;
     110             : 
     111       77991 :         *ret = 0;
     112       77991 :         if (!(b = BBPquickdesc(*bid)))
     113           0 :                 throw(MAL, "bat.mirror", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     114       77990 :         if (!(bn = BATdense(b->hseqbase, b->hseqbase, BATcount(b))))
     115           0 :                 throw(MAL, "bat.mirror", GDK_EXCEPTION);
     116       77990 :         BBPkeepref(*ret = bn->batCacheid);
     117       77987 :         return MAL_SUCCEED;
     118             : }
     119             : 
     120             : static str
     121           4 : BKCdelete(bat *r, const bat *bid, const oid *h)
     122             : {
     123             :         BAT *b;
     124             : 
     125           4 :         if ((b = BATdescriptor(*bid)) == NULL)
     126           0 :                 throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     127           4 :         if (BUNdelete(b, *h) != GDK_SUCCEED) {
     128           0 :                 BBPunfix(b->batCacheid);
     129           0 :                 throw(MAL, "bat.delete", GDK_EXCEPTION);
     130             :         }
     131           4 :         *r = b->batCacheid;
     132           4 :         BATsettrivprop(b);
     133           4 :         BBPretain(b->batCacheid);
     134           4 :         BBPunfix(b->batCacheid);
     135           4 :         return MAL_SUCCEED;
     136             : }
     137             : 
     138             : static str
     139           4 : BKCdelete_multi(bat *r, const bat *bid, const bat *sid)
     140             : {
     141             :         BAT *b, *s;
     142             :         gdk_return ret;
     143             : 
     144           4 :         if ((b = BATdescriptor(*bid)) == NULL)
     145           0 :                 throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     146           4 :         if ((s = BATdescriptor(*sid)) == NULL) {
     147           0 :                 BBPunfix(b->batCacheid);
     148           0 :                 throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     149             :         }
     150           4 :         ret = BATdel(b, s);
     151           4 :         BBPunfix(s->batCacheid);
     152           4 :         if (ret != GDK_SUCCEED) {
     153           0 :                 BBPunfix(b->batCacheid);
     154           0 :                 throw(MAL, "bat.delete", GDK_EXCEPTION);
     155             :         }
     156           4 :         *r = b->batCacheid;
     157           4 :         BATsettrivprop(b);
     158           4 :         BBPretain(b->batCacheid);
     159           4 :         BBPunfix(b->batCacheid);
     160           4 :         return MAL_SUCCEED;
     161             : }
     162             : 
     163             : static str
     164           7 : BKCdelete_all(bat *r, const bat *bid)
     165             : {
     166             :         BAT *b;
     167             : 
     168           7 :         if ((b = BATdescriptor(*bid)) == NULL)
     169           0 :                 throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     170           7 :         if (BATclear(b, false) != GDK_SUCCEED) {
     171           0 :                 BBPunfix(b->batCacheid);
     172           0 :                 throw(MAL, "bat.delete", GDK_EXCEPTION);
     173             :         }
     174           7 :         if( !b->batTransient)
     175           0 :                 BATmsync(b);
     176           7 :         *r = b->batCacheid;
     177           7 :         BATsettrivprop(b);
     178           7 :         BBPretain(b->batCacheid);
     179           7 :         BBPunfix(b->batCacheid);
     180           7 :         return MAL_SUCCEED;
     181             : }
     182             : 
     183             : static str
     184      334918 : BKCappend_cand_force_wrap(bat *r, const bat *bid, const bat *uid, const bat *sid, const bit *force)
     185             : {
     186             :         BAT *b, *u, *s = NULL;
     187             :         gdk_return ret;
     188             : 
     189      334918 :         if ((b = BATdescriptor(*bid)) == NULL)
     190           0 :                 throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     191      334898 :         if (isVIEW(b)) {
     192       32240 :                 BAT *bn = COLcopy(b, b->ttype, true, TRANSIENT);
     193       32241 :                 restrict_t mode = (restrict_t) b->batRestricted;
     194       32241 :                 BBPunfix(b->batCacheid);
     195       32241 :                 if (bn == NULL || (b = BATsetaccess(bn, mode)) == NULL)
     196           0 :                         throw(MAL, "bat.append", GDK_EXCEPTION);
     197             :         }
     198      334900 :         if ((u = BATdescriptor(*uid)) == NULL) {
     199           0 :                 BBPunfix(b->batCacheid);
     200           0 :                 throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     201             :         }
     202      334873 :         if (mask_cand(u)) {
     203             :                 BAT *ou = u;
     204           0 :                 u = BATunmask(u);
     205           0 :                 BBPunfix(ou->batCacheid);
     206           0 :                 if (!u) {
     207           0 :                         BBPunfix(b->batCacheid);
     208           0 :                         throw(MAL, "bat.append", GDK_EXCEPTION);
     209             :                 }
     210             :         }
     211      334873 :         if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     212           0 :                 BBPunfix(b->batCacheid);
     213           0 :                 BBPunfix(u->batCacheid);
     214           0 :                 throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     215             :         }
     216      334908 :         ret = BATappend(b, u, s, force ? *force : false);
     217      334904 :         BBPunfix(u->batCacheid);
     218      334889 :         if (s)
     219           0 :                 BBPunfix(s->batCacheid);
     220      334889 :         if (ret != GDK_SUCCEED) {
     221           0 :                 BBPunfix(b->batCacheid);
     222           0 :                 throw(MAL, "bat.append", GDK_EXCEPTION);
     223             :         }
     224      334889 :         if( !b->batTransient)
     225           0 :                 BATmsync(b);
     226      334889 :         *r = b->batCacheid;
     227      334889 :         BATsettrivprop(b);
     228      334896 :         BBPretain(b->batCacheid);
     229      334895 :         BBPunfix(b->batCacheid);
     230      334861 :         return MAL_SUCCEED;
     231             : }
     232             : 
     233             : static str
     234           0 : BKCappend_cand_wrap(bat *r, const bat *bid, const bat *uid, const bat *sid)
     235             : {
     236           0 :         return BKCappend_cand_force_wrap(r, bid, uid, sid, NULL);
     237             : }
     238             : 
     239             : static str
     240          35 : BKCappend_wrap(bat *r, const bat *bid, const bat *uid)
     241             : {
     242          35 :         return BKCappend_cand_force_wrap(r, bid, uid, NULL, NULL);
     243             : }
     244             : 
     245             : static str
     246      334884 : BKCappend_force_wrap(bat *r, const bat *bid, const bat *uid, const bit *force)
     247             : {
     248      334884 :         return BKCappend_cand_force_wrap(r, bid, uid, NULL, force);
     249             : }
     250             : 
     251             : static str
     252    18222559 : BKCappend_val_force_wrap(bat *r, const bat *bid, const void *u, const bit *force)
     253             : {
     254             :         BAT *b;
     255             : 
     256    18222559 :         if ((b = BATdescriptor(*bid)) == NULL)
     257           0 :                 throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     258    18222559 :         if (isVIEW(b)) {
     259         711 :                 BAT *bn = COLcopy(b, b->ttype, true, TRANSIENT);
     260         711 :                 restrict_t mode = (restrict_t) b->batRestricted;
     261         711 :                 BBPunfix(b->batCacheid);
     262         711 :                 if (bn == NULL || (b = BATsetaccess(bn, mode)) == NULL)
     263           0 :                         throw(MAL, "bat.append", GDK_EXCEPTION);
     264             :         }
     265    18222559 :         derefStr(b, u);
     266    36443062 :         if (BUNappend(b, u, force ? *force : false) != GDK_SUCCEED) {
     267           0 :                 BBPunfix(b->batCacheid);
     268           0 :                 throw(MAL, "bat.append", GDK_EXCEPTION);
     269             :         }
     270    18222559 :         *r = b->batCacheid;
     271    18222559 :         BATsettrivprop(b);
     272    18222558 :         BBPretain(b->batCacheid);
     273    18222558 :         BBPunfix(b->batCacheid);
     274    18222559 :         return MAL_SUCCEED;
     275             : }
     276             : 
     277             : static str
     278    18220503 : BKCappend_val_wrap(bat *r, const bat *bid, const void *u)
     279             : {
     280    18220503 :         return BKCappend_val_force_wrap(r, bid, u, NULL);
     281             : }
     282             : 
     283             : static str
     284         103 : BKCbun_inplace(bat *r, const bat *bid, const oid *id, const void *t)
     285             : {
     286             :         BAT *b;
     287             : 
     288         103 :         if ((b = BATdescriptor(*bid)) == NULL)
     289           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     290         103 :         derefStr(b, t);
     291         103 :         if (void_inplace(b, *id, t, false) != GDK_SUCCEED) {
     292           0 :                 BBPunfix(b->batCacheid);
     293           0 :                 throw(MAL, "bat.inplace", GDK_EXCEPTION);
     294             :         }
     295         103 :         *r = b->batCacheid;
     296         103 :         BATsettrivprop(b);
     297         103 :         BBPretain(b->batCacheid);
     298         103 :         BBPunfix(b->batCacheid);
     299         103 :         return MAL_SUCCEED;
     300             : }
     301             : 
     302             : static str
     303           0 : BKCbun_inplace_force(bat *r, const bat *bid, const oid *id, const void *t, const bit *force)
     304             : {
     305             :         BAT *b;
     306             : 
     307           0 :         if ((b = BATdescriptor(*bid)) == NULL)
     308           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     309           0 :         derefStr(b, t);
     310           0 :         if (void_inplace(b, *id, t, *force) != GDK_SUCCEED) {
     311           0 :                 BBPunfix(b->batCacheid);
     312           0 :                 throw(MAL, "bat.inplace", GDK_EXCEPTION);
     313             :         }
     314           0 :         *r = b->batCacheid;
     315           0 :         BATsettrivprop(b);
     316           0 :         BBPretain(b->batCacheid);
     317           0 :         BBPunfix(b->batCacheid);
     318           0 :         return MAL_SUCCEED;
     319             : }
     320             : 
     321             : 
     322             : static str
     323       67615 : BKCbat_inplace_force(bat *r, const bat *bid, const bat *rid, const bat *uid, const bit *force)
     324             : {
     325             :         BAT *b, *p, *u;
     326             : 
     327       67615 :         if ((b = BATdescriptor(*bid)) == NULL)
     328           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     329       67612 :         if ((p = BATdescriptor(*rid)) == NULL) {
     330           0 :                 BBPunfix(b->batCacheid);
     331           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     332             :         }
     333       67602 :         if ((u = BATdescriptor(*uid)) == NULL) {
     334           0 :                 BBPunfix(b->batCacheid);
     335           0 :                 BBPunfix(p->batCacheid);
     336           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     337             :         }
     338       67605 :         if (BATreplace(b, p, u, *force) != GDK_SUCCEED) {
     339           0 :                 BBPunfix(b->batCacheid);
     340           0 :                 BBPunfix(p->batCacheid);
     341           0 :                 BBPunfix(u->batCacheid);
     342           0 :                 throw(MAL, "bat.inplace", GDK_EXCEPTION);
     343             :         }
     344       67529 :         *r = b->batCacheid;
     345       67529 :         BATsettrivprop(b);
     346       67494 :         BBPretain(b->batCacheid);
     347       67584 :         BBPunfix(b->batCacheid);
     348       67594 :         BBPunfix(p->batCacheid);
     349       67587 :         BBPunfix(u->batCacheid);
     350       67586 :         return MAL_SUCCEED;
     351             : }
     352             : 
     353             : static str
     354           2 : BKCbat_inplace(bat *r, const bat *bid, const bat *rid, const bat *uid)
     355             : {
     356           2 :         bit F = FALSE;
     357             : 
     358           2 :         return BKCbat_inplace_force(r, bid, rid, uid, &F);
     359             : }
     360             : 
     361             : /*end of SQL enhancement */
     362             : 
     363             : static str
     364           0 : BKCgetCapacity(lng *res, const bat *bid)
     365             : {
     366           0 :         *res = lng_nil;
     367           0 :         BAT *b = BBPquickdesc(*bid);
     368             : 
     369           0 :         if (b == NULL)
     370           0 :                 throw(MAL, "bat.getCapacity", ILLEGAL_ARGUMENT);
     371           0 :         *res = (lng) BATcapacity(b);
     372           0 :         return MAL_SUCCEED;
     373             : }
     374             : 
     375             : static str
     376           0 : BKCgetColumnType(str *res, const bat *bid)
     377             : {
     378             :         const char *ret = str_nil;
     379           0 :         BAT *b = BBPquickdesc(*bid);
     380             : 
     381           0 :         if (b == NULL)
     382           0 :                 throw(MAL, "bat.getColumnType", ILLEGAL_ARGUMENT);
     383           0 :         ret = *bid < 0 ? ATOMname(TYPE_void) : ATOMname(b->ttype);
     384           0 :         *res = GDKstrdup(ret);
     385           0 :         if(*res == NULL)
     386           0 :                 throw(MAL,"bat.getColumnType", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     387             :         return MAL_SUCCEED;
     388             : }
     389             : 
     390             : static str
     391           0 : BKCgetRole(str *res, const bat *bid)
     392             : {
     393             :         BAT *b;
     394             : 
     395           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     396           0 :                 throw(MAL, "bat.getRole", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     397             :         }
     398           0 :         *res = GDKstrdup(b->tident);
     399           0 :         BBPunfix(b->batCacheid);
     400           0 :         if(*res == NULL)
     401           0 :                 throw(MAL,"bat.getRole", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     402             :         return MAL_SUCCEED;
     403             : }
     404             : 
     405             : static str
     406           0 : BKCisSorted(bit *res, const bat *bid)
     407             : {
     408             :         BAT *b;
     409             : 
     410           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     411           0 :                 throw(MAL, "bat.isSorted", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     412             :         }
     413           0 :         *res = BATordered(b);
     414           0 :         BBPunfix(b->batCacheid);
     415           0 :         return MAL_SUCCEED;
     416             : }
     417             : 
     418             : static str
     419           0 : BKCisSortedReverse(bit *res, const bat *bid)
     420             : {
     421             :         BAT *b;
     422             : 
     423           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     424           0 :                 throw(MAL, "bat.isSorted", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     425             :         }
     426           0 :         *res = BATordered_rev(b);
     427           0 :         BBPunfix(b->batCacheid);
     428           0 :         return MAL_SUCCEED;
     429             : }
     430             : 
     431             : /*
     432             :  * We must take care of the special case of a nil column (TYPE_void,seqbase=nil)
     433             :  * such nil columns never set tkey
     434             :  * a nil column of a BAT with <= 1 entries does not contain doubles => return TRUE.
     435             :  */
     436             : 
     437             : static str
     438           0 : BKCgetKey(bit *ret, const bat *bid)
     439             : {
     440             :         BAT *b;
     441             : 
     442           0 :         if ((b = BATdescriptor(*bid)) == NULL)
     443           0 :                 throw(MAL, "bat.setPersistence", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     444           0 :         *ret = b->tkey;
     445           0 :         BBPunfix(b->batCacheid);
     446           0 :         return MAL_SUCCEED;
     447             : }
     448             : 
     449             : static str
     450          11 : BKCpersists(void *r, const bat *bid, const bit *flg)
     451             : {
     452             :         BAT *b;
     453             : 
     454             :         (void) r;
     455          11 :         if ((b = BATdescriptor(*bid)) == NULL) {
     456           0 :                 throw(MAL, "bat.setPersistence", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     457             :         }
     458          11 :         if (BATmode(b, (*flg != TRUE)) != GDK_SUCCEED) {
     459           0 :                 BBPunfix(b->batCacheid);
     460           0 :                 throw(MAL, "bat.setPersistence", ILLEGAL_ARGUMENT);
     461             :         }
     462          11 :         BBPunfix(b->batCacheid);
     463          11 :         return MAL_SUCCEED;
     464             : }
     465             : 
     466             : str
     467          10 : BKCsetPersistent(void *r, const bat *bid)
     468             : {
     469          10 :         bit flag= TRUE;
     470          10 :         return BKCpersists(r, bid, &flag);
     471             : }
     472             : 
     473             : static str
     474           2 : BKCisPersistent(bit *res, const bat *bid)
     475             : {
     476             :         BAT *b;
     477             : 
     478           2 :         if ((b = BATdescriptor(*bid)) == NULL) {
     479           0 :                 throw(MAL, "bat.setPersistence", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     480             :         }
     481           2 :         *res = !b->batTransient;
     482           2 :         BBPunfix(b->batCacheid);
     483           2 :         return MAL_SUCCEED;
     484             : }
     485             : 
     486             : static str
     487           1 : BKCsetTransient(void *r, const bat *bid)
     488             : {
     489           1 :         bit flag = FALSE;
     490           1 :         return BKCpersists(r, bid, &flag);
     491             : }
     492             : 
     493             : static str
     494           2 : BKCisTransient(bit *res, const bat *bid)
     495             : {
     496             :         BAT *b;
     497             : 
     498           2 :         if ((b = BATdescriptor(*bid)) == NULL) {
     499           0 :                 throw(MAL, "bat.setTransient", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     500             :         }
     501           2 :         *res = b->batTransient;
     502           2 :         BBPunfix(b->batCacheid);
     503           2 :         return MAL_SUCCEED;
     504             : }
     505             : 
     506             : static str
     507          10 : BKCsetAccess(bat *res, const bat *bid, const char * const *param)
     508             : {
     509             :         BAT *b;
     510             :         restrict_t m;
     511             : 
     512          10 :         if ((b = BATdescriptor(*bid)) == NULL)
     513           0 :                 throw(MAL, "bat.setAccess", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     514          10 :         switch (*param[0]) {
     515             :         case 'r':
     516             :                 m = BAT_READ;
     517             :                 break;
     518           0 :         case 'a':
     519             :                 m = BAT_APPEND;
     520           0 :                 break;
     521           7 :         case 'w':
     522             :                 m = BAT_WRITE;
     523           7 :                 break;
     524           0 :         default:
     525           0 :                 *res = 0;
     526           0 :                 BBPunfix(b->batCacheid);
     527           0 :                 throw(MAL, "bat.setAccess", ILLEGAL_ARGUMENT " Got %c" " expected 'r','a', or 'w'", *param[0]);
     528             :         }
     529          10 :         if ((b = BATsetaccess(b, m)) == NULL)
     530           0 :                 throw(MAL, "bat.setAccess", OPERATION_FAILED);
     531          10 :         *res = b->batCacheid;
     532          10 :         BATsettrivprop(b);
     533          10 :         BBPretain(b->batCacheid);
     534          10 :         BBPunfix(b->batCacheid);
     535          10 :         return MAL_SUCCEED;
     536             : }
     537             : 
     538             : static str
     539           0 : BKCgetAccess(str *res, const bat *bid)
     540             : {
     541             :         BAT *b;
     542             : 
     543           0 :         if ((b = BATdescriptor(*bid)) == NULL)
     544           0 :                 throw(MAL, "bat.getAccess", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     545           0 :         switch (BATgetaccess(b)) {
     546           0 :         case BAT_READ:
     547           0 :                 *res = GDKstrdup("read");
     548           0 :                 break;
     549           0 :         case BAT_APPEND:
     550           0 :                 *res = GDKstrdup("append");
     551           0 :                 break;
     552           0 :         case BAT_WRITE:
     553           0 :                 *res = GDKstrdup("write");
     554           0 :                 break;
     555             :         }
     556           0 :         BBPunfix(b->batCacheid);
     557           0 :         if(*res == NULL)
     558           0 :                 throw(MAL,"bat.getAccess", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     559             :         return MAL_SUCCEED;
     560             : }
     561             : 
     562             : /*
     563             :  * Property management
     564             :  * All property operators should ensure exclusive access to the BAT
     565             :  * descriptor.
     566             :  * Where necessary use the primary view to access the properties
     567             :  */
     568             : static str
     569           0 : BKCinfo(bat *ret1, bat *ret2, const bat *bid)
     570             : {
     571             :         BAT *bv, *bk;
     572             :         str msg;
     573             : 
     574           0 :         if ((msg = BATinfo(&bk, &bv, *bid)) != NULL)
     575             :                 return msg;
     576           0 :         BBPkeepref(*ret1 = bk->batCacheid);
     577           0 :         BBPkeepref(*ret2 = bv->batCacheid);
     578           0 :         return MAL_SUCCEED;
     579             : }
     580             : 
     581             : // get the actual size of all constituents, also for views
     582             : #define ROUND_UP(x,y) ((y)*(((x)+(y)-1)/(y)))
     583             : 
     584             : static str
     585           0 : BKCgetSize(lng *tot, const bat *bid){
     586             :         BAT *b;
     587             :         lng size = 0;
     588           0 :         lng blksize = (lng) MT_pagesize();
     589           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     590           0 :                 throw(MAL, "bat.getDiskSize", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     591             :         }
     592             : 
     593             :         size = sizeof (bat);
     594             : 
     595           0 :         MT_lock_set(&b->theaplock);
     596           0 :         if ( !isVIEW(b)) {
     597           0 :                 BUN cnt = BATcapacity(b);
     598           0 :                 size += ROUND_UP(b->theap->free, blksize);
     599           0 :                 if (b->tvheap)
     600           0 :                         size += ROUND_UP(b->tvheap->free, blksize);
     601           0 :                 MT_lock_unset(&b->theaplock);
     602             : 
     603           0 :                 if (b->thash)
     604           0 :                         size += ROUND_UP(sizeof(BUN) * cnt, blksize);
     605           0 :                 size += IMPSimprintsize(b);
     606             :         } else {
     607           0 :                 MT_lock_unset(&b->theaplock);
     608             :         }
     609           0 :         *tot = size;
     610           0 :         BBPunfix(*bid);
     611           0 :         return MAL_SUCCEED;
     612             : }
     613             : 
     614             : static str
     615           3 : BKCgetVHeapSize(lng *tot, const bat *bid){
     616             :         BAT *b;
     617             :         lng size = 0;
     618           3 :         if ((b = BATdescriptor(*bid)) == NULL) {
     619           0 :                 throw(MAL, "bat.getVHeapSize", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     620             :         }
     621           3 :         if (ATOMvarsized(b->ttype)) {
     622           3 :                 MT_lock_set(&b->theaplock);
     623           3 :                 if (b->tvheap)
     624           3 :                         size += b->tvheap->size;
     625           3 :                 MT_lock_unset(&b->theaplock);
     626             :         }
     627             : 
     628           3 :         *tot = size;
     629           3 :         BBPunfix(*bid);
     630           3 :         return MAL_SUCCEED;
     631             : }
     632             : 
     633             : /*
     634             :  * Synced BATs
     635             :  */
     636             : static str
     637           0 : BKCisSynced(bit *ret, const bat *bid1, const bat *bid2)
     638             : {
     639             :         BAT *b1, *b2;
     640             : 
     641           0 :         if ((b1 = BATdescriptor(*bid1)) == NULL) {
     642           0 :                 throw(MAL, "bat.isSynced", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     643             :         }
     644           0 :         if ((b2 = BATdescriptor(*bid2)) == NULL) {
     645           0 :                 BBPunfix(b1->batCacheid);
     646           0 :                 throw(MAL, "bat.isSynced", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     647             :         }
     648           0 :         *ret = ALIGNsynced(b1, b2) != 0;
     649           0 :         BBPunfix(b1->batCacheid);
     650           0 :         BBPunfix(b2->batCacheid);
     651           0 :         return MAL_SUCCEED;
     652             : }
     653             : 
     654             : /*
     655             :  * Role Management
     656             :  */
     657             : static str
     658           3 : BKCsetColumn(void *r, const bat *bid, const char * const *tname)
     659             : {
     660             :         BAT *b;
     661             : 
     662             :         (void) r;
     663           3 :         if ((b = BATdescriptor(*bid)) == NULL) {
     664           0 :                 throw(MAL, "bat.setColumn", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     665             :         }
     666           3 :         if (tname == 0 || *tname == 0 || **tname == 0){
     667           0 :                 BBPunfix(b->batCacheid);
     668           0 :                 throw(MAL, "bat.setColumn", ILLEGAL_ARGUMENT " Column name missing");
     669             :         }
     670           3 :         if (BATroles(b, *tname) != GDK_SUCCEED) {
     671           0 :                 BBPunfix(b->batCacheid);
     672           0 :                 throw(MAL, "bat.setColumn", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     673             :         }
     674           3 :         BBPunfix(b->batCacheid);
     675           3 :         return MAL_SUCCEED;
     676             : }
     677             : 
     678             : str
     679          18 : BKCsetName(void *r, const bat *bid, const char * const *s)
     680             : {
     681             :         BAT *b;
     682             :         int ret;
     683             :         int c;
     684          18 :         const char *t = *s;
     685             : 
     686             :         (void) r;
     687          18 :         if ((b = BATdescriptor(*bid)) == NULL)
     688           0 :                 throw(MAL, "bat.setName", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     689             : 
     690         135 :         for ( ; (c = *t) != 0; t++)
     691         117 :                 if (c != '_' && !GDKisalnum(c)) {
     692           0 :                         BBPunfix(b->batCacheid);
     693           0 :                         throw(MAL, "bat.setName", ILLEGAL_ARGUMENT ": identifier expected: %s", *s);
     694             :                 }
     695             : 
     696          18 :         t = *s;
     697          18 :         ret = BBPrename(b->batCacheid, t);
     698          18 :         BBPunfix(b->batCacheid);
     699          18 :         switch (ret) {
     700           0 :         case BBPRENAME_ILLEGAL:
     701           0 :                 GDKclrerr();
     702           0 :                 throw(MAL, "bat.setName", ILLEGAL_ARGUMENT ": illegal temporary name: '%s'", t);
     703           0 :         case BBPRENAME_LONG:
     704           0 :                 GDKclrerr();
     705           0 :                 throw(MAL, "bat.setName", ILLEGAL_ARGUMENT ": name too long: '%s'", t);
     706           0 :         case BBPRENAME_MEMORY:
     707           0 :                 GDKclrerr();
     708           0 :                 throw(MAL, "bat.setName", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     709           1 :         case BBPRENAME_ALREADY:
     710           1 :                 GDKclrerr();
     711             :                 /* fall through */
     712             :         case 0:
     713             :                 break;
     714             :         }
     715             :         return MAL_SUCCEED;
     716             : }
     717             : 
     718             : static str
     719           0 : BKCgetBBPname(str *ret, const bat *bid)
     720             : {
     721             :         BAT *b;
     722             : 
     723           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     724           0 :                 throw(MAL, "bat.getName", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     725             :         }
     726           0 :         *ret = GDKstrdup(BBP_logical(b->batCacheid));
     727           0 :         BBPunfix(b->batCacheid);
     728           0 :         return *ret ? MAL_SUCCEED : createException(MAL, "bat.getName", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     729             : }
     730             : 
     731             : static str
     732           0 : BKCsave(bit *res, const char * const *input)
     733             : {
     734           0 :         bat bid = BBPindex(*input);
     735             :         BAT *b;
     736             : 
     737           0 :         *res = FALSE;
     738           0 :         if (!is_bat_nil(bid)) {
     739           0 :                 if (BBPfix(bid) > 0) {
     740           0 :                         b = BBP_cache(bid);
     741           0 :                         if (b && BATdirty(b)) {
     742           0 :                                 if (BBPsave(b) == GDK_SUCCEED)
     743           0 :                                         *res = TRUE;
     744             :                         }
     745           0 :                         BBPunfix(bid);
     746           0 :                         return MAL_SUCCEED;
     747             :                 }
     748           0 :                 throw(MAL, "bat.save", "fix failed");
     749             :         }
     750             :         return MAL_SUCCEED;
     751             : }
     752             : 
     753             : static str
     754           0 : BKCsave2(void *r, const bat *bid)
     755             : {
     756             :         BAT *b;
     757             : 
     758             :         (void) r;
     759           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     760           0 :                 throw(MAL, "bat.save", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     761             :         }
     762           0 :         if ( !b->batTransient){
     763           0 :                 BBPunfix(b->batCacheid);
     764           0 :                 throw(MAL, "bat.save", "Only save transient columns.");
     765             :         }
     766             : 
     767           0 :         if (b && BATdirty(b))
     768           0 :                 BBPsave(b);
     769           0 :         BBPunfix(b->batCacheid);
     770           0 :         return MAL_SUCCEED;
     771             : }
     772             : 
     773             : /*
     774             :  * Accelerator Control
     775             :  */
     776             : static str
     777           0 : BKCsetHash(bit *ret, const bat *bid)
     778             : {
     779             :         BAT *b;
     780             : 
     781             :         (void) ret;
     782           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     783           0 :                 throw(MAL, "bat.setHash", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     784             :         }
     785           0 :         *ret = BAThash(b) == GDK_SUCCEED;
     786           0 :         BBPunfix(b->batCacheid);
     787           0 :         return MAL_SUCCEED;
     788             : }
     789             : 
     790             : static str
     791           0 : BKCsetImprints(bit *ret, const bat *bid)
     792             : {
     793             :         BAT *b;
     794             : 
     795             :         (void) ret;
     796           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     797           0 :                 throw(MAL, "bat.setImprints", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     798             :         }
     799           0 :         *ret = BATimprints(b) == GDK_SUCCEED;
     800           0 :         BBPunfix(b->batCacheid);
     801           0 :         return MAL_SUCCEED;
     802             : }
     803             : 
     804             : static str
     805           0 : BKCgetSequenceBase(oid *r, const bat *bid)
     806             : {
     807             :         BAT *b;
     808             : 
     809           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     810           0 :                 throw(MAL, "bat.setSequenceBase", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     811             :         }
     812           0 :         *r = b->hseqbase;
     813           0 :         BBPunfix(b->batCacheid);
     814           0 :         return MAL_SUCCEED;
     815             : }
     816             : 
     817             : /*
     818             :  * Shrinking a void-headed BAT using a list of oids to ignore.
     819             :  */
     820             : #define shrinkloop(Type)                                                        \
     821             :         do {                                                                                    \
     822             :                 const Type *in = (Type*)bi.base;                        \
     823             :                 Type *restrict r = (Type*)Tloc(bn, 0);          \
     824             :                 for (;p<q; oidx++, p++) {                                    \
     825             :                         if ( o < ol && *o == oidx ){                 \
     826             :                                 o++;                                                            \
     827             :                         } else {                                                                \
     828             :                                 *r++ = in[p];                                           \
     829             :                                 cnt++;                                                          \
     830             :                         }                                                                               \
     831             :                 }                                                                                       \
     832             :         } while (0)
     833             : 
     834             : str
     835           0 : BKCshrinkBAT(bat *ret, const bat *bid, const bat *did)
     836             : {
     837             :         BAT *b, *d, *bn, *bs;
     838             :         BUN cnt = 0, p = 0, q;
     839             :         oid oidx = 0, *o, *ol;
     840             :         gdk_return res;
     841             : 
     842           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     843           0 :                 throw(MAL, "bat.shrink", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     844             :         }
     845           0 :         if ((d = BATdescriptor(*did)) == NULL) {
     846           0 :                 BBPunfix(b->batCacheid);
     847           0 :                 throw(MAL, "bat.shrink", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     848             :         }
     849           0 :         bn= COLnew(0, b->ttype, BATcount(b) - BATcount(d), b->batRole);
     850           0 :         if (bn == NULL) {
     851           0 :                 BBPunfix(b->batCacheid);
     852           0 :                 BBPunfix(d->batCacheid);
     853           0 :                 throw(MAL, "bat.shrink", SQLSTATE(HY013) MAL_MALLOC_FAIL );
     854             :         }
     855           0 :         res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false);
     856           0 :         BBPunfix(d->batCacheid);
     857           0 :         if (res != GDK_SUCCEED) {
     858           0 :                 BBPunfix(b->batCacheid);
     859           0 :                 BBPunfix(bn->batCacheid);
     860           0 :                 throw(MAL, "bat.shrink", GDK_EXCEPTION);
     861             :         }
     862             : 
     863           0 :         o = (oid*)Tloc(bs, 0);
     864           0 :         ol = (oid*)Tloc(bs, BUNlast(bs));
     865             : 
     866           0 :         BATiter bi = bat_iterator(b);
     867           0 :         q = bi.count;
     868           0 :         if (ATOMvarsized(bi.type)) {
     869           0 :                 for (;p<q; oidx++, p++) {
     870           0 :                         if ( o < ol && *o == oidx ){
     871           0 :                                 o++;
     872             :                         } else {
     873           0 :                                 if (BUNappend(bn, BUNtail(bi, p), false) != GDK_SUCCEED) {
     874           0 :                                         bat_iterator_end(&bi);
     875           0 :                                         BBPunfix(b->batCacheid);
     876           0 :                                         BBPunfix(bn->batCacheid);
     877           0 :                                         throw(MAL, "bat.shrink", GDK_EXCEPTION);
     878             :                                 }
     879           0 :                                 cnt++;
     880             :                         }
     881             :                 }
     882             :         } else {
     883           0 :                 uint16_t width = bi.width;
     884             : 
     885           0 :                 switch (width) {
     886           0 :                 case 0:
     887           0 :                         bat_iterator_end(&bi);
     888           0 :                         BBPunfix(b->batCacheid);
     889           0 :                         BBPunfix(bn->batCacheid);
     890           0 :                         throw(MAL, "bat.shrink", SQLSTATE(42000) "bat.shrink not available for 0 width types");
     891           0 :                 case 1:shrinkloop(bte); break;
     892           0 :                 case 2:shrinkloop(sht); break;
     893           0 :                 case 4:shrinkloop(int); break;
     894           0 :                 case 8:shrinkloop(lng); break;
     895             : #ifdef HAVE_HGE
     896           0 :                 case 16:shrinkloop(hge); break;
     897             : #endif
     898           0 :                 default: {
     899           0 :                         const int8_t *restrict src = (int8_t*) bi.base;
     900           0 :                         int8_t *restrict dst = (int8_t*) Tloc(bn, 0);
     901             : 
     902           0 :                         assert(b->ttype != TYPE_oid); /* because of 'restrict', the oid case can't fall here */
     903           0 :                         for (;p<q; oidx++, p++) {
     904           0 :                                 if (o < ol && *o == oidx) {
     905           0 :                                         o++;
     906             :                                 } else {
     907           0 :                                         memcpy(dst, src, width);
     908           0 :                                         dst += width;
     909           0 :                                         cnt++;
     910             :                                 }
     911           0 :                                 src += width;
     912             :                         }
     913             :                 }
     914             :                 }
     915             :         }
     916           0 :         bat_iterator_end(&bi);
     917             : 
     918           0 :         BATsetcount(bn, cnt);
     919           0 :         bn->tsorted = false;
     920           0 :         bn->trevsorted = false;
     921           0 :         bn->tseqbase = oid_nil;
     922           0 :         bn->tkey = b->tkey;
     923           0 :         bn->tnonil = b->tnonil;
     924           0 :         bn->tnil = false;            /* can't be sure if values deleted */
     925             : 
     926           0 :         BBPunfix(b->batCacheid);
     927           0 :         BBPunfix(bs->batCacheid);
     928           0 :         BBPkeepref(*ret= bn->batCacheid);
     929           0 :         return MAL_SUCCEED;
     930             : }
     931             : 
     932             : #if 0
     933             : str
     934             : BKCshrinkBATmap(bat *ret, const bat *bid, const bat *did)
     935             : {
     936             :         BAT *b, *d, *bn, *bs;
     937             :         oid lim,oidx = 0, *o, *ol;
     938             :         oid *r;
     939             :         gdk_return res;
     940             : 
     941             :         if ((b = BATdescriptor(*bid)) == NULL) {
     942             :                 throw(MAL, "bat.shrinkMap", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     943             :         }
     944             :         if ((d = BATdescriptor(*did)) == NULL) {
     945             :                 BBPunfix(b->batCacheid);
     946             :                 throw(MAL, "bat.shrinkMap", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     947             :         }
     948             : 
     949             :         bn= COLnew(b->hseqbase, TYPE_oid, BATcount(b) , TRANSIENT);
     950             :         if (bn == NULL) {
     951             :                 BBPunfix(b->batCacheid);
     952             :                 BBPunfix(d->batCacheid);
     953             :                 throw(MAL, "bat.shrinkMap", SQLSTATE(HY013) MAL_MALLOC_FAIL );
     954             :         }
     955             :         res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false);
     956             :         BBPunfix(d->batCacheid);
     957             :         if (res != GDK_SUCCEED) {
     958             :                 BBPunfix(b->batCacheid);
     959             :                 BBPunfix(bn->batCacheid);
     960             :                 throw(MAL, "bat.shrinkMap", GDK_EXCEPTION);
     961             :         }
     962             : 
     963             :         o = (oid*)Tloc(bs, 0);
     964             :         ol= (oid*)Tloc(bs, BUNlast(bs));
     965             :         r = (oid*)Tloc(bn, 0);
     966             : 
     967             :         lim = BATcount(b);
     968             : 
     969             :         for (;oidx<lim; oidx++) {
     970             :                 if ( o < ol && *o == oidx ){
     971             :                         o++;
     972             :                 } else {
     973             :                         *r++ = oidx;
     974             :                 }
     975             :         }
     976             : 
     977             :     BATsetcount(bn, BATcount(b)-BATcount(bs));
     978             :     bn->tsorted = false;
     979             :     bn->trevsorted = false;
     980             :         bn->tseqbase = oid_nil;
     981             : 
     982             : 
     983             :         BBPunfix(b->batCacheid);
     984             :         BBPunfix(bs->batCacheid);
     985             :         BBPkeepref(*ret= bn->batCacheid);
     986             :         return MAL_SUCCEED;
     987             : }
     988             : #endif  /* unused */
     989             : 
     990             : /*
     991             :  * Shrinking a void-headed BAT using a list of oids to ignore.
     992             :  */
     993             : #define reuseloop(Type)                                                                         \
     994             :         do {                                                                                                    \
     995             :                 Type *dst = (Type *) Tloc(bn, 0);                                       \
     996             :                 const Type *src = (const Type *) bi.base;                       \
     997             :                 for (BUN p = 0; p < bi.count; p++, src++) {                  \
     998             :                         if (o < ol && b->hseqbase + p == *o) {                    \
     999             :                                 do                                                                                      \
    1000             :                                         o++;                                                                    \
    1001             :                                 while (o < ol && b->hseqbase + p == *o);  \
    1002             :                         } else {                                                                                \
    1003             :                                 *dst++ = *src;                                                          \
    1004             :                                 n++;                                                                            \
    1005             :                         }                                                                                               \
    1006             :                 }                                                                                                       \
    1007             :         } while (0)
    1008             : 
    1009             : str
    1010           1 : BKCreuseBAT(bat *ret, const bat *bid, const bat *did)
    1011             : {
    1012             :         BAT *b, *d, *bn, *bs;
    1013             :         gdk_return res;
    1014             : 
    1015           1 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1016           0 :                 throw(MAL, "bat.reuse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1017             :         }
    1018           1 :         if ((d = BATdescriptor(*did)) == NULL) {
    1019           0 :                 BBPunfix(b->batCacheid);
    1020           0 :                 throw(MAL, "bat.reuse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1021             :         }
    1022           1 :         bn= COLnew(b->hseqbase, b->ttype, BATcount(b) - BATcount(d), b->batRole);
    1023           1 :         if (bn == NULL) {
    1024           0 :                 BBPunfix(b->batCacheid);
    1025           0 :                 BBPunfix(d->batCacheid);
    1026           0 :                 throw(MAL, "bat.reuse", SQLSTATE(HY013) MAL_MALLOC_FAIL );
    1027             :         }
    1028           1 :         res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false);
    1029           1 :         BBPunfix(d->batCacheid);
    1030           1 :         if (res != GDK_SUCCEED) {
    1031           0 :                 BBPunfix(b->batCacheid);
    1032           0 :                 BBPunfix(bn->batCacheid);
    1033           0 :                 throw(MAL, "bat.reuse", GDK_EXCEPTION);
    1034             :         }
    1035             : 
    1036           1 :         const oid *o = (const oid *) Tloc(bs, 0);
    1037           1 :         const oid *ol = o + bs->batCount;
    1038           1 :         while (o < ol && *o < b->hseqbase)
    1039           0 :                 o++;
    1040           1 :         BATiter bi = bat_iterator(b);
    1041           1 :         if (b->tvarsized) {
    1042           0 :                 for (BUN p = 0; p < bi.count; p++) {
    1043           0 :                         if (o < ol && b->hseqbase + p == *o) {
    1044             :                                 do
    1045           0 :                                         o++;
    1046           0 :                                 while (o < ol && b->hseqbase + p == *o);
    1047           0 :                         } else if (BUNappend(bn, BUNtail(bi, p), false) != GDK_SUCCEED) {
    1048           0 :                                 bat_iterator_end(&bi);
    1049           0 :                                 BBPunfix(bn->batCacheid);
    1050           0 :                                 BBPunfix(b->batCacheid);
    1051           0 :                                 BBPunfix(bs->batCacheid);
    1052           0 :                                 throw(MAL, "bat.reuse", GDK_EXCEPTION);
    1053             :                         }
    1054             :                 }
    1055             :         } else {
    1056             :                 BUN n = 0;
    1057           1 :                 switch (bi.width) {
    1058           0 :                 case 0:
    1059           0 :                         bat_iterator_end(&bi);
    1060           0 :                         BBPunfix(bn->batCacheid);
    1061           0 :                         BBPunfix(b->batCacheid);
    1062           0 :                         BBPunfix(bs->batCacheid);
    1063           0 :                         throw(MAL, "bat.reuse", SQLSTATE(42000) "bat.reuse not available for 0 width types");
    1064           0 :                 case 1:
    1065           0 :                         reuseloop(bte);
    1066             :                         break;
    1067           0 :                 case 2:
    1068           0 :                         reuseloop(sht);
    1069             :                         break;
    1070           1 :                 case 4:
    1071          10 :                         reuseloop(int);
    1072             :                         break;
    1073           0 :                 case 8:
    1074           0 :                         reuseloop(lng);
    1075             :                         break;
    1076             : #ifdef HAVE_HGE
    1077           0 :                 case 16:
    1078           0 :                         reuseloop(hge);
    1079             :                         break;
    1080             : #endif
    1081           0 :                 default: {
    1082           0 :                         char *dst = (char *) Tloc(bn, 0);
    1083           0 :                         const char *src = (const char *) bi.base;
    1084           0 :                         for (BUN p = 0; p < bi.count; p++) {
    1085           0 :                                 if (o < ol && b->hseqbase + p == *o) {
    1086             :                                         do
    1087           0 :                                                 o++;
    1088           0 :                                         while (o < ol && b->hseqbase + p == *o);
    1089             :                                 } else {
    1090           0 :                                         memcpy(dst, src, bi.width);
    1091           0 :                                         dst += bi.width;
    1092           0 :                                         n++;
    1093             :                                 }
    1094           0 :                                 src += bi.width;
    1095             :                         }
    1096             :                         break;
    1097             :                 }
    1098             :                 }
    1099           1 :                 BATsetcount(bn, n);
    1100           1 :                 bn->tkey = b->tkey;
    1101           1 :                 bn->tsorted = b->tsorted;
    1102           1 :                 bn->trevsorted = b->trevsorted;
    1103           1 :                 bn->tnonil = b->tnonil;
    1104           1 :                 bn->tnil = false;            /* can't be sure if values deleted */
    1105             :         }
    1106           1 :         bat_iterator_end(&bi);
    1107             : 
    1108           1 :         BBPunfix(b->batCacheid);
    1109           1 :         BBPunfix(bs->batCacheid);
    1110           1 :         BBPkeepref(*ret= bn->batCacheid);
    1111           1 :         return MAL_SUCCEED;
    1112             : }
    1113             : 
    1114             : static str
    1115           1 : BKCreuseBATmap(bat *ret, const bat *bid, const bat *did)
    1116             : {
    1117             :         BAT *b, *d, *bn, *bs;
    1118             :         gdk_return res;
    1119             : 
    1120           1 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1121           0 :                 throw(MAL, "bat.shrinkMap", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1122             :         }
    1123           1 :         if ((d = BATdescriptor(*did)) == NULL) {
    1124           0 :                 BBPunfix(b->batCacheid);
    1125           0 :                 throw(MAL, "bat.shrinkMap", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1126             :         }
    1127           1 :         bn= COLnew(b->hseqbase, TYPE_oid, BATcount(b) - BATcount(d), TRANSIENT);
    1128           1 :         if (bn == NULL) {
    1129           0 :                 BBPunfix(b->batCacheid);
    1130           0 :                 BBPunfix(d->batCacheid);
    1131           0 :                 throw(MAL, "bat.shrinkMap", SQLSTATE(HY013) MAL_MALLOC_FAIL );
    1132             :         }
    1133           1 :         res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false);
    1134           1 :         BBPunfix(d->batCacheid);
    1135           1 :         if (res != GDK_SUCCEED) {
    1136           0 :                 BBPunfix(b->batCacheid);
    1137           0 :                 BBPunfix(bn->batCacheid);
    1138           0 :                 throw(MAL, "bat.shrinkMap", GDK_EXCEPTION);
    1139             :         }
    1140             : 
    1141           1 :         const oid *o = (const oid *) Tloc(bs, 0);
    1142           1 :         const oid *ol = o + bs->batCount;
    1143           1 :         while (o < ol && *o < b->hseqbase)
    1144           0 :                 o++;
    1145           1 :         oid *dst = (oid *) Tloc(bn, 0);
    1146             :         BUN n = 0;
    1147          10 :         for (BUN p = 0; p < b->batCount; p++) {
    1148           9 :                 if (o < ol && b->hseqbase + p == *o) {
    1149             :                         do
    1150           3 :                                 o++;
    1151           3 :                         while (o < ol && b->hseqbase + p == *o);
    1152             :                 } else {
    1153           6 :                         *dst++ = b->hseqbase + p;
    1154           6 :                         n++;
    1155             :                 }
    1156             :         }
    1157           1 :         BATsetcount(bn, n);
    1158           1 :         bn->tkey = true;
    1159           1 :         bn->tsorted = true;
    1160           1 :         bn->trevsorted = n <= 1;
    1161           1 :         bn->tnil = false;
    1162           1 :         bn->tnonil = true;
    1163           1 :         bn->tseqbase = oid_nil;
    1164             : 
    1165           1 :         BBPunfix(b->batCacheid);
    1166           1 :         BBPunfix(bs->batCacheid);
    1167           1 :         BBPkeepref(*ret= bn->batCacheid);
    1168           1 :         return MAL_SUCCEED;
    1169             : }
    1170             : 
    1171             : static str
    1172       81055 : BKCmergecand(bat *ret, const bat *aid, const bat *bid)
    1173             : {
    1174             :         BAT *a, *b, *bn;
    1175             : 
    1176       81055 :         if ((a = BATdescriptor(*aid)) == NULL) {
    1177           0 :                 throw(MAL, "bat.mergecand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1178             :         }
    1179       81052 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1180           0 :                 BBPunfix(a->batCacheid);
    1181           0 :                 throw(MAL, "bat.mergecand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1182             :         }
    1183       81054 :         bn = BATmergecand(a, b);
    1184       81055 :         BBPunfix(a->batCacheid);
    1185       81053 :         BBPunfix(b->batCacheid);
    1186       81054 :         if (bn == NULL)
    1187           0 :                 throw(MAL, "bat.mergecand", GDK_EXCEPTION);
    1188       81054 :         *ret = bn->batCacheid;
    1189       81054 :         BBPkeepref(*ret);
    1190       81053 :         return MAL_SUCCEED;
    1191             : }
    1192             : 
    1193             : static str
    1194           0 : BKCintersectcand(bat *ret, const bat *aid, const bat *bid)
    1195             : {
    1196             :         BAT *a, *b, *bn;
    1197             : 
    1198           0 :         if ((a = BATdescriptor(*aid)) == NULL) {
    1199           0 :                 throw(MAL, "bat.intersectcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1200             :         }
    1201           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1202           0 :                 BBPunfix(a->batCacheid);
    1203           0 :                 throw(MAL, "bat.intersectcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1204             :         }
    1205           0 :         bn = BATintersectcand(a, b);
    1206           0 :         BBPunfix(a->batCacheid);
    1207           0 :         BBPunfix(b->batCacheid);
    1208           0 :         if (bn == NULL)
    1209           0 :                 throw(MAL, "bat.intersectcand", GDK_EXCEPTION);
    1210           0 :         *ret = bn->batCacheid;
    1211           0 :         BBPkeepref(*ret);
    1212           0 :         return MAL_SUCCEED;
    1213             : }
    1214             : 
    1215             : static str
    1216           0 : BKCdiffcand(bat *ret, const bat *aid, const bat *bid)
    1217             : {
    1218             :         BAT *a, *b, *bn;
    1219             : 
    1220           0 :         if ((a = BATdescriptor(*aid)) == NULL) {
    1221           0 :                 throw(MAL, "bat.diffcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1222             :         }
    1223           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1224           0 :                 BBPunfix(a->batCacheid);
    1225           0 :                 throw(MAL, "bat.diffcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1226             :         }
    1227           0 :         bn = BATdiffcand(a, b);
    1228           0 :         BBPunfix(a->batCacheid);
    1229           0 :         BBPunfix(b->batCacheid);
    1230           0 :         if (bn == NULL)
    1231           0 :                 throw(MAL, "bat.diffcand", GDK_EXCEPTION);
    1232           0 :         *ret = bn->batCacheid;
    1233           0 :         BBPkeepref(*ret);
    1234           0 :         return MAL_SUCCEED;
    1235             : }
    1236             : 
    1237             : #include "mel.h"
    1238             : mel_func bat5_init_funcs[] = {
    1239             :  command("bat", "mirror", BKCmirror, false, "Returns the head-mirror image of a BAT (two head columns).", args(1,2, batarg("",oid),batargany("b",2))),
    1240             :  command("bat", "delete", BKCdelete, false, "Delete BUN indicated by head value, exchanging with last BUN", args(1,3, batargany("",1),batargany("b",1),arg("h",oid))),
    1241             :  command("bat", "delete", BKCdelete_multi, false, "Delete multiple BUN, shifting BUNs up", args(1,3, batargany("",1),batargany("b",1),batarg("d",oid))),
    1242             :  command("bat", "delete", BKCdelete_all, false, "Delete all entries.", args(1,2, batargany("",1),batargany("b",1))),
    1243             :  command("bat", "replace", BKCbun_inplace, false, "Replace the tail value of one BUN that has some head value.", args(1,4, batargany("",1),batargany("b",1),arg("h",oid),argany("t",1))),
    1244             :  command("bat", "replace", BKCbun_inplace_force, false, "Replace the tail value of one BUN that has some head value.", args(1,5, batargany("",1),batargany("b",1),arg("h",oid),argany("t",1),arg("force",bit))),
    1245             :  command("bat", "replace", BKCbat_inplace, false, "Perform replace for all BUNs of the second BAT into the first.", args(1,4, batargany("",1),batargany("b",1),batarg("rid",oid),batargany("val",1))),
    1246             :  command("bat", "replace", BKCbat_inplace_force, false, "Perform replace for all BUNs of the second BAT into the first.", args(1,5, batargany("",1),batargany("b",1),batarg("rid",oid),batargany("val",1),arg("force",bit))),
    1247             :  command("bat", "append", BKCappend_wrap, false, "append the content of u to i", args(1,3, batargany("",1),batargany("i",1),batargany("u",1))),
    1248             :  command("bat", "append", BKCappend_force_wrap, false, "append the content of u to i", args(1,4, batargany("",1),batargany("i",1),batargany("u",1),arg("force",bit))),
    1249             :  command("bat", "append", BKCappend_cand_wrap, false, "append the content of u with candidate list s to i", args(1,4, batargany("",1),batargany("i",1),batargany("u",1),batarg("s",oid))),
    1250             :  command("bat", "append", BKCappend_cand_force_wrap, false, "append the content of u with candidate list s to i", args(1,5, batargany("",1),batargany("i",1),batargany("u",1),batarg("s",oid),arg("force",bit))),
    1251             :  command("bat", "append", BKCappend_val_force_wrap, false, "append the value u to i", args(1,4, batargany("",1),batargany("i",1),argany("u",1),arg("force",bit))),
    1252             :  command("bat", "attach", BKCattach, false, "Returns a new BAT with dense head and tail of the given type and uses\nthe given file to initialize the tail. The file will be owned by the\nserver.", args(1,3, batargany("",1),arg("tt",int),arg("heapfile",str))),
    1253             :  command("bat", "densebat", BKCdensebat, false, "Creates a new [void,void] BAT of size 'sz'.", args(1,2, batarg("",oid),arg("sz",lng))),
    1254             :  command("bat", "info", BKCinfo, false, "Produce a table containing information about a BAT in [attribute,value] format. \nIt contains all properties of the BAT record. ", args(2,3, batarg("",str),batarg("",str),batargany("b",1))),
    1255             :  command("bat", "getSize", BKCgetSize, false, "Calculate the actual size of the BAT descriptor, heaps, hashes and imprint indices in bytes\nrounded to the memory page size (see bbp.getPageSize()).", args(1,2, arg("",lng),batargany("b",1))),
    1256             :  command("bat", "getVHeapSize", BKCgetVHeapSize, false, "Calculate the vheap size for varsized bats", args(1,2, arg("",lng),batargany("b",1))),
    1257             :  command("bat", "getCapacity", BKCgetCapacity, false, "Returns the current allocation size (in max number of elements) of a BAT.", args(1,2, arg("",lng),batargany("b",1))),
    1258             :  command("bat", "getColumnType", BKCgetColumnType, false, "Returns the type of the tail column of a BAT, as an integer type number.", args(1,2, arg("",str),batargany("b",1))),
    1259             :  command("bat", "getRole", BKCgetRole, false, "Returns the rolename of the head column of a BAT.", args(1,2, arg("",str),batargany("bid",1))),
    1260             :  command("bat", "isaKey", BKCgetKey, false, "Return whether the column tail values are unique (key).", args(1,2, arg("",bit),batargany("b",1))),
    1261             :  command("bat", "setAccess", BKCsetAccess, false, "Try to change the update access priviliges \nto this BAT. Mode:\nr[ead-only]      - allow only read access.\na[append-only]   - allow reads and update.\nw[riteable]      - allow all operations.\nBATs are updatable by default. On making a BAT read-only, \nall subsequent updates fail with an error message.\nReturns the BAT itself.", args(1,3, batargany("",1),batargany("b",1),arg("mode",str))),
    1262             :  command("bat", "getAccess", BKCgetAccess, false, "Return the access mode attached to this BAT as a character.", args(1,2, arg("",str),batargany("b",1))),
    1263             :  command("bat", "getSequenceBase", BKCgetSequenceBase, false, "Get the sequence base for the void column of a BAT.", args(1,2, arg("",oid),batargany("b",1))),
    1264             :  command("bat", "isSorted", BKCisSorted, false, "Returns true if BAT values are ordered.", args(1,2, arg("",bit),batargany("b",1))),
    1265             :  command("bat", "isSortedReverse", BKCisSortedReverse, false, "Returns true if BAT values are reversely ordered.", args(1,2, arg("",bit),batargany("b",1))),
    1266             :  command("bat", "append", BKCappend_val_wrap, false, "append the value u to i", args(1,3, batargany("",1),batargany("i",1),argany("u",1))),
    1267             :  command("bat", "setName", BKCsetName, false, "Give a logical name to a BAT. ", args(1,3, arg("",void),batargany("b",1),arg("s",str))),
    1268             :  command("bat", "getName", BKCgetBBPname, false, "Gives back the logical name of a BAT.", args(1,2, arg("",str),batargany("b",1))),
    1269             :  command("bat", "setColumn", BKCsetColumn, false, "Give a logical name to the tail column of a BAT.", args(1,3, arg("",void),batargany("b",1),arg("t",str))),
    1270             :  command("bat", "isTransient", BKCisTransient, false, "", args(1,2, arg("",bit),batargany("b",1))),
    1271             :  command("bat", "setTransient", BKCsetTransient, false, "Make the BAT transient.  Returns \nboolean which indicates if the\nBAT administration has indeed changed.", args(1,2, arg("",void),batargany("b",1))),
    1272             :  command("bat", "isPersistent", BKCisPersistent, false, "", args(1,2, arg("",bit),batargany("b",1))),
    1273             :  command("bat", "setPersistent", BKCsetPersistent, false, "Make the BAT persistent.", args(1,2, arg("",void),batargany("b",1))),
    1274             :  command("bat", "save", BKCsave2, false, "", args(1,2, arg("",void),batargany("nme",1))),
    1275             :  command("bat", "save", BKCsave, false, "Save a BAT to storage, if it was loaded and dirty.  \nReturns whether IO was necessary.  Please realize that \ncalling this function violates the atomic commit protocol!!", args(1,2, arg("",bit),arg("nme",str))),
    1276             :  command("bat", "setHash", BKCsetHash, false, "Create a hash structure on the column", args(1,2, arg("",bit),batargany("b",1))),
    1277             :  command("bat", "setImprints", BKCsetImprints, false, "Create an imprints structure on the column", args(1,2, arg("",bit),batargany("b",1))),
    1278             :  command("bat", "isSynced", BKCisSynced, false, "Tests whether two BATs are synced or not. ", args(1,3, arg("",bit),batargany("b1",1),batargany("b2",2))),
    1279             :  command("bat", "reuse", BKCreuseBAT, false, "Shuffle the values around to restore a dense representation of buns.", args(1,3, batargany("",1),batargany("b",1),batarg("del",oid))),
    1280             :  command("bat", "reuseMap", BKCreuseBATmap, false, "Derive the oid mapping for reuse BAT based on list of to-be-deleted", args(1,3, batarg("",oid),batargany("b",1),batarg("del",oid))),
    1281             :  command("bat", "mergecand", BKCmergecand, false, "Merge two candidate lists into one", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
    1282             :  command("bat", "intersectcand", BKCintersectcand, false, "Intersect two candidate lists into one", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
    1283             :  command("bat", "diffcand", BKCdiffcand, false, "Calculate difference of two candidate lists", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
    1284             :  { .imp=NULL }
    1285             : };
    1286             : #include "mal_import.h"
    1287             : #ifdef _MSC_VER
    1288             : #undef read
    1289             : #pragma section(".CRT$XCU",read)
    1290             : #endif
    1291         259 : LIB_STARTUP_FUNC(init_bat5_mal)
    1292         259 : { mal_module("bat5", NULL, bat5_init_funcs); }

Generated by: LCOV version 1.14