LCOV - code coverage report
Current view: top level - monetdb5/modules/kernel - bat5.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 192 656 29.3 %
Date: 2024-04-25 20:03:45 Functions: 23 47 48.9 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * Peter Boncz, M.L. Kersten
      15             :  * Binary Association Tables
      16             :  * This module contains the commands and patterns to manage Binary
      17             :  * Association Tables (BATs). The relational operations you can execute
      18             :  * on BATs have the form of a neat algebra, described in algebra.c
      19             :  *
      20             :  * But a database system needs more that just this algebra, since often it
      21             :  * is crucial to do table-updates (this would not be permitted in a strict
      22             :  * algebra).
      23             :  *
      24             :  * All commands needed for BAT updates, property management, basic I/O,
      25             :  * persistence, and storage options can be found in this module.
      26             :  *
      27             :  * All parameters to the modules are passed by reference.
      28             :  * In particular, this means that string values are passed to the module
      29             :  * layer as (str *)
      30             :  * and we have to de-reference them before entering the gdk library.
      31             :  * (Actual a design error in gdk to differentiate passing int/str)
      32             :  * This calls for knowledge on the underlying BAT types`s
      33             :  */
      34             : 
      35             : #include "monetdb_config.h"
      36             : #include "bat5.h"
      37             : #include "mal_exception.h"
      38             : 
      39             : /*
      40             :  * The remainder contains the wrapper code over the mserver version 4
      41             :  * InformationFunctions
      42             :  * In most cases we pass a BAT identifier, which should be unified
      43             :  * with a BAT descriptor. Upon failure we can simply abort the function.
      44             :  *
      45             :  * The logical head type :oid is mapped to a TYPE_void
      46             :  * with sequenceBase. It represents the old fashioned :vid
      47             :  */
      48             : 
      49             : 
      50             : #define derefStr(b, v)                                                  \
      51             :         do {                                                                            \
      52             :                 int _tpe= ATOMstorage((b)->ttype);           \
      53             :                 if (_tpe >= TYPE_str) {                                      \
      54             :                         if ((v) == 0 || *(str*) (v) == 0)       \
      55             :                                 (v) = (str) str_nil;                    \
      56             :                         else                                                            \
      57             :                                 (v) = *(str *) (v);                             \
      58             :                 }                                                                               \
      59             :         } while (0)
      60             : 
      61             : str
      62      208728 : BKCnewBAT(bat *res, const int *tt, const BUN *cap, role_t role)
      63             : {
      64      208728 :         BAT *bn;
      65             : 
      66      208728 :         bn = COLnew(0, *tt, *cap, role);
      67      208720 :         if (bn == NULL)
      68           0 :                 throw(MAL, "bat.new", GDK_EXCEPTION);
      69      208720 :         *res = bn->batCacheid;
      70      208720 :         bn->tkey = true;                     /* COLnew leaves it as false */
      71      208720 :         BBPretain(bn->batCacheid);
      72      208664 :         BBPunfix(bn->batCacheid);
      73      208664 :         return MAL_SUCCEED;
      74             : }
      75             : 
      76             : static str
      77           0 : BKCattach(bat *ret, const int *tt, const char *const *heapfile)
      78             : {
      79           0 :         BAT *bn;
      80             : 
      81           0 :         bn = BATattach(*tt, *heapfile, TRANSIENT);
      82           0 :         if (bn == NULL)
      83           0 :                 throw(MAL, "bat.attach", GDK_EXCEPTION);
      84           0 :         *ret = bn->batCacheid;
      85           0 :         BBPkeepref(bn);
      86           0 :         return MAL_SUCCEED;
      87             : }
      88             : 
      89             : static str
      90           0 : BKCdensebat(bat *ret, const lng *size)
      91             : {
      92           0 :         BAT *bn;
      93           0 :         lng sz = *size;
      94             : 
      95           0 :         if (sz < 0)
      96             :                 sz = 0;
      97             :         if (sz > (lng) BUN_MAX)
      98             :                 sz = (lng) BUN_MAX;
      99           0 :         bn = BATdense(0, 0, (BUN) sz);
     100           0 :         if (bn == NULL)
     101           0 :                 throw(MAL, "bat.densebat", GDK_EXCEPTION);
     102           0 :         *ret = bn->batCacheid;
     103           0 :         BBPkeepref(bn);
     104           0 :         return MAL_SUCCEED;
     105             : }
     106             : 
     107             : str
     108       43067 : BKCmirror(bat *ret, const bat *bid)
     109             : {
     110       43067 :         BAT *b, *bn;
     111             : 
     112       43067 :         *ret = 0;
     113       43067 :         if (!(b = BBPquickdesc(*bid)))
     114           0 :                 throw(MAL, "bat.mirror", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     115       43067 :         if (!(bn = BATdense(b->hseqbase, b->hseqbase, BATcount(b))))
     116           0 :                 throw(MAL, "bat.mirror", GDK_EXCEPTION);
     117       43065 :         *ret = bn->batCacheid;
     118       43065 :         BBPkeepref(bn);
     119       43065 :         return MAL_SUCCEED;
     120             : }
     121             : 
     122             : static str
     123           4 : BKCdelete(bat *r, const bat *bid, const oid *h)
     124             : {
     125           4 :         BAT *b;
     126             : 
     127           4 :         if ((b = BATdescriptor(*bid)) == NULL)
     128           0 :                 throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     129           4 :         if (BUNdelete(b, *h) != GDK_SUCCEED) {
     130           0 :                 BBPunfix(b->batCacheid);
     131           0 :                 throw(MAL, "bat.delete", GDK_EXCEPTION);
     132             :         }
     133           4 :         *r = b->batCacheid;
     134           4 :         BBPretain(b->batCacheid);
     135           4 :         BBPunfix(b->batCacheid);
     136           4 :         return MAL_SUCCEED;
     137             : }
     138             : 
     139             : static str
     140           4 : BKCdelete_multi(bat *r, const bat *bid, const bat *sid)
     141             : {
     142           4 :         BAT *b, *s;
     143           4 :         gdk_return ret;
     144             : 
     145           4 :         if ((b = BATdescriptor(*bid)) == NULL)
     146           0 :                 throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     147           4 :         if ((s = BATdescriptor(*sid)) == NULL) {
     148           0 :                 BBPunfix(b->batCacheid);
     149           0 :                 throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     150             :         }
     151           4 :         ret = BATdel(b, s);
     152           4 :         BBPunfix(s->batCacheid);
     153           4 :         if (ret != GDK_SUCCEED) {
     154           0 :                 BBPunfix(b->batCacheid);
     155           0 :                 throw(MAL, "bat.delete", GDK_EXCEPTION);
     156             :         }
     157           4 :         *r = b->batCacheid;
     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           7 :         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 :         *r = b->batCacheid;
     175           7 :         BBPretain(b->batCacheid);
     176           7 :         BBPunfix(b->batCacheid);
     177           7 :         return MAL_SUCCEED;
     178             : }
     179             : 
     180             : static str
     181      118592 : BKCappend_cand_force_wrap(bat *r, const bat *bid, const bat *uid,
     182             :                                                   const bat *sid, const bit *force)
     183             : {
     184      118592 :         BAT *b, *u, *s = NULL;
     185      118592 :         gdk_return ret;
     186             : 
     187      118592 :         if ((b = BATdescriptor(*bid)) == NULL)
     188           0 :                 throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     189      118575 :         if (isVIEW(b)) {
     190        9400 :                 BAT *bn = COLcopy(b, b->ttype, true, TRANSIENT);
     191        9402 :                 MT_lock_set(&b->theaplock);
     192        9402 :                 restrict_t mode = b->batRestricted;
     193        9402 :                 MT_lock_unset(&b->theaplock);
     194        9404 :                 BBPunfix(b->batCacheid);
     195        9403 :                 if (bn == NULL || (b = BATsetaccess(bn, mode)) == NULL)
     196           0 :                         throw(MAL, "bat.append", GDK_EXCEPTION);
     197             :         }
     198      118578 :         if ((u = BATdescriptor(*uid)) == NULL) {
     199           0 :                 BBPunfix(b->batCacheid);
     200           0 :                 throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     201             :         }
     202      118555 :         if (mask_cand(u)) {
     203           0 :                 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      118555 :         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      118794 :         ret = BATappend(b, u, s, force ? *force : false);
     217      118583 :         BBPunfix(u->batCacheid);
     218      118577 :         BBPreclaim(s);
     219      118576 :         if (ret != GDK_SUCCEED) {
     220           0 :                 BBPunfix(b->batCacheid);
     221           0 :                 throw(MAL, "bat.append", GDK_EXCEPTION);
     222             :         }
     223      118576 :         *r = b->batCacheid;
     224      118576 :         BBPretain(b->batCacheid);
     225      118586 :         BBPunfix(b->batCacheid);
     226      118586 :         return MAL_SUCCEED;
     227             : }
     228             : 
     229             : static str
     230           0 : BKCappend_cand_wrap(bat *r, const bat *bid, const bat *uid, const bat *sid)
     231             : {
     232           0 :         return BKCappend_cand_force_wrap(r, bid, uid, sid, NULL);
     233             : }
     234             : 
     235             : static str
     236         239 : BKCappend_wrap(bat *r, const bat *bid, const bat *uid)
     237             : {
     238         239 :         return BKCappend_cand_force_wrap(r, bid, uid, NULL, NULL);
     239             : }
     240             : 
     241             : static str
     242      118352 : BKCappend_force_wrap(bat *r, const bat *bid, const bat *uid, const bit *force)
     243             : {
     244      118352 :         return BKCappend_cand_force_wrap(r, bid, uid, NULL, force);
     245             : }
     246             : 
     247             : static str
     248    15260540 : BKCappend_val_force_wrap(bat *r, const bat *bid, const void *u,
     249             :                                                  const bit *force)
     250             : {
     251    15260540 :         BAT *b;
     252             : 
     253    15260540 :         if ((b = BATdescriptor(*bid)) == NULL)
     254           0 :                 throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     255    15260540 :         if (isVIEW(b)) {
     256         739 :                 BAT *bn = COLcopy(b, b->ttype, true, TRANSIENT);
     257         739 :                 MT_lock_set(&b->theaplock);
     258         739 :                 restrict_t mode = b->batRestricted;
     259         739 :                 MT_lock_unset(&b->theaplock);
     260         739 :                 BBPunfix(b->batCacheid);
     261         739 :                 if (bn == NULL || (b = BATsetaccess(bn, mode)) == NULL)
     262           0 :                         throw(MAL, "bat.append", GDK_EXCEPTION);
     263             :         }
     264    15260540 :         derefStr(b, u);
     265    30518853 :         if (BUNappend(b, u, force ? *force : false) != GDK_SUCCEED) {
     266           0 :                 BBPunfix(b->batCacheid);
     267           0 :                 throw(MAL, "bat.append", GDK_EXCEPTION);
     268             :         }
     269    15260540 :         *r = b->batCacheid;
     270    15260540 :         BBPretain(b->batCacheid);
     271    15260540 :         BBPunfix(b->batCacheid);
     272    15260540 :         return MAL_SUCCEED;
     273             : }
     274             : 
     275             : static str
     276    15258313 : BKCappend_val_wrap(bat *r, const bat *bid, const void *u)
     277             : {
     278    15258313 :         return BKCappend_val_force_wrap(r, bid, u, NULL);
     279             : }
     280             : 
     281             : static str
     282         103 : BKCbun_inplace(bat *r, const bat *bid, const oid *id, const void *t)
     283             : {
     284         103 :         BAT *b;
     285             : 
     286         103 :         if ((b = BATdescriptor(*bid)) == NULL)
     287           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     288         103 :         derefStr(b, t);
     289         103 :         if (void_inplace(b, *id, t, false) != GDK_SUCCEED) {
     290           0 :                 BBPunfix(b->batCacheid);
     291           0 :                 throw(MAL, "bat.inplace", GDK_EXCEPTION);
     292             :         }
     293         103 :         *r = b->batCacheid;
     294         103 :         BBPretain(b->batCacheid);
     295         103 :         BBPunfix(b->batCacheid);
     296         103 :         return MAL_SUCCEED;
     297             : }
     298             : 
     299             : static str
     300           0 : BKCbun_inplace_force(bat *r, const bat *bid, const oid *id, const void *t,
     301             :                                          const bit *force)
     302             : {
     303           0 :         BAT *b;
     304             : 
     305           0 :         if ((b = BATdescriptor(*bid)) == NULL)
     306           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     307           0 :         derefStr(b, t);
     308           0 :         if (void_inplace(b, *id, t, *force) != GDK_SUCCEED) {
     309           0 :                 BBPunfix(b->batCacheid);
     310           0 :                 throw(MAL, "bat.inplace", GDK_EXCEPTION);
     311             :         }
     312           0 :         *r = b->batCacheid;
     313           0 :         BBPretain(b->batCacheid);
     314           0 :         BBPunfix(b->batCacheid);
     315           0 :         return MAL_SUCCEED;
     316             : }
     317             : 
     318             : 
     319             : static str
     320       69508 : BKCbat_inplace_force(bat *r, const bat *bid, const bat *rid, const bat *uid,
     321             :                                          const bit *force)
     322             : {
     323       69508 :         BAT *b, *p, *u;
     324             : 
     325       69508 :         if ((b = BATdescriptor(*bid)) == NULL)
     326           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     327       69508 :         if ((p = BATdescriptor(*rid)) == NULL) {
     328           0 :                 BBPunfix(b->batCacheid);
     329           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     330             :         }
     331       69505 :         if ((u = BATdescriptor(*uid)) == NULL) {
     332           0 :                 BBPunfix(b->batCacheid);
     333           0 :                 BBPunfix(p->batCacheid);
     334           0 :                 throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     335             :         }
     336       69504 :         if (BATreplace(b, p, u, *force) != GDK_SUCCEED) {
     337           0 :                 BBPunfix(b->batCacheid);
     338           0 :                 BBPunfix(p->batCacheid);
     339           0 :                 BBPunfix(u->batCacheid);
     340           0 :                 throw(MAL, "bat.inplace", GDK_EXCEPTION);
     341             :         }
     342       69503 :         *r = b->batCacheid;
     343       69503 :         BBPretain(b->batCacheid);
     344       69506 :         BBPunfix(b->batCacheid);
     345       69498 :         BBPunfix(p->batCacheid);
     346       69497 :         BBPunfix(u->batCacheid);
     347       69497 :         return MAL_SUCCEED;
     348             : }
     349             : 
     350             : static str
     351           2 : BKCbat_inplace(bat *r, const bat *bid, const bat *rid, const bat *uid)
     352             : {
     353           2 :         bit F = FALSE;
     354             : 
     355           2 :         return BKCbat_inplace_force(r, bid, rid, uid, &F);
     356             : }
     357             : 
     358             : /*end of SQL enhancement */
     359             : 
     360             : static str
     361           0 : BKCgetCapacity(lng *res, const bat *bid)
     362             : {
     363           0 :         *res = lng_nil;
     364           0 :         BAT *b = BBPquickdesc(*bid);
     365             : 
     366           0 :         if (b == NULL)
     367           0 :                 throw(MAL, "bat.getCapacity", ILLEGAL_ARGUMENT);
     368           0 :         *res = (lng) BATcapacity(b);
     369           0 :         return MAL_SUCCEED;
     370             : }
     371             : 
     372             : static str
     373           0 : BKCgetColumnType(str *res, const bat *bid)
     374             : {
     375           0 :         const char *ret = str_nil;
     376           0 :         BAT *b = BBPquickdesc(*bid);
     377             : 
     378           0 :         if (b == NULL)
     379           0 :                 throw(MAL, "bat.getColumnType", ILLEGAL_ARGUMENT);
     380           0 :         ret = *bid < 0 ? ATOMname(TYPE_void) : ATOMname(b->ttype);
     381           0 :         *res = GDKstrdup(ret);
     382           0 :         if (*res == NULL)
     383           0 :                 throw(MAL, "bat.getColumnType", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     384             :         return MAL_SUCCEED;
     385             : }
     386             : 
     387             : static str
     388           0 : BKCisSorted(bit *res, const bat *bid)
     389             : {
     390           0 :         BAT *b;
     391             : 
     392           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     393           0 :                 throw(MAL, "bat.isSorted", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     394             :         }
     395           0 :         *res = BATordered(b);
     396           0 :         BBPunfix(b->batCacheid);
     397           0 :         return MAL_SUCCEED;
     398             : }
     399             : 
     400             : static str
     401           0 : BKCisSortedReverse(bit *res, const bat *bid)
     402             : {
     403           0 :         BAT *b;
     404             : 
     405           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     406           0 :                 throw(MAL, "bat.isSorted", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     407             :         }
     408           0 :         *res = BATordered_rev(b);
     409           0 :         BBPunfix(b->batCacheid);
     410           0 :         return MAL_SUCCEED;
     411             : }
     412             : 
     413             : /*
     414             :  * We must take care of the special case of a nil column (TYPE_void,seqbase=nil)
     415             :  * such nil columns never set tkey
     416             :  * a nil column of a BAT with <= 1 entries does not contain doubles => return TRUE.
     417             :  */
     418             : 
     419             : static str
     420           0 : BKCgetKey(bit *ret, const bat *bid)
     421             : {
     422           0 :         BAT *b;
     423             : 
     424           0 :         if ((b = BATdescriptor(*bid)) == NULL)
     425           0 :                 throw(MAL, "bat.setPersistence",
     426             :                           SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     427           0 :         MT_lock_set(&b->theaplock);
     428           0 :         *ret = b->tkey;
     429           0 :         MT_lock_unset(&b->theaplock);
     430           0 :         BBPunfix(b->batCacheid);
     431           0 :         return MAL_SUCCEED;
     432             : }
     433             : 
     434             : static str
     435           2 : BKCpersists(void *r, const bat *bid, const bit *flg)
     436             : {
     437           2 :         BAT *b;
     438             : 
     439           2 :         (void) r;
     440           2 :         if ((b = BATdescriptor(*bid)) == NULL) {
     441           0 :                 throw(MAL, "bat.setPersistence",
     442             :                           SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     443             :         }
     444           2 :         if (BATmode(b, (*flg != TRUE)) != GDK_SUCCEED) {
     445           0 :                 BBPunfix(b->batCacheid);
     446           0 :                 throw(MAL, "bat.setPersistence", ILLEGAL_ARGUMENT);
     447             :         }
     448           2 :         BBPunfix(b->batCacheid);
     449           2 :         return MAL_SUCCEED;
     450             : }
     451             : 
     452             : static str
     453           1 : BKCsetPersistent(void *r, const bat *bid)
     454             : {
     455           1 :         bit flag = TRUE;
     456           1 :         return BKCpersists(r, bid, &flag);
     457             : }
     458             : 
     459             : static str
     460           2 : BKCisPersistent(bit *res, const bat *bid)
     461             : {
     462           2 :         BAT *b;
     463             : 
     464           2 :         if ((b = BATdescriptor(*bid)) == NULL) {
     465           0 :                 throw(MAL, "bat.setPersistence",
     466             :                           SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     467             :         }
     468           2 :         MT_lock_set(&b->theaplock);
     469           2 :         *res = !b->batTransient;
     470           2 :         MT_lock_unset(&b->theaplock);
     471           2 :         BBPunfix(b->batCacheid);
     472           2 :         return MAL_SUCCEED;
     473             : }
     474             : 
     475             : static str
     476           1 : BKCsetTransient(void *r, const bat *bid)
     477             : {
     478           1 :         bit flag = FALSE;
     479           1 :         return BKCpersists(r, bid, &flag);
     480             : }
     481             : 
     482             : static str
     483           2 : BKCisTransient(bit *res, const bat *bid)
     484             : {
     485           2 :         BAT *b;
     486             : 
     487           2 :         if ((b = BATdescriptor(*bid)) == NULL) {
     488           0 :                 throw(MAL, "bat.setTransient", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     489             :         }
     490           2 :         MT_lock_set(&b->theaplock);
     491           2 :         *res = b->batTransient;
     492           2 :         MT_lock_unset(&b->theaplock);
     493           2 :         BBPunfix(b->batCacheid);
     494           2 :         return MAL_SUCCEED;
     495             : }
     496             : 
     497             : static str
     498           3 : BKCsetAccess(bat *res, const bat *bid, const char *const *param)
     499             : {
     500           3 :         BAT *b;
     501           3 :         restrict_t m;
     502             : 
     503           3 :         if ((b = BATdescriptor(*bid)) == NULL)
     504           0 :                 throw(MAL, "bat.setAccess", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     505           3 :         switch (*param[0]) {
     506             :         case 'r':
     507             :                 m = BAT_READ;
     508             :                 break;
     509           0 :         case 'a':
     510           0 :                 m = BAT_APPEND;
     511           0 :                 break;
     512           0 :         case 'w':
     513           0 :                 m = BAT_WRITE;
     514           0 :                 break;
     515           0 :         default:
     516           0 :                 *res = 0;
     517           0 :                 BBPunfix(b->batCacheid);
     518           0 :                 throw(MAL, "bat.setAccess",
     519             :                           ILLEGAL_ARGUMENT " Got %c" " expected 'r','a', or 'w'",
     520           0 :                           *param[0]);
     521             :         }
     522           3 :         if ((b = BATsetaccess(b, m)) == NULL)
     523           0 :                 throw(MAL, "bat.setAccess", OPERATION_FAILED);
     524           3 :         *res = b->batCacheid;
     525           3 :         BBPretain(b->batCacheid);
     526           3 :         BBPunfix(b->batCacheid);
     527           3 :         return MAL_SUCCEED;
     528             : }
     529             : 
     530             : static str
     531           0 : BKCgetAccess(str *res, const bat *bid)
     532             : {
     533           0 :         BAT *b;
     534             : 
     535           0 :         if ((b = BATdescriptor(*bid)) == NULL)
     536           0 :                 throw(MAL, "bat.getAccess", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     537           0 :         switch (BATgetaccess(b)) {
     538           0 :         case BAT_READ:
     539           0 :                 *res = GDKstrdup("read");
     540           0 :                 break;
     541           0 :         case BAT_APPEND:
     542           0 :                 *res = GDKstrdup("append");
     543           0 :                 break;
     544           0 :         case BAT_WRITE:
     545           0 :                 *res = GDKstrdup("write");
     546           0 :                 break;
     547             :         default:
     548           0 :                 MT_UNREACHABLE();
     549             :         }
     550           0 :         BBPunfix(b->batCacheid);
     551           0 :         if (*res == NULL)
     552           0 :                 throw(MAL, "bat.getAccess", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     553             :         return MAL_SUCCEED;
     554             : }
     555             : 
     556             : /*
     557             :  * Property management
     558             :  * All property operators should ensure exclusive access to the BAT
     559             :  * descriptor.
     560             :  * Where necessary use the primary view to access the properties
     561             :  */
     562             : static inline char *
     563           0 : pre(const char *s1, const char *s2, char *buf)
     564             : {
     565           0 :         snprintf(buf, 64, "%s%s", s1, s2);
     566           0 :         return buf;
     567             : }
     568             : 
     569             : static inline char *
     570           0 : local_itoa(ssize_t i, char *buf)
     571             : {
     572           0 :         snprintf(buf, 32, "%zd", i);
     573           0 :         return buf;
     574             : }
     575             : 
     576             : static inline char *
     577           0 : local_utoa(size_t i, char *buf)
     578             : {
     579           0 :         snprintf(buf, 32, "%zu", i);
     580           0 :         return buf;
     581             : }
     582             : 
     583             : static inline char *
     584           0 : oidtostr(oid i, char *p, size_t len)
     585             : {
     586           0 :         if (OIDtoStr(&p, &len, &i, false) < 0)
     587             :                 return NULL;
     588           0 :         return p;
     589             : }
     590             : 
     591             : static gdk_return
     592           0 : infoHeap(BAT *bk, BAT *bv, Heap *hp, str nme)
     593             : {
     594           0 :         char buf[1024], *p = buf;
     595             : 
     596           0 :         if (!hp)
     597             :                 return GDK_SUCCEED;
     598           0 :         while (*nme)
     599           0 :                 *p++ = *nme++;
     600           0 :         strcpy(p, "free");
     601           0 :         if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
     602           0 :                 BUNappend(bv, local_utoa(hp->free, buf), false) != GDK_SUCCEED)
     603           0 :                 return GDK_FAIL;
     604           0 :         strcpy(p, "size");
     605           0 :         if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
     606           0 :                 BUNappend(bv, local_utoa(hp->size, buf), false) != GDK_SUCCEED)
     607           0 :                 return GDK_FAIL;
     608           0 :         strcpy(p, "storage");
     609           0 :         if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
     610           0 :                 BUNappend(bv, (hp->base == NULL || hp->base == (char *) 1) ? "absent" : (hp->storage == STORE_MMAP) ? (hp-> filename [0] ? "memory mapped" : "anonymous vm") : (hp->storage == STORE_PRIV) ? "private map" : "malloced", false) != GDK_SUCCEED)
     611           0 :                 return GDK_FAIL;
     612           0 :         strcpy(p, "newstorage");
     613           0 :         if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
     614           0 :                 BUNappend(bv, (hp->newstorage == STORE_MEM) ? "malloced" : (hp->newstorage == STORE_PRIV) ? "private map" : "memory mapped", false) != GDK_SUCCEED)
     615           0 :                 return GDK_FAIL;
     616           0 :         strcpy(p, "filename");
     617           0 :         if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
     618           0 :                 BUNappend(bv, hp->filename[0] ? hp->filename : "no file",
     619             :                                   false) != GDK_SUCCEED)
     620           0 :                 return GDK_FAIL;
     621             :         return GDK_SUCCEED;
     622             : }
     623             : 
     624             : #define COLLISION (8 * sizeof(size_t))
     625             : 
     626             : static gdk_return
     627           0 : HASHinfo(BAT *bk, BAT *bv, Hash *h, str s)
     628             : {
     629           0 :         BUN i;
     630           0 :         BUN j;
     631           0 :         BUN k;
     632           0 :         BUN cnt[COLLISION + 1];
     633           0 :         char buf[32];
     634           0 :         char prebuf[64];
     635             : 
     636           0 :         if (BUNappend(bk, pre(s, "type", prebuf), false) != GDK_SUCCEED ||
     637           0 :                 BUNappend(bv, ATOMname(h->type), false) != GDK_SUCCEED ||
     638           0 :                 BUNappend(bk, pre(s, "mask", prebuf), false) != GDK_SUCCEED ||
     639           0 :                 BUNappend(bv, local_utoa(h->nbucket, buf), false) != GDK_SUCCEED)
     640           0 :                 return GDK_FAIL;
     641             : 
     642           0 :         for (i = 0; i < COLLISION + 1; i++) {
     643           0 :                 cnt[i] = 0;
     644             :         }
     645           0 :         for (i = 0; i < h->nbucket; i++) {
     646           0 :                 j = HASHlist(h, i);
     647           0 :                 for (k = 0; j; k++)
     648           0 :                         j >>= 1;
     649           0 :                 cnt[k]++;
     650             :         }
     651             : 
     652           0 :         for (i = 0; i < COLLISION + 1; i++)
     653           0 :                 if (cnt[i]) {
     654           0 :                         if (BUNappend(bk,
     655           0 :                                                   pre(s, local_utoa(i ? (((size_t) 1) << (i - 1)) : 0,
     656             :                                                                                         buf),
     657             :                                                           prebuf),
     658             :                                                   false) != GDK_SUCCEED
     659           0 :                                 || BUNappend(bv, local_utoa((size_t) cnt[i], buf),
     660             :                                                          false) != GDK_SUCCEED)
     661           0 :                                 return GDK_FAIL;
     662             :                 }
     663             :         return GDK_SUCCEED;
     664             : }
     665             : 
     666             : static str
     667           0 : BKCinfo(bat *ret1, bat *ret2, const bat *bid)
     668             : {
     669           0 :         const char *mode, *accessmode;
     670           0 :         BAT *bk = NULL, *bv = NULL, *b;
     671           0 :         char bf[oidStrlen];
     672           0 :         char buf[32];
     673             : 
     674           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     675           0 :                 throw(MAL, "bat.info", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     676             :         }
     677             : 
     678           0 :         bk = COLnew(0, TYPE_str, 128, TRANSIENT);
     679           0 :         bv = COLnew(0, TYPE_str, 128, TRANSIENT);
     680           0 :         if (bk == NULL || bv == NULL) {
     681           0 :                 BBPreclaim(bk);
     682           0 :                 BBPreclaim(bv);
     683           0 :                 BBPunfix(b->batCacheid);
     684           0 :                 throw(MAL, "bat.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     685             :         }
     686             : 
     687           0 :         BATiter bi = bat_iterator(b);
     688           0 :         if (bi.transient) {
     689             :                 mode = "transient";
     690             :         } else {
     691           0 :                 mode = "persistent";
     692             :         }
     693             : 
     694           0 :         switch (bi.restricted) {
     695             :         case BAT_READ:
     696             :                 accessmode = "read-only";
     697             :                 break;
     698           0 :         case BAT_WRITE:
     699           0 :                 accessmode = "updatable";
     700           0 :                 break;
     701           0 :         case BAT_APPEND:
     702           0 :                 accessmode = "append-only";
     703           0 :                 break;
     704           0 :         default:
     705           0 :                 accessmode = "unknown";
     706             :         }
     707             : 
     708           0 :         if (BUNappend(bk, "batId", false) != GDK_SUCCEED
     709           0 :                 || BUNappend(bv, BATgetId(b), false) != GDK_SUCCEED
     710           0 :                 || BUNappend(bk, "batCacheid", false) != GDK_SUCCEED
     711           0 :                 || BUNappend(bv, local_itoa((ssize_t) b->batCacheid, buf),
     712             :                                          false) != GDK_SUCCEED
     713           0 :                 || BUNappend(bk, "tparentid", false) != GDK_SUCCEED
     714           0 :                 || BUNappend(bv, local_itoa((ssize_t) bi.h->parentid, buf),
     715             :                                          false) != GDK_SUCCEED
     716           0 :                 || BUNappend(bk, "batCount", false) != GDK_SUCCEED
     717           0 :                 || BUNappend(bv, local_utoa((size_t) bi.count, buf),
     718             :                                          false) != GDK_SUCCEED
     719           0 :                 || BUNappend(bk, "batCapacity", false) != GDK_SUCCEED
     720           0 :                 || BUNappend(bv, local_utoa((size_t) b->batCapacity, buf),
     721             :                                          false) != GDK_SUCCEED
     722           0 :                 || BUNappend(bk, "head", false) != GDK_SUCCEED
     723           0 :                 || BUNappend(bv, ATOMname(TYPE_void), false) != GDK_SUCCEED
     724           0 :                 || BUNappend(bk, "tail", false) != GDK_SUCCEED
     725           0 :                 || BUNappend(bv, ATOMname(bi.type), false) != GDK_SUCCEED
     726           0 :                 || BUNappend(bk, "batPersistence", false) != GDK_SUCCEED
     727           0 :                 || BUNappend(bv, mode, false) != GDK_SUCCEED
     728           0 :                 || BUNappend(bk, "batRestricted", false) != GDK_SUCCEED
     729           0 :                 || BUNappend(bv, accessmode, false) != GDK_SUCCEED
     730           0 :                 || BUNappend(bk, "batRefcnt", false) != GDK_SUCCEED
     731           0 :                 || BUNappend(bv, local_itoa((ssize_t) BBP_refs(b->batCacheid), buf),
     732             :                                          false) != GDK_SUCCEED
     733           0 :                 || BUNappend(bk, "batLRefcnt", false) != GDK_SUCCEED
     734           0 :                 || BUNappend(bv, local_itoa((ssize_t) BBP_lrefs(b->batCacheid), buf),
     735             :                                          false) != GDK_SUCCEED
     736           0 :                 || BUNappend(bk, "batDirty", false) != GDK_SUCCEED
     737           0 :                 || BUNappend(bv, BATdirtybi(bi) ? "dirty" : "clean",
     738             :                                          false) != GDK_SUCCEED
     739           0 :                 || BUNappend(bk, "hseqbase", false) != GDK_SUCCEED
     740           0 :                 || BUNappend(bv, oidtostr(b->hseqbase, bf, sizeof(bf)),
     741             :                                          FALSE) != GDK_SUCCEED
     742           0 :                 || BUNappend(bk, "tdense", false) != GDK_SUCCEED
     743           0 :                 || BUNappend(bv, local_itoa((ssize_t) BATtdensebi(&bi), buf),
     744             :                                          false) != GDK_SUCCEED
     745           0 :                 || BUNappend(bk, "tseqbase", false) != GDK_SUCCEED
     746           0 :                 || BUNappend(bv, oidtostr(bi.tseq, bf, sizeof(bf)),
     747             :                                          FALSE) != GDK_SUCCEED
     748           0 :                 || BUNappend(bk, "tsorted", false) != GDK_SUCCEED
     749           0 :                 || BUNappend(bv, local_itoa((ssize_t) bi.sorted, buf),
     750             :                                          false) != GDK_SUCCEED
     751           0 :                 || BUNappend(bk, "trevsorted", false) != GDK_SUCCEED
     752           0 :                 || BUNappend(bv, local_itoa((ssize_t) bi.revsorted, buf),
     753             :                                          false) != GDK_SUCCEED
     754           0 :                 || BUNappend(bk, "tkey", false) != GDK_SUCCEED
     755           0 :                 || BUNappend(bv, local_itoa((ssize_t) bi.key, buf),
     756             :                                          false) != GDK_SUCCEED
     757           0 :                 || BUNappend(bk, "tvarsized", false) != GDK_SUCCEED
     758           0 :                 || BUNappend(bv,
     759           0 :                                          local_itoa((ssize_t)
     760             :                                                                 (bi.type == TYPE_void
     761           0 :                                                                  || bi.vh != NULL), buf), false) != GDK_SUCCEED
     762           0 :                 || BUNappend(bk, "tnosorted", false) != GDK_SUCCEED
     763           0 :                 || BUNappend(bv, local_utoa(bi.nosorted, buf), false) != GDK_SUCCEED
     764           0 :                 || BUNappend(bk, "tnorevsorted", false) != GDK_SUCCEED
     765           0 :                 || BUNappend(bv, local_utoa(bi.norevsorted, buf), false) != GDK_SUCCEED
     766           0 :                 || BUNappend(bk, "tnokey[0]", false) != GDK_SUCCEED
     767           0 :                 || BUNappend(bv, local_utoa(bi.nokey[0], buf), false) != GDK_SUCCEED
     768           0 :                 || BUNappend(bk, "tnokey[1]", false) != GDK_SUCCEED
     769           0 :                 || BUNappend(bv, local_utoa(bi.nokey[1], buf), false) != GDK_SUCCEED
     770           0 :                 || BUNappend(bk, "tnonil", false) != GDK_SUCCEED
     771           0 :                 || BUNappend(bv, local_utoa(bi.nonil, buf), false) != GDK_SUCCEED
     772           0 :                 || BUNappend(bk, "tnil", false) != GDK_SUCCEED
     773           0 :                 || BUNappend(bv, local_utoa(bi.nil, buf), false) != GDK_SUCCEED
     774           0 :                 || BUNappend(bk, "batInserted", false) != GDK_SUCCEED
     775           0 :                 || BUNappend(bv, local_utoa(b->batInserted, buf), false) != GDK_SUCCEED
     776           0 :                 || BUNappend(bk, "ttop", false) != GDK_SUCCEED
     777           0 :                 || BUNappend(bv, local_utoa(bi.hfree, buf), false) != GDK_SUCCEED
     778           0 :                 || BUNappend(bk, "batCopiedtodisk", false) != GDK_SUCCEED
     779           0 :                 || BUNappend(bv, local_itoa((ssize_t) bi.copiedtodisk, buf),
     780             :                                          false) != GDK_SUCCEED
     781           0 :                 || BUNappend(bk, "theap.dirty", false) != GDK_SUCCEED
     782           0 :                 || BUNappend(bv, bi.hdirty ? "dirty" : "clean", false) != GDK_SUCCEED
     783           0 :                 || infoHeap(bk, bv, bi.h, "tail.") != GDK_SUCCEED
     784           0 :                 || BUNappend(bk, "tvheap->dirty", false) != GDK_SUCCEED
     785           0 :                 || BUNappend(bv, bi.vhdirty ? "dirty" : "clean", false) != GDK_SUCCEED
     786           0 :                 || infoHeap(bk, bv, bi.vh, "theap.") != GDK_SUCCEED) {
     787           0 :                 bat_iterator_end(&bi);
     788           0 :                 BBPreclaim(bk);
     789           0 :                 BBPreclaim(bv);
     790           0 :                 BBPunfix(b->batCacheid);
     791           0 :                 throw(MAL, "bat.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     792             :         }
     793             :         /* dump index information */
     794           0 :         MT_rwlock_rdlock(&b->thashlock);
     795           0 :         if (b->thash && HASHinfo(bk, bv, b->thash, "thash->") != GDK_SUCCEED) {
     796           0 :                 MT_rwlock_rdunlock(&b->thashlock);
     797           0 :                 bat_iterator_end(&bi);
     798           0 :                 BBPreclaim(bk);
     799           0 :                 BBPreclaim(bv);
     800           0 :                 BBPunfix(b->batCacheid);
     801           0 :                 throw(MAL, "bat.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     802             :         }
     803           0 :         MT_rwlock_rdunlock(&b->thashlock);
     804           0 :         bat_iterator_end(&bi);
     805           0 :         assert(BATcount(bk) == BATcount(bv));
     806           0 :         BBPunfix(b->batCacheid);
     807           0 :         *ret1 = bk->batCacheid;
     808           0 :         BBPkeepref(bk);
     809           0 :         *ret2 = bv->batCacheid;
     810           0 :         BBPkeepref(bv);
     811           0 :         return MAL_SUCCEED;
     812             : }
     813             : 
     814             : // get the actual size of all constituents, also for views
     815             : #define ROUND_UP(x,y) ((y)*(((x)+(y)-1)/(y)))
     816             : 
     817             : static str
     818           0 : BKCgetSize(lng *tot, const bat *bid)
     819             : {
     820           0 :         BAT *b;
     821           0 :         lng size = 0;
     822           0 :         lng blksize = (lng) MT_pagesize();
     823           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     824           0 :                 throw(MAL, "bat.getDiskSize", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     825             :         }
     826             : 
     827           0 :         size = sizeof(bat);
     828             : 
     829           0 :         MT_lock_set(&b->theaplock);
     830           0 :         if (!isVIEW(b)) {
     831           0 :                 BUN cnt = BATcapacity(b);
     832           0 :                 size += ROUND_UP(b->theap->free, blksize);
     833           0 :                 if (b->tvheap)
     834           0 :                         size += ROUND_UP(b->tvheap->free, blksize);
     835           0 :                 MT_lock_unset(&b->theaplock);
     836             : 
     837           0 :                 if (b->thash)
     838           0 :                         size += ROUND_UP(sizeof(BUN) * cnt, blksize);
     839           0 :                 size += IMPSimprintsize(b);
     840             :         } else {
     841           0 :                 MT_lock_unset(&b->theaplock);
     842             :         }
     843           0 :         *tot = size;
     844           0 :         BBPunfix(*bid);
     845           0 :         return MAL_SUCCEED;
     846             : }
     847             : 
     848             : static str
     849           3 : BKCgetVHeapSize(lng *tot, const bat *bid)
     850             : {
     851           3 :         BAT *b;
     852           3 :         lng size = 0;
     853           3 :         if ((b = BATdescriptor(*bid)) == NULL) {
     854           0 :                 throw(MAL, "bat.getVHeapSize", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     855             :         }
     856           3 :         if (ATOMvarsized(b->ttype)) {
     857           3 :                 MT_lock_set(&b->theaplock);
     858           3 :                 if (b->tvheap)
     859           3 :                         size += b->tvheap->size;
     860           3 :                 MT_lock_unset(&b->theaplock);
     861             :         }
     862             : 
     863           3 :         *tot = size;
     864           3 :         BBPunfix(*bid);
     865           3 :         return MAL_SUCCEED;
     866             : }
     867             : 
     868             : /*
     869             :  * Synced BATs
     870             :  */
     871             : static str
     872           0 : BKCisSynced(bit *ret, const bat *bid1, const bat *bid2)
     873             : {
     874           0 :         BAT *b1, *b2;
     875             : 
     876           0 :         if ((b1 = BATdescriptor(*bid1)) == NULL) {
     877           0 :                 throw(MAL, "bat.isSynced", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     878             :         }
     879           0 :         if ((b2 = BATdescriptor(*bid2)) == NULL) {
     880           0 :                 BBPunfix(b1->batCacheid);
     881           0 :                 throw(MAL, "bat.isSynced", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     882             :         }
     883           0 :         *ret = ALIGNsynced(b1, b2) != 0;
     884           0 :         BBPunfix(b1->batCacheid);
     885           0 :         BBPunfix(b2->batCacheid);
     886           0 :         return MAL_SUCCEED;
     887             : }
     888             : 
     889             : /*
     890             :  * Role Management
     891             :  */
     892             : static str
     893           9 : BKCsetName(void *r, const bat *bid, const char *const *s)
     894             : {
     895           9 :         BAT *b;
     896           9 :         int ret;
     897           9 :         int c;
     898           9 :         const char *t = *s;
     899             : 
     900           9 :         (void) r;
     901           9 :         if ((b = BATdescriptor(*bid)) == NULL)
     902           0 :                 throw(MAL, "bat.setName", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     903             : 
     904          52 :         for (; (c = *t) != 0; t++)
     905          43 :                 if (c != '_' && !GDKisalnum(c)) {
     906           0 :                         BBPunfix(b->batCacheid);
     907           0 :                         throw(MAL, "bat.setName",
     908             :                                   ILLEGAL_ARGUMENT ": identifier expected: %s", *s);
     909             :                 }
     910             : 
     911           9 :         t = *s;
     912           9 :         ret = BBPrename(b, t);
     913           9 :         BBPunfix(b->batCacheid);
     914           9 :         switch (ret) {
     915           0 :         case BBPRENAME_ILLEGAL:
     916           0 :                 GDKclrerr();
     917           0 :                 throw(MAL, "bat.setName",
     918             :                           ILLEGAL_ARGUMENT ": illegal temporary name: '%s'", t);
     919           0 :         case BBPRENAME_LONG:
     920           0 :                 GDKclrerr();
     921           0 :                 throw(MAL, "bat.setName", ILLEGAL_ARGUMENT ": name too long: '%s'", t);
     922           0 :         case BBPRENAME_MEMORY:
     923           0 :                 GDKclrerr();
     924           0 :                 throw(MAL, "bat.setName", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     925           1 :         case BBPRENAME_ALREADY:
     926           1 :                 GDKclrerr();
     927             :                 /* fall through */
     928             :         case 0:
     929             :                 break;
     930             :         }
     931             :         return MAL_SUCCEED;
     932             : }
     933             : 
     934             : static str
     935           0 : BKCgetBBPname(str *ret, const bat *bid)
     936             : {
     937           0 :         BAT *b;
     938             : 
     939           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     940           0 :                 throw(MAL, "bat.getName", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     941             :         }
     942           0 :         *ret = GDKstrdup(BBP_logical(b->batCacheid));
     943           0 :         BBPunfix(b->batCacheid);
     944           0 :         return *ret ? MAL_SUCCEED : createException(MAL, "bat.getName",
     945             :                                                                                                 SQLSTATE(HY013)
     946             :                                                                                                 MAL_MALLOC_FAIL);
     947             : }
     948             : 
     949             : static str
     950           0 : BKCsave(bit *res, const char *const *input)
     951             : {
     952           0 :         bat bid = BBPindex(*input);
     953           0 :         BAT *b;
     954             : 
     955           0 :         *res = FALSE;
     956           0 :         if (!is_bat_nil(bid)) {
     957           0 :                 if (BBPfix(bid) > 0) {
     958           0 :                         b = BBP_cache(bid);
     959           0 :                         if (b && BATdirty(b)) {
     960           0 :                                 if (BBPsave(b) == GDK_SUCCEED)
     961           0 :                                         *res = TRUE;
     962             :                         }
     963           0 :                         BBPunfix(bid);
     964           0 :                         return MAL_SUCCEED;
     965             :                 }
     966           0 :                 throw(MAL, "bat.save", "fix failed");
     967             :         }
     968             :         return MAL_SUCCEED;
     969             : }
     970             : 
     971             : static str
     972           0 : BKCsave2(void *r, const bat *bid)
     973             : {
     974           0 :         BAT *b;
     975             : 
     976           0 :         (void) r;
     977           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     978           0 :                 throw(MAL, "bat.save", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     979             :         }
     980           0 :         MT_lock_set(&b->theaplock);
     981           0 :         if (!b->batTransient) {
     982           0 :                 MT_lock_unset(&b->theaplock);
     983           0 :                 BBPunfix(b->batCacheid);
     984           0 :                 throw(MAL, "bat.save", "Only save transient columns.");
     985             :         }
     986           0 :         MT_lock_unset(&b->theaplock);
     987             : 
     988           0 :         if (b && BATdirty(b))
     989           0 :                 BBPsave(b);
     990           0 :         BBPunfix(b->batCacheid);
     991           0 :         return MAL_SUCCEED;
     992             : }
     993             : 
     994             : /*
     995             :  * Accelerator Control
     996             :  */
     997             : static str
     998           0 : BKCsetHash(bit *ret, const bat *bid)
     999             : {
    1000           0 :         BAT *b;
    1001             : 
    1002           0 :         (void) ret;
    1003           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1004           0 :                 throw(MAL, "bat.setHash", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1005             :         }
    1006           0 :         *ret = BAThash(b) == GDK_SUCCEED;
    1007           0 :         BBPunfix(b->batCacheid);
    1008           0 :         return MAL_SUCCEED;
    1009             : }
    1010             : 
    1011             : static str
    1012           0 : BKCsetImprints(bit *ret, const bat *bid)
    1013             : {
    1014           0 :         BAT *b;
    1015             : 
    1016           0 :         (void) ret;
    1017           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1018           0 :                 throw(MAL, "bat.setImprints", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1019             :         }
    1020           0 :         *ret = BATimprints(b) == GDK_SUCCEED;
    1021           0 :         BBPunfix(b->batCacheid);
    1022           0 :         return MAL_SUCCEED;
    1023             : }
    1024             : 
    1025             : static str
    1026           0 : BKCgetSequenceBase(oid *r, const bat *bid)
    1027             : {
    1028           0 :         BAT *b;
    1029             : 
    1030           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1031           0 :                 throw(MAL, "bat.setSequenceBase",
    1032             :                           SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1033             :         }
    1034           0 :         *r = b->hseqbase;
    1035           0 :         BBPunfix(b->batCacheid);
    1036           0 :         return MAL_SUCCEED;
    1037             : }
    1038             : 
    1039             : static str
    1040       78201 : BKCmergecand(bat *ret, const bat *aid, const bat *bid)
    1041             : {
    1042       78201 :         BAT *a, *b, *bn;
    1043             : 
    1044       78201 :         if ((a = BATdescriptor(*aid)) == NULL) {
    1045           0 :                 throw(MAL, "bat.mergecand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1046             :         }
    1047       78201 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1048           0 :                 BBPunfix(a->batCacheid);
    1049           0 :                 throw(MAL, "bat.mergecand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1050             :         }
    1051       78198 :         bn = BATmergecand(a, b);
    1052       78190 :         BBPunfix(a->batCacheid);
    1053       78190 :         BBPunfix(b->batCacheid);
    1054       78184 :         if (bn == NULL)
    1055           0 :                 throw(MAL, "bat.mergecand", GDK_EXCEPTION);
    1056       78184 :         *ret = bn->batCacheid;
    1057       78184 :         BBPkeepref(bn);
    1058       78184 :         return MAL_SUCCEED;
    1059             : }
    1060             : 
    1061             : static str
    1062           0 : BKCintersectcand(bat *ret, const bat *aid, const bat *bid)
    1063             : {
    1064           0 :         BAT *a, *b, *bn;
    1065             : 
    1066           0 :         if ((a = BATdescriptor(*aid)) == NULL) {
    1067           0 :                 throw(MAL, "bat.intersectcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1068             :         }
    1069           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1070           0 :                 BBPunfix(a->batCacheid);
    1071           0 :                 throw(MAL, "bat.intersectcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1072             :         }
    1073           0 :         bn = BATintersectcand(a, b);
    1074           0 :         BBPunfix(a->batCacheid);
    1075           0 :         BBPunfix(b->batCacheid);
    1076           0 :         if (bn == NULL)
    1077           0 :                 throw(MAL, "bat.intersectcand", GDK_EXCEPTION);
    1078           0 :         *ret = bn->batCacheid;
    1079           0 :         BBPkeepref(bn);
    1080           0 :         return MAL_SUCCEED;
    1081             : }
    1082             : 
    1083             : static str
    1084           0 : BKCdiffcand(bat *ret, const bat *aid, const bat *bid)
    1085             : {
    1086           0 :         BAT *a, *b, *bn;
    1087             : 
    1088           0 :         if ((a = BATdescriptor(*aid)) == NULL) {
    1089           0 :                 throw(MAL, "bat.diffcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1090             :         }
    1091           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
    1092           0 :                 BBPunfix(a->batCacheid);
    1093           0 :                 throw(MAL, "bat.diffcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
    1094             :         }
    1095           0 :         bn = BATdiffcand(a, b);
    1096           0 :         BBPunfix(a->batCacheid);
    1097           0 :         BBPunfix(b->batCacheid);
    1098           0 :         if (bn == NULL)
    1099           0 :                 throw(MAL, "bat.diffcand", GDK_EXCEPTION);
    1100           0 :         *ret = bn->batCacheid;
    1101           0 :         BBPkeepref(bn);
    1102           0 :         return MAL_SUCCEED;
    1103             : }
    1104             : 
    1105             : #include "mel.h"
    1106             : mel_func bat5_init_funcs[] = {
    1107             :  command("bat", "mirror", BKCmirror, false, "Returns the head-mirror image of a BAT (two head columns).", args(1,2, batarg("",oid),batargany("b",2))),
    1108             :  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))),
    1109             :  command("bat", "delete", BKCdelete_multi, false, "Delete multiple BUN, shifting BUNs up", args(1,3, batargany("",1),batargany("b",1),batarg("d",oid))),
    1110             :  command("bat", "delete", BKCdelete_all, false, "Delete all entries.", args(1,2, batargany("",1),batargany("b",1))),
    1111             :  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))),
    1112             :  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))),
    1113             :  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))),
    1114             :  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))),
    1115             :  command("bat", "append", BKCappend_wrap, false, "append the content of u to i", args(1,3, batargany("",1),batargany("i",1),batargany("u",1))),
    1116             :  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))),
    1117             :  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))),
    1118             :  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))),
    1119             :  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))),
    1120             :  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))),
    1121             :  command("bat", "densebat", BKCdensebat, false, "Creates a new [void,void] BAT of size 'sz'.", args(1,2, batarg("",oid),arg("sz",lng))),
    1122             :  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))),
    1123             :  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))),
    1124             :  command("bat", "getVHeapSize", BKCgetVHeapSize, false, "Calculate the vheap size for varsized bats", args(1,2, arg("",lng),batargany("b",1))),
    1125             :  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))),
    1126             :  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))),
    1127             :  command("bat", "isaKey", BKCgetKey, false, "Return whether the column tail values are unique (key).", args(1,2, arg("",bit),batargany("b",1))),
    1128             :  command("bat", "setAccess", BKCsetAccess, false, "Try to change the update access privileges \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))),
    1129             :  command("bat", "getAccess", BKCgetAccess, false, "Return the access mode attached to this BAT as a character.", args(1,2, arg("",str),batargany("b",1))),
    1130             :  command("bat", "getSequenceBase", BKCgetSequenceBase, false, "Get the sequence base for the void column of a BAT.", args(1,2, arg("",oid),batargany("b",1))),
    1131             :  command("bat", "isSorted", BKCisSorted, false, "Returns true if BAT values are ordered.", args(1,2, arg("",bit),batargany("b",1))),
    1132             :  command("bat", "isSortedReverse", BKCisSortedReverse, false, "Returns true if BAT values are reversely ordered.", args(1,2, arg("",bit),batargany("b",1))),
    1133             :  command("bat", "append", BKCappend_val_wrap, false, "append the value u to i", args(1,3, batargany("",1),batargany("i",1),argany("u",1))),
    1134             :  command("bat", "setName", BKCsetName, false, "Give a logical name to a BAT. ", args(1,3, arg("",void),batargany("b",1),arg("s",str))),
    1135             :  command("bat", "getName", BKCgetBBPname, false, "Gives back the logical name of a BAT.", args(1,2, arg("",str),batargany("b",1))),
    1136             :  command("bat", "isTransient", BKCisTransient, false, "", args(1,2, arg("",bit),batargany("b",1))),
    1137             :  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))),
    1138             :  command("bat", "isPersistent", BKCisPersistent, false, "", args(1,2, arg("",bit),batargany("b",1))),
    1139             :  command("bat", "setPersistent", BKCsetPersistent, false, "Make the BAT persistent.", args(1,2, arg("",void),batargany("b",1))),
    1140             :  command("bat", "save", BKCsave2, false, "", args(1,2, arg("",void),batargany("nme",1))),
    1141             :  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))),
    1142             :  command("bat", "setHash", BKCsetHash, false, "Create a hash structure on the column", args(1,2, arg("",bit),batargany("b",1))),
    1143             :  command("bat", "setImprints", BKCsetImprints, false, "Create an imprints structure on the column", args(1,2, arg("",bit),batargany("b",1))),
    1144             :  command("bat", "isSynced", BKCisSynced, false, "Tests whether two BATs are synced or not. ", args(1,3, arg("",bit),batargany("b1",1),batargany("b2",2))),
    1145             :  command("bat", "mergecand", BKCmergecand, false, "Merge two candidate lists into one", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
    1146             :  command("bat", "intersectcand", BKCintersectcand, false, "Intersect two candidate lists into one", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
    1147             :  command("bat", "diffcand", BKCdiffcand, false, "Calculate difference of two candidate lists", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
    1148             :  { .imp=NULL }
    1149             : };
    1150             : #include "mal_import.h"
    1151             : #ifdef _MSC_VER
    1152             : #undef read
    1153             : #pragma section(".CRT$XCU",read)
    1154             : #endif
    1155         329 : LIB_STARTUP_FUNC(init_bat5_mal)
    1156         329 : { mal_module("bat5", NULL, bat5_init_funcs); }

Generated by: LCOV version 1.14