LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - batExtensions.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 137 188 72.9 %
Date: 2024-04-26 00:35:57 Functions: 9 10 90.0 %

          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             :  * M.L.Kersten
      15             :  * BAT Algebra Extensions
      16             :  * The kernel libraries are unaware of the MAL runtime semantics.
      17             :  * This calls for declaring some operations in the MAL module section
      18             :  * and register them in the kernel modules explicitly.
      19             :  *
      20             :  * A good example of this borderline case are BAT creation operations,
      21             :  * which require a mapping of the type identifier to the underlying
      22             :  * implementation type.
      23             :  *
      24             :  * Another example concerns the (un)pack operations, which direct
      25             :  * access the runtime stack to (push)pull the values needed.
      26             :  */
      27             : #include "monetdb_config.h"
      28             : #include "mal_client.h"
      29             : #include "mal_interpreter.h"
      30             : #include "bat5.h"
      31             : #include "gdk_time.h"
      32             : #include "mal_instruction.h"
      33             : #include "mal_exception.h"
      34             : 
      35             : /*
      36             :  * BAT enhancements
      37             :  * The code to enhance the kernel.
      38             :  */
      39             : 
      40             : static str
      41      200292 : CMDBATnew(Client cntxt, MalBlkPtr m, MalStkPtr s, InstrPtr p)
      42             : {
      43      200292 :         int tt;
      44      200292 :         role_t kind = TRANSIENT;
      45      200292 :         BUN cap = 0;
      46      200292 :         bat *res;
      47             : 
      48      200292 :         (void) cntxt;
      49      200292 :         res = getArgReference_bat(s, p, 0);
      50      200292 :         tt = getArgType(m, p, 1);
      51      200292 :         if (p->argc > 2) {
      52           2 :                 lng lcap;
      53             : 
      54           2 :                 if (getArgType(m, p, 2) == TYPE_lng)
      55           0 :                         lcap = *getArgReference_lng(s, p, 2);
      56           2 :                 else if (getArgType(m, p, 2) == TYPE_int)
      57           2 :                         lcap = (lng) *getArgReference_int(s, p, 2);
      58             :                 else
      59           0 :                         throw(MAL, "bat.new", ILLEGAL_ARGUMENT " Incorrect type for size");
      60           2 :                 if (lcap < 0)
      61           0 :                         throw(MAL, "bat.new", POSITIVE_EXPECTED);
      62           2 :                 if (lcap > (lng) BUN_MAX)
      63           0 :                         throw(MAL, "bat.new", ILLEGAL_ARGUMENT " Capacity too large");
      64           2 :                 cap = (BUN) lcap;
      65           2 :                 if (p->argc == 4 && getVarConstant(m, getArg(p, 3)).val.ival)
      66      200292 :                         kind = PERSISTENT;
      67             :         }
      68             : 
      69      200292 :         if (tt == TYPE_any || isaBatType(tt))
      70           0 :                 throw(MAL, "bat.new", SEMANTIC_TYPE_ERROR);
      71      202915 :         return (str) BKCnewBAT(res, &tt, &cap, kind);
      72             : }
      73             : 
      74             : static str
      75         834 : CMDBATdup(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      76             : {
      77         834 :         BAT *b, *i;
      78         834 :         bat *ret = getArgReference_bat(stk, pci, 0);
      79         834 :         int tt = getArgType(mb, pci, 1);
      80         834 :         bat input = *getArgReference_bat(stk, pci, 2);
      81             : 
      82         834 :         (void) cntxt;
      83         834 :         if ((i = BBPquickdesc(input)) == NULL)
      84           0 :                 throw(MAL, "bat.new", INTERNAL_BAT_ACCESS);
      85         834 :         b = COLnew(i->hseqbase, tt, BATcount(i), TRANSIENT);
      86         834 :         if (b == 0)
      87           0 :                 throw(MAL, "bat.new", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      88         834 :         *ret = b->batCacheid;
      89         834 :         BBPretain(b->batCacheid);
      90         834 :         BBPunfix(b->batCacheid);
      91         834 :         return MAL_SUCCEED;
      92             : }
      93             : 
      94             : static str
      95        7402 : CMDBATsingle(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      96             : {
      97        7402 :         BAT *b;
      98        7402 :         int *ret = getArgReference_bat(stk, pci, 0);
      99        7402 :         void *u = (void *) getArgReference(stk, pci, 1);
     100             : 
     101        7425 :         (void) cntxt;
     102             : 
     103        7425 :         b = COLnew(0, getArgType(mb, pci, 1), 0, TRANSIENT);
     104        7821 :         if (b == 0)
     105           0 :                 throw(MAL, "bat.single", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     106        7821 :         if (ATOMextern(b->ttype))
     107        1803 :                 u = (ptr) *(ptr *) u;
     108        7821 :         if (BUNappend(b, u, false) != GDK_SUCCEED) {
     109           0 :                 BBPreclaim(b);
     110           0 :                 throw(MAL, "bat.single", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     111             :         }
     112        7710 :         *ret = b->batCacheid;
     113        7710 :         BBPkeepref(b);
     114        7710 :         return MAL_SUCCEED;
     115             : }
     116             : 
     117             : /* If the optimizer has not determined the partition bounds we derive one here.  */
     118             : static str
     119           2 : CMDBATpartition(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     120             : {
     121           2 :         BAT *b, *bn;
     122           2 :         bat *ret;
     123           2 :         int i;
     124           2 :         bat bid;
     125           2 :         oid lval, hval = 0, step;
     126             : 
     127           2 :         (void) mb;
     128           2 :         (void) cntxt;
     129           2 :         bid = *getArgReference_bat(stk, pci, pci->retc);
     130             : 
     131           2 :         if ((b = BATdescriptor(bid)) == NULL) {
     132           0 :                 throw(MAL, "bat.partition", INTERNAL_BAT_ACCESS);
     133             :         }
     134           2 :         step = BATcount(b) / pci->retc + 1;
     135             : 
     136             :         /* create the slices slightly overshoot to make sure it all is taken */
     137           5 :         for (i = 0; i < pci->retc; i++) {
     138           3 :                 lval = i * step;
     139           3 :                 hval = lval + step;
     140           3 :                 if (i == pci->retc - 1)
     141           2 :                         hval = BATcount(b);
     142           3 :                 bn = BATslice(b, lval, hval);
     143           3 :                 if (bn == NULL) {
     144           0 :                         BBPunfix(b->batCacheid);
     145           0 :                         throw(MAL, "bat.partition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     146             :                 }
     147           3 :                 BAThseqbase(bn, lval);
     148           3 :                 stk->stk[getArg(pci, i)].val.bval = bn->batCacheid;
     149           3 :                 ret = getArgReference_bat(stk, pci, i);
     150           3 :                 *ret = bn->batCacheid;
     151           3 :                 BBPkeepref(bn);
     152             :         }
     153           2 :         BBPunfix(b->batCacheid);
     154           2 :         return MAL_SUCCEED;
     155             : }
     156             : 
     157             : static str
     158           9 : CMDBATpartition2(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     159             : {
     160           9 :         BAT *b, *bn;
     161           9 :         bat *ret, bid;
     162           9 :         int pieces = *getArgReference_int(stk, pci, 2);
     163           9 :         int idx = *getArgReference_int(stk, pci, 3);
     164           9 :         oid lval, hval = 0, step;
     165             : 
     166           9 :         (void) mb;
     167           9 :         (void) cntxt;
     168           9 :         if (pieces <= 0)
     169           0 :                 throw(MAL, "bat.partition", POSITIVE_EXPECTED);
     170           9 :         if (idx >= pieces || idx < 0)
     171           1 :                 throw(MAL, "bat.partition", ILLEGAL_ARGUMENT " Illegal piece index");
     172             : 
     173           8 :         bid = *getArgReference_bat(stk, pci, pci->retc);
     174             : 
     175           8 :         if ((b = BATdescriptor(bid)) == NULL) {
     176           0 :                 throw(MAL, "bat.partition", INTERNAL_BAT_ACCESS);
     177             :         }
     178           8 :         step = BATcount(b) / pieces;
     179             : 
     180           8 :         lval = idx * step;
     181           8 :         if (idx == pieces - 1)
     182             :                 hval = BATcount(b);
     183             :         else
     184           4 :                 hval = lval + step;
     185           8 :         bn = BATslice(b, lval, hval);
     186           8 :         BAThseqbase(bn, lval + b->hseqbase);
     187           8 :         BBPunfix(b->batCacheid);
     188           8 :         if (bn == NULL) {
     189           0 :                 throw(MAL, "bat.partition", INTERNAL_OBJ_CREATE);
     190             :         }
     191           8 :         ret = getArgReference_bat(stk, pci, 0);
     192           8 :         *ret = bn->batCacheid;
     193           8 :         BBPkeepref(bn);
     194           8 :         return MAL_SUCCEED;
     195             : }
     196             : 
     197             : static str
     198           1 : CMDBATimprints(void *ret, bat *bid)
     199             : {
     200           1 :         BAT *b;
     201           1 :         gdk_return r;
     202             : 
     203           1 :         (void) ret;
     204           1 :         if ((b = BATdescriptor(*bid)) == NULL)
     205           0 :                 throw(MAL, "bat.imprints", INTERNAL_BAT_ACCESS);
     206             : 
     207           1 :         r = BATimprints(b);
     208           1 :         BBPunfix(b->batCacheid);
     209           1 :         if (r != GDK_SUCCEED)
     210           0 :                 throw(MAL, "bat.imprints", GDK_EXCEPTION);
     211             :         return MAL_SUCCEED;
     212             : }
     213             : 
     214             : static str
     215           0 : CMDBATimprintsize(lng *ret, bat *bid)
     216             : {
     217           0 :         BAT *b;
     218             : 
     219           0 :         if ((b = BATdescriptor(*bid)) == NULL)
     220           0 :                 throw(MAL, "bat.imprints", INTERNAL_BAT_ACCESS);
     221             : 
     222           0 :         *ret = IMPSimprintsize(b);
     223           0 :         BBPunfix(b->batCacheid);
     224           0 :         return MAL_SUCCEED;
     225             : }
     226             : 
     227             : static str
     228      136759 : CMDBATappend_bulk(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     229             : {
     230      136759 :         bat *r = getArgReference_bat(stk, pci, 0),
     231      136759 :                 *bid = getArgReference_bat(stk, pci, 1);
     232      136759 :         bit force = *getArgReference_bit(stk, pci, 2);
     233      136759 :         BAT *b;
     234      136759 :         BUN inputs = (BUN) (pci->argc - 3), number_existing = 0, total = 0;
     235             : 
     236      136759 :         (void) cntxt;
     237      136759 :         if ((b = BATdescriptor(*bid)) == NULL)
     238           0 :                 throw(MAL, "bat.append_bulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     239             : 
     240      137210 :         if (inputs > 0) {
     241      137210 :                 number_existing = BATcount(b);
     242             : 
     243      137210 :                 if (isaBatType(getArgType(mb, pci, 3))) {       /* use BATappend for the bulk case */
     244           0 :                         gdk_return rt;
     245           0 :                         for (int i = 3, args = pci->argc; i < args; i++) {
     246           0 :                                 BAT *d = BATdescriptor(*getArgReference_bat(stk, pci, i));
     247           0 :                                 if (!d) {
     248           0 :                                         BBPunfix(b->batCacheid);
     249           0 :                                         throw(MAL, "bat.append_bulk",
     250             :                                                   SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     251             :                                 }
     252           0 :                                 if (mask_cand(d)) {
     253           0 :                                         BAT *du = d;
     254           0 :                                         d = BATunmask(d);
     255           0 :                                         BBPunfix(du->batCacheid);
     256           0 :                                         if (!d) {
     257           0 :                                                 BBPunfix(b->batCacheid);
     258           0 :                                                 throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     259             :                                         }
     260             :                                 }
     261           0 :                                 rt = BATappend(b, d, NULL, force);
     262           0 :                                 BBPunfix(d->batCacheid);
     263           0 :                                 if (rt != GDK_SUCCEED) {
     264           0 :                                         BBPunfix(b->batCacheid);
     265           0 :                                         throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     266             :                                 }
     267             :                         }
     268             :                 } else {
     269      137210 :                         bool external = ATOMextern(b->ttype);
     270      137210 :                         total = number_existing + inputs;
     271      137210 :                         if (BATextend(b, total) != GDK_SUCCEED) {
     272           0 :                                 BBPunfix(b->batCacheid);
     273           0 :                                 throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     274             :                         }
     275      660148 :                         for (int i = 3, args = pci->argc; i < args; i++) {
     276      523194 :                                 ptr u = getArgReference(stk, pci, i);
     277      522738 :                                 if (external)
     278       94639 :                                         u = (ptr) *(ptr *) u;
     279      522738 :                                 if (BUNappend(b, u, force) != GDK_SUCCEED) {
     280           0 :                                         BBPunfix(b->batCacheid);
     281           0 :                                         throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     282             :                                 }
     283             :                         }
     284             :                 }
     285             :         }
     286             : 
     287      136954 :         *r = b->batCacheid;
     288      136954 :         BBPretain(b->batCacheid);
     289      137085 :         BBPunfix(b->batCacheid);
     290      137085 :         return MAL_SUCCEED;
     291             : }
     292             : 
     293             : static str
     294           1 : CMDBATvacuum(bat *r, const bat *bid)
     295             : {
     296           1 :         BAT *b, *bn;
     297             : 
     298           1 :         if ((b = BATdescriptor(*bid)) == NULL)
     299           0 :                 throw(MAL, "bat.vacuum", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     300           1 :         if ((bn = COLcopy(b, b->ttype, true, b->batRole)) == NULL) {
     301           0 :                 BBPunfix(b->batCacheid);
     302           0 :                 throw(MAL, "bat.vacuum", GDK_EXCEPTION);
     303             :         }
     304             : 
     305           1 :         *r = bn->batCacheid;
     306           1 :         BBPkeepref(bn);
     307           1 :         BBPunfix(b->batCacheid);
     308           1 :         return MAL_SUCCEED;
     309             : }
     310             : 
     311             : #include "mel.h"
     312             : mel_func batExtensions_init_funcs[] = {
     313             :  pattern("bat", "new", CMDBATnew, false, "", args(1,2, batargany("",1),argany("tt",1))),
     314             :  pattern("bat", "new", CMDBATnew, false, "", args(1,3, batargany("",1),argany("tt",1),arg("size",int))),
     315             :  pattern("bat", "new", CMDBATnew, false, "", args(1,4, batargany("",1),argany("tt",1),arg("size",lng),arg("persist",bit))),
     316             :  pattern("bat", "new", CMDBATnew, false, "", args(1,4, batargany("",1),argany("tt",1),arg("size",int),arg("persist",bit))),
     317             :  pattern("bat", "new", CMDBATnew, false, "Creates a new empty transient BAT, with tail-types as indicated.", args(1,3, batargany("",1),argany("tt",1),arg("size",lng))),
     318             :  pattern("bat", "new", CMDBATdup, false, "Creates a new empty transient BAT, with tail-type tt and hseqbase and size from the input bat argument.", args(1,3, batargany("",1), argany("tt",1),batargany("i",2))),
     319             :  pattern("bat", "single", CMDBATsingle, false, "Create a BAT with a single elemenet", args(1,2, batargany("",1),argany("val",1))),
     320             :  pattern("bat", "partition", CMDBATpartition, false, "Create a serie of slices over the BAT argument. The BUNs are distributed evenly.", args(1,2, batvarargany("",1),batargany("b",1))),
     321             :  pattern("bat", "partition", CMDBATpartition2, false, "Create the n-th slice over the BAT broken into several pieces.", args(1,4, batargany("",1),batargany("b",1),arg("pieces",int),arg("n",int))),
     322             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",bte))),
     323             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",sht))),
     324             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",int))),
     325             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",lng))),
     326             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",flt))),
     327             :  command("bat", "imprints", CMDBATimprints, false, "Check for existence or create an imprint index on the BAT.", args(1,2, arg("",void),batarg("b",dbl))),
     328             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",bte))),
     329             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",sht))),
     330             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",int))),
     331             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",lng))),
     332             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",flt))),
     333             :  command("bat", "imprintsize", CMDBATimprintsize, false, "Return the storage size of the imprints index structure.", args(1,2, arg("",lng),batarg("b",dbl))),
     334             : #ifdef HAVE_HGE
     335             :  command("bat", "imprints", CMDBATimprints, false, "", args(0,1, batarg("b",hge))),
     336             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",hge))),
     337             : #endif
     338             :  pattern("bat", "appendBulk", CMDBATappend_bulk, false, "append the arguments ins to i", args(1,4, batargany("",1), batargany("i",1),arg("force",bit),varargany("ins",1))),
     339             :  pattern("bat", "appendBulk", CMDBATappend_bulk, false, "append the arguments ins to i", args(1,4, batargany("",1), batargany("i",1),arg("force",bit),batvarargany("ins",1))),
     340             :  command("bat", "vacuum", CMDBATvacuum, false, "", args(1,2, batarg("",str),batarg("b",str))),
     341             :  { .imp=NULL }
     342             : };
     343             : #include "mal_import.h"
     344             : #ifdef _MSC_VER
     345             : #undef read
     346             : #pragma section(".CRT$XCU",read)
     347             : #endif
     348         334 : LIB_STARTUP_FUNC(init_batExtensions_mal)
     349         334 : { mal_module("batExtensions", NULL, batExtensions_init_funcs); }

Generated by: LCOV version 1.14