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

Generated by: LCOV version 1.14