LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - batExtensions.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 130 171 76.0 %
Date: 2024-10-04 20:04:04 Functions: 8 8 100.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      199660 : CMDBATnew(Client cntxt, MalBlkPtr m, MalStkPtr s, InstrPtr p)
      42             : {
      43      199660 :         int tt;
      44      199660 :         role_t kind = TRANSIENT;
      45      199660 :         BUN cap = 0;
      46      199660 :         bat *res;
      47             : 
      48      199660 :         (void) cntxt;
      49      199660 :         res = getArgReference_bat(s, p, 0);
      50      199660 :         tt = getArgType(m, p, 1);
      51      199660 :         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      199660 :                         kind = PERSISTENT;
      67             :         }
      68             : 
      69      199660 :         if (tt == TYPE_any || isaBatType(tt))
      70           1 :                 throw(MAL, "bat.new", SEMANTIC_TYPE_ERROR);
      71      199659 :         return (str) BKCnewBAT(res, &tt, &cap, kind);
      72             : }
      73             : 
      74             : static str
      75        2294 : CMDBATdup(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      76             : {
      77        2294 :         BAT *b, *i;
      78        2294 :         bat *ret = getArgReference_bat(stk, pci, 0);
      79        2294 :         int tt = getArgType(mb, pci, 1);
      80        2294 :         bat input = *getArgReference_bat(stk, pci, 2);
      81             : 
      82        2294 :         (void) cntxt;
      83        2294 :         if ((i = BBPquickdesc(input)) == NULL)
      84           0 :                 throw(MAL, "bat.new", INTERNAL_BAT_ACCESS);
      85        2294 :         b = COLnew(i->hseqbase, tt, BATcount(i), TRANSIENT);
      86        2294 :         if (b == 0)
      87           0 :                 throw(MAL, "bat.new", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      88        2294 :         *ret = b->batCacheid;
      89        2294 :         BBPretain(b->batCacheid);
      90        2294 :         BBPunfix(b->batCacheid);
      91        2294 :         return MAL_SUCCEED;
      92             : }
      93             : 
      94             : static str
      95       12340 : CMDBATsingle(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      96             : {
      97       12340 :         BAT *b;
      98       12340 :         int *ret = getArgReference_bat(stk, pci, 0);
      99       12340 :         void *u = (void *) getArgReference(stk, pci, 1);
     100             : 
     101       12342 :         (void) cntxt;
     102             : 
     103       12342 :         b = COLnew(0, getArgType(mb, pci, 1), 0, TRANSIENT);
     104       12343 :         if (b == 0)
     105           0 :                 throw(MAL, "bat.single", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     106       12343 :         if (ATOMextern(b->ttype))
     107        3506 :                 u = (ptr) *(ptr *) u;
     108       12343 :         if (BUNappend(b, u, false) != GDK_SUCCEED) {
     109           0 :                 BBPreclaim(b);
     110           0 :                 throw(MAL, "bat.single", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     111             :         }
     112       12337 :         *ret = b->batCacheid;
     113       12337 :         BBPkeepref(b);
     114       12337 :         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      137714 : CMDBATappend_bulk(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     199             : {
     200      137714 :         bat *r = getArgReference_bat(stk, pci, 0),
     201      137714 :                 *bid = getArgReference_bat(stk, pci, 1);
     202      137714 :         bit force = *getArgReference_bit(stk, pci, 2);
     203      137714 :         BAT *b;
     204      137714 :         BUN inputs = (BUN) (pci->argc - 3), number_existing = 0, total = 0;
     205             : 
     206      137714 :         (void) cntxt;
     207      137714 :         if ((b = BATdescriptor(*bid)) == NULL)
     208           0 :                 throw(MAL, "bat.append_bulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     209             : 
     210      137697 :         if (inputs > 0) {
     211      137697 :                 number_existing = BATcount(b);
     212             : 
     213      137697 :                 if (isaBatType(getArgType(mb, pci, 3))) {       /* use BATappend for the bulk case */
     214           0 :                         gdk_return rt;
     215           0 :                         for (int i = 3, args = pci->argc; i < args; i++) {
     216           0 :                                 BAT *d = BATdescriptor(*getArgReference_bat(stk, pci, i));
     217           0 :                                 if (!d) {
     218           0 :                                         BBPunfix(b->batCacheid);
     219           0 :                                         throw(MAL, "bat.append_bulk",
     220             :                                                   SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     221             :                                 }
     222           0 :                                 if (mask_cand(d)) {
     223           0 :                                         BAT *du = d;
     224           0 :                                         d = BATunmask(d);
     225           0 :                                         BBPunfix(du->batCacheid);
     226           0 :                                         if (!d) {
     227           0 :                                                 BBPunfix(b->batCacheid);
     228           0 :                                                 throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     229             :                                         }
     230             :                                 }
     231           0 :                                 rt = BATappend(b, d, NULL, force);
     232           0 :                                 BBPunfix(d->batCacheid);
     233           0 :                                 if (rt != GDK_SUCCEED) {
     234           0 :                                         BBPunfix(b->batCacheid);
     235           0 :                                         throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     236             :                                 }
     237             :                         }
     238             :                 } else {
     239      137697 :                         bool external = ATOMextern(b->ttype);
     240      137697 :                         total = number_existing + inputs;
     241      137697 :                         if (BATextend(b, total) != GDK_SUCCEED) {
     242           0 :                                 BBPunfix(b->batCacheid);
     243           0 :                                 throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     244             :                         }
     245      874770 :                         for (int i = 3, args = pci->argc; i < args; i++) {
     246      737053 :                                 ptr u = getArgReference(stk, pci, i);
     247      734927 :                                 if (external)
     248      143092 :                                         u = (ptr) *(ptr *) u;
     249      734927 :                                 if (BUNappend(b, u, force) != GDK_SUCCEED) {
     250           0 :                                         BBPunfix(b->batCacheid);
     251           0 :                                         throw(MAL, "bat.append_bulk", GDK_EXCEPTION);
     252             :                                 }
     253             :                         }
     254             :                 }
     255             :         }
     256             : 
     257      137717 :         *r = b->batCacheid;
     258      137717 :         BBPretain(b->batCacheid);
     259      137727 :         BBPunfix(b->batCacheid);
     260      137727 :         return MAL_SUCCEED;
     261             : }
     262             : 
     263             : static str
     264           1 : CMDBATvacuum(bat *r, const bat *bid)
     265             : {
     266           1 :         BAT *b, *bn;
     267             : 
     268           1 :         if ((b = BATdescriptor(*bid)) == NULL)
     269           0 :                 throw(MAL, "bat.vacuum", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     270           1 :         if ((bn = COLcopy(b, b->ttype, true, b->batRole)) == NULL) {
     271           0 :                 BBPunfix(b->batCacheid);
     272           0 :                 throw(MAL, "bat.vacuum", GDK_EXCEPTION);
     273             :         }
     274             : 
     275           1 :         *r = bn->batCacheid;
     276           1 :         BBPkeepref(bn);
     277           1 :         BBPunfix(b->batCacheid);
     278           1 :         return MAL_SUCCEED;
     279             : }
     280             : 
     281             : #include "mel.h"
     282             : mel_func batExtensions_init_funcs[] = {
     283             :  pattern("bat", "new", CMDBATnew, false, "", args(1,2, batargany("",1),argany("tt",1))),
     284             :  pattern("bat", "new", CMDBATnew, false, "", args(1,3, batargany("",1),argany("tt",1),arg("size",int))),
     285             :  pattern("bat", "new", CMDBATnew, false, "", args(1,4, batargany("",1),argany("tt",1),arg("size",lng),arg("persist",bit))),
     286             :  pattern("bat", "new", CMDBATnew, false, "", args(1,4, batargany("",1),argany("tt",1),arg("size",int),arg("persist",bit))),
     287             :  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))),
     288             :  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))),
     289             :  pattern("bat", "single", CMDBATsingle, false, "Create a BAT with a single element", args(1,2, batargany("",1),argany("val",1))),
     290             :  pattern("bat", "partition", CMDBATpartition, false, "Create a series of slices over the BAT argument. The BUNs are distributed evenly.", args(1,2, batvarargany("",1),batargany("b",1))),
     291             :  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))),
     292             :  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))),
     293             :  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))),
     294             :  command("bat", "vacuum", CMDBATvacuum, false, "", args(1,2, batarg("",str),batarg("b",str))),
     295             :  { .imp=NULL }
     296             : };
     297             : #include "mal_import.h"
     298             : #ifdef _MSC_VER
     299             : #undef read
     300             : #pragma section(".CRT$XCU",read)
     301             : #endif
     302         323 : LIB_STARTUP_FUNC(init_batExtensions_mal)
     303         323 : { mal_module("batExtensions", NULL, batExtensions_init_funcs); }

Generated by: LCOV version 1.14