LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - batExtensions.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 118 147 80.3 %
Date: 2021-01-13 20:07:21 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * M.L.Kersten
      11             :  * BAT Algebra Extensions
      12             :  * The kernel libraries are unaware of the MAL runtime semantics.
      13             :  * This calls for declaring some operations in the MAL module section
      14             :  * and register them in the kernel modules explicitly.
      15             :  *
      16             :  * A good example of this borderline case are BAT creation operations,
      17             :  * which require a mapping of the type identifier to the underlying
      18             :  * implementation type.
      19             :  *
      20             :  * Another example concerns the (un)pack operations, which direct
      21             :  * access the runtime stack to (push)pull the values needed.
      22             :  */
      23             : #include "monetdb_config.h"
      24             : #include "mal_client.h"
      25             : #include "mal_interpreter.h"
      26             : #include "bat5.h"
      27             : #include "gdk_time.h"
      28             : 
      29             : /*
      30             :  * BAT enhancements
      31             :  * The code to enhance the kernel.
      32             :  */
      33             : 
      34             : static str
      35      122008 : CMDBATnew(Client cntxt, MalBlkPtr m, MalStkPtr s, InstrPtr p){
      36             :         int tt;
      37             :         role_t kind = TRANSIENT;
      38      122008 :         BUN cap = 0;
      39             :         bat *res;
      40             : 
      41             :         (void) cntxt;
      42      122008 :         res = getArgReference_bat(s, p, 0);
      43      122008 :         tt = getArgType(m, p, 1);
      44      122008 :         if (p->argc > 2) {
      45             :                 lng lcap;
      46             : 
      47           3 :                 if (getArgType(m, p, 2) == TYPE_lng)
      48           0 :                         lcap = *getArgReference_lng(s, p, 2);
      49           3 :                 else if (getArgType(m, p, 2) == TYPE_int)
      50           3 :                         lcap = (lng) *getArgReference_int(s, p, 2);
      51             :                 else
      52           0 :                         throw(MAL, "bat.new", ILLEGAL_ARGUMENT " Incorrect type for size");
      53           3 :                 if (lcap < 0)
      54           0 :                         throw(MAL, "bat.new", POSITIVE_EXPECTED);
      55           3 :                 if (lcap > (lng) BUN_MAX)
      56           0 :                         throw(MAL, "bat.new", ILLEGAL_ARGUMENT " Capacity too large");
      57           3 :                 cap = (BUN) lcap;
      58           3 :                 if( p->argc == 4 && getVarConstant(m,getArg(p,3)).val.ival)
      59             :                         kind = PERSISTENT;
      60             :         }
      61             : 
      62      122008 :         if (tt == TYPE_any || isaBatType(tt))
      63           3 :                 throw(MAL, "bat.new", SEMANTIC_TYPE_ERROR);
      64      122005 :         return (str) BKCnewBAT(res,  &tt, &cap, kind);
      65             : }
      66             : 
      67             : static str
      68        4429 : CMDBATsingle(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      69             : {
      70             :         BAT *b;
      71        4429 :         int * ret= getArgReference_bat(stk,pci,0);
      72        4429 :         void *u =(void*) getArgReference(stk,pci,1);
      73             : 
      74             :         (void)cntxt;
      75             : 
      76        4429 :         b = COLnew(0,getArgType(mb,pci,1),0, TRANSIENT);
      77        4429 :         if( b == 0)
      78           0 :                 throw(MAL,"bat.single", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      79        4429 :         if (ATOMextern(b->ttype))
      80         995 :                 u = (ptr) *(str *)u;
      81        4429 :         if (BUNappend(b, u, false) != GDK_SUCCEED) {
      82           0 :                 BBPreclaim(b);
      83           0 :                 throw(MAL, "bat.single", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      84             :         }
      85        4429 :         BBPkeepref(*ret = b->batCacheid);
      86        4429 :         return MAL_SUCCEED;
      87             : }
      88             : 
      89             : /* If the optimizer has not determined the partition bounds we derive one here.  */
      90             : static str
      91           2 : CMDBATpartition(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      92             : {
      93             :         BAT *b,*bn;
      94             :         bat *ret;
      95             :         int i;
      96             :         bat bid;
      97             :         oid lval,hval=0, step;
      98             : 
      99             :         (void) mb;
     100             :         (void) cntxt;
     101           2 :         bid = *getArgReference_bat(stk, pci, pci->retc);
     102             : 
     103           2 :         if ((b = BATdescriptor(bid)) == NULL) {
     104           0 :                 throw(MAL, "bat.partition", INTERNAL_BAT_ACCESS);
     105             :         }
     106           2 :         step = BATcount(b) / pci->retc + 1;
     107             : 
     108             :         /* create the slices slightly overshoot to make sure it all is taken*/
     109           5 :         for(i=0; i<pci->retc; i++){
     110           3 :                 lval = i*step;
     111           3 :                 hval = lval + step;
     112           3 :                 if (i == pci->retc-1)
     113           2 :                         hval = BATcount(b);
     114           3 :                 bn =  BATslice(b, lval,hval);
     115           3 :                 if (bn== NULL){
     116           0 :                         BBPunfix(b->batCacheid);
     117           0 :                         throw(MAL, "bat.partition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     118             :                 }
     119           3 :                 BAThseqbase(bn, lval);
     120           3 :                 stk->stk[getArg(pci,i)].val.bval = bn->batCacheid;
     121             :                 ret= getArgReference_bat(stk,pci,i);
     122           3 :                 BBPkeepref(*ret = bn->batCacheid);
     123             :         }
     124           2 :         BBPunfix(b->batCacheid);
     125           2 :         return MAL_SUCCEED;
     126             : }
     127             : 
     128             : static str
     129           9 : CMDBATpartition2(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     130             : {
     131             :         BAT *b,*bn;
     132             :         bat *ret,bid;
     133           9 :         int pieces= *getArgReference_int(stk, pci, 2);
     134           9 :         int idx = *getArgReference_int(stk, pci, 3);
     135             :         oid lval,hval=0, step;
     136             : 
     137             :         (void) mb;
     138             :         (void) cntxt;
     139           9 :         if ( pieces <=0 )
     140           0 :                 throw(MAL, "bat.partition", POSITIVE_EXPECTED);
     141           9 :         if ( idx >= pieces || idx <0 )
     142           1 :                 throw(MAL, "bat.partition", ILLEGAL_ARGUMENT " Illegal piece index");
     143             : 
     144           8 :         bid = *getArgReference_bat(stk, pci, pci->retc);
     145             : 
     146           8 :         if ((b = BATdescriptor(bid)) == NULL) {
     147           0 :                 throw(MAL, "bat.partition", INTERNAL_BAT_ACCESS);
     148             :         }
     149           8 :         step = BATcount(b) / pieces;
     150             : 
     151           8 :         lval = idx * step;
     152           8 :         if ( idx == pieces-1)
     153             :                 hval = BATcount(b);
     154             :         else
     155           4 :                 hval = lval+step;
     156           8 :         bn =  BATslice(b, lval,hval);
     157           8 :         BAThseqbase(bn, lval + b->hseqbase);
     158           8 :         BBPunfix(b->batCacheid);
     159           8 :         if (bn== NULL){
     160           0 :                 throw(MAL, "bat.partition",  INTERNAL_OBJ_CREATE);
     161             :         }
     162           8 :         ret= getArgReference_bat(stk,pci,0);
     163           8 :         BBPkeepref(*ret = bn->batCacheid);
     164           8 :         return MAL_SUCCEED;
     165             : }
     166             : 
     167             : static str
     168           1 : CMDBATimprints(void *ret, bat *bid)
     169             : {
     170             :         BAT *b;
     171             :         gdk_return r;
     172             : 
     173             :         (void) ret;
     174           1 :         if ((b = BATdescriptor(*bid)) == NULL)
     175           0 :                 throw(MAL, "bat.imprints", INTERNAL_BAT_ACCESS);
     176             : 
     177           1 :         r = BATimprints(b);
     178           1 :         BBPunfix(b->batCacheid);
     179           1 :         if (r != GDK_SUCCEED)
     180           0 :                 throw(MAL, "bat.imprints", GDK_EXCEPTION);
     181             :         return MAL_SUCCEED;
     182             : }
     183             : 
     184             : static str
     185           1 : CMDBATimprintsize(lng *ret, bat *bid)
     186             : {
     187             :         BAT *b;
     188             : 
     189           1 :         if ((b = BATdescriptor(*bid)) == NULL)
     190           0 :                 throw(MAL, "bat.imprints", INTERNAL_BAT_ACCESS);
     191             : 
     192           1 :         *ret = IMPSimprintsize(b);
     193           1 :         BBPunfix(b->batCacheid);
     194           1 :         return MAL_SUCCEED;
     195             : }
     196             : 
     197             : #define append_bulk_imp_fixed_size(TPE, UNION_VAL) \
     198             :         do { \
     199             :                 ValRecord *stack = stk->stk; \
     200             :                 int *argv = pci->argv; \
     201             :                 total = number_existing + inputs; \
     202             :                 if (BATextend(b, total) != GDK_SUCCEED) { \
     203             :                         BBPunfix(b->batCacheid); \
     204             :                         throw(MAL,"bat.append_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     205             :                 } \
     206             :                 if (!b->tsorted && !b->trevsorted) { \
     207             :                         for (int i = 3, args = pci->argc; i < args; i++) { \
     208             :                                 TPE next = stack[argv[i]].val.UNION_VAL; \
     209             :                                 new_nil |= is_##TPE##_nil(next); \
     210             :                                 if (BUNappend(b, &next, force) != GDK_SUCCEED) { \
     211             :                                         BBPunfix(b->batCacheid); \
     212             :                                         throw(MAL,"bat.append_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     213             :                                 } \
     214             :                         } \
     215             :                 } else { \
     216             :                         bool sorted = b->tsorted, revsorted = b->trevsorted; \
     217             :                         TPE prev = stack[argv[3]].val.UNION_VAL; \
     218             :                         new_nil |= is_##TPE##_nil(prev); \
     219             :                         if (number_existing) { \
     220             :                                 TPE last = *(TPE*) Tloc(b, number_existing - 1); \
     221             :                                 sorted &= prev >= last; \
     222             :                                 revsorted &= prev <= last; \
     223             :                         } \
     224             :                         if (BUNappend(b, &prev, force) != GDK_SUCCEED) { \
     225             :                                 BBPunfix(b->batCacheid); \
     226             :                                 throw(MAL,"bat.append_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     227             :                         } \
     228             :                         for (int i = 4, args = pci->argc; i < args; i++) { \
     229             :                                 TPE next = stack[argv[i]].val.UNION_VAL; \
     230             :                                 new_nil |= is_##TPE##_nil(next); \
     231             :                                 sorted &= next >= prev; \
     232             :                                 revsorted &= next <= prev; \
     233             :                                 if (BUNappend(b, &next, force) != GDK_SUCCEED) { \
     234             :                                         BBPunfix(b->batCacheid); \
     235             :                                         throw(MAL,"bat.append_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
     236             :                                 } \
     237             :                         } \
     238             :                         b->tsorted &= sorted; \
     239             :                         b->trevsorted &= revsorted; \
     240             :                 } \
     241             :         } while (0)
     242             : 
     243             : static str
     244        6964 : CMDBATappend_bulk(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     245             : {
     246        6964 :         bat *r = getArgReference_bat(stk, pci, 0), *bid = getArgReference_bat(stk, pci, 1);
     247        6964 :         bit force = *getArgReference_bit(stk, pci, 2), new_nil = 0;
     248             :         BAT *b;
     249        6964 :         BUN inputs = (BUN)(pci->argc - 3), number_existing = 0, total = 0;
     250             : 
     251             :         (void) cntxt;
     252        6964 :         if ((b = BATdescriptor(*bid)) == NULL)
     253           0 :                 throw(MAL, "bat.append_bulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     254             : 
     255        6966 :         if (inputs > 0) {
     256        6966 :                 uint8_t storage = ATOMstorage(b->ttype);
     257        6966 :                 number_existing = BATcount(b);
     258             : 
     259        6966 :                 if (isaBatType(getArgType(mb, pci, 3))) { /* use BATappend for the bulk case */
     260             :                         gdk_return rt;
     261           7 :                         for (int i = 3, args = pci->argc; i < args; i++) {
     262           5 :                                 BAT *d = BATdescriptor(*getArgReference_bat(stk, pci, i));
     263           5 :                                 if (!d) {
     264           0 :                                         BBPunfix(b->batCacheid);
     265           0 :                                         throw(MAL, "bat.append_bulk", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     266             :                                 }
     267           5 :                                 rt = BATappend(b, d, NULL, force);
     268           5 :                                 BBPunfix(d->batCacheid);
     269           5 :                                 if (rt != GDK_SUCCEED) {
     270           0 :                                         BBPunfix(b->batCacheid);
     271           0 :                                         throw(MAL,"bat.append_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     272             :                                 }
     273             :                         }
     274        6964 :                 } else if (b->ttype < TYPE_str && storage == b->ttype) {
     275        4068 :                         switch (b->ttype) {
     276         580 :                         case TYPE_bit:
     277             :                         case TYPE_bte:
     278        1843 :                                 append_bulk_imp_fixed_size(bte, btval);
     279             :                                 break;
     280        1040 :                         case TYPE_sht:
     281        8798 :                                 append_bulk_imp_fixed_size(sht, shval);
     282             :                                 break;
     283        1922 :                         case TYPE_date:
     284             :                         case TYPE_int:
     285      152319 :                                 append_bulk_imp_fixed_size(int, ival);
     286             :                                 break;
     287          93 :                         case TYPE_daytime:
     288             :                         case TYPE_timestamp:
     289             :                         case TYPE_lng:
     290        1091 :                                 append_bulk_imp_fixed_size(lng, lval);
     291             :                                 break;
     292           0 :                         case TYPE_oid:
     293           0 :                                 append_bulk_imp_fixed_size(oid, oval);
     294             :                                 break;
     295          15 :                         case TYPE_flt:
     296          87 :                                 append_bulk_imp_fixed_size(flt, fval);
     297             :                                 break;
     298         416 :                         case TYPE_dbl:
     299        5664 :                                 append_bulk_imp_fixed_size(dbl, dval);
     300             :                                 break;
     301             : #ifdef HAVE_HGE
     302           2 :                         case TYPE_hge:
     303          11 :                                 append_bulk_imp_fixed_size(hge, hval);
     304             :                                 break;
     305             : #endif
     306        4068 :                         default:
     307             :                                 assert(0);
     308             :                         }
     309        4068 :                         BATsetcount(b, total);
     310        4068 :                         if (number_existing == 0) {
     311        4068 :                                 b->tnil = new_nil;
     312        4068 :                                 b->tnonil = !new_nil;
     313             :                         } else {
     314           0 :                                 b->tnil |= new_nil;
     315           0 :                                 b->tnonil &= ~new_nil;
     316             :                         }
     317        4068 :                         b->tkey = BATcount(b) <= 1;
     318             :                 } else { /* non fixed size, use the conventional way */
     319        2896 :                         total = number_existing + inputs;
     320        2896 :                         if (BATextend(b, total) != GDK_SUCCEED) {
     321           0 :                                 BBPunfix(b->batCacheid);
     322           0 :                                 throw(MAL,"bat.append_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     323             :                         }
     324      162162 :                         for (int i = 3, args = pci->argc; i < args; i++) {
     325      159265 :                                 ptr u = getArgReference(stk,pci,i);
     326      159255 :                                 if (storage >= TYPE_str)
     327      116854 :                                         u = (ptr) *(str *) u;
     328      159255 :                                 if (BUNappend(b, u, force) != GDK_SUCCEED) {
     329           0 :                                         BBPunfix(b->batCacheid);
     330           0 :                                         throw(MAL,"bat.append_bulk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     331             :                                 }
     332             :                         }
     333             :                 }
     334             :         }
     335             : 
     336        6967 :         BBPkeepref(*r = b->batCacheid);
     337        6967 :         return MAL_SUCCEED;
     338             : }
     339             : 
     340             : #include "mel.h"
     341             : mel_func batExtensions_init_funcs[] = {
     342             :  pattern("bat", "new", CMDBATnew, false, "", args(1,2, batargany("",1),argany("tt",1))),
     343             :  pattern("bat", "new", CMDBATnew, false, "", args(1,3, batargany("",1),argany("tt",1),arg("size",int))),
     344             :  pattern("bat", "new", CMDBATnew, false, "", args(1,4, batargany("",1),argany("tt",1),arg("size",lng),arg("persist",bit))),
     345             :  pattern("bat", "new", CMDBATnew, false, "", args(1,4, batargany("",1),argany("tt",1),arg("size",int),arg("persist",bit))),
     346             :  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))),
     347             :  pattern("bat", "single", CMDBATsingle, false, "Create a BAT with a single elemenet", args(1,2, batargany("",1),argany("val",1))),
     348             :  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))),
     349             :  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))),
     350             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",bte))),
     351             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",sht))),
     352             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",int))),
     353             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",lng))),
     354             :  command("bat", "imprints", CMDBATimprints, false, "", args(1,2, arg("",void),batarg("b",flt))),
     355             :  command("bat", "imprints", CMDBATimprints, false, "Check for existence or create an imprint index on the BAT.", args(1,2, arg("",void),batarg("b",dbl))),
     356             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",bte))),
     357             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",sht))),
     358             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",int))),
     359             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",lng))),
     360             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",flt))),
     361             :  command("bat", "imprintsize", CMDBATimprintsize, false, "Return the storage size of the imprints index structure.", args(1,2, arg("",lng),batarg("b",dbl))),
     362             : #ifdef HAVE_HGE
     363             :  command("bat", "imprints", CMDBATimprints, false, "", args(0,1, batarg("b",hge))),
     364             :  command("bat", "imprintsize", CMDBATimprintsize, false, "", args(1,2, arg("",lng),batarg("b",hge))),
     365             : #endif
     366             :  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))),
     367             :  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))),
     368             :  { .imp=NULL }
     369             : };
     370             : #include "mal_import.h"
     371             : #ifdef _MSC_VER
     372             : #undef read
     373             : #pragma section(".CRT$XCU",read)
     374             : #endif
     375         255 : LIB_STARTUP_FUNC(init_batExtensions_mal)
     376         255 : { mal_module("batExtensions", NULL, batExtensions_init_funcs); }

Generated by: LCOV version 1.14