LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - mat.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 79 130 60.8 %
Date: 2021-10-13 02:24:04 Functions: 5 5 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             :  * Martin Kersten
      11             :  * Multiple association tables
      12             :  * A MAT is a convenient way to deal represent horizontal fragmented
      13             :  * tables. It combines the definitions of several, type compatible
      14             :  * BATs under a single name.
      15             :  * It is produced by the mitosis optimizer and the operations
      16             :  * are the target of the mergetable optimizer.
      17             :  *
      18             :  * The MAT is materialized when the operations
      19             :  * can not deal with the components individually,
      20             :  * or the incremental operation is not supported.
      21             :  * Normally all mat.new() operations are removed by the
      22             :  * mergetable optimizer.
      23             :  * In case a mat.new() is retained in the code, then it will
      24             :  * behave as a mat.pack();
      25             :  *
      26             :  * The primitives below are chosen to accomodate the SQL
      27             :  * front-end to produce reasonable efficient code.
      28             :  */
      29             : #include "monetdb_config.h"
      30             : #include "mal_resolve.h"
      31             : #include "mal_exception.h"
      32             : #include "mal_interpreter.h"
      33             : 
      34             : /*
      35             :  * The pack is an ordinary multi BAT insert. Oid synchronistion
      36             :  * between pieces should be ensured by the code generators.
      37             :  * The pack operation could be quite expensive, because it
      38             :  * may create a really large BAT.
      39             :  * The slice over a mat helps to avoid constructing intermediates
      40             :  * that are subsequently reduced.
      41             :  * Contrary to most operations, NIL arguments are skipped and
      42             :  * do not produce RUNTIME_OBJECT_MISSING.
      43             :  */
      44             : static str
      45         709 : MATpackInternal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
      46             : {
      47             :         int i;
      48         709 :         bat *ret = getArgReference_bat(stk,p,0);
      49             :         BAT *b, *bn;
      50             :         BUN cap = 0;
      51             :         int tt = TYPE_any;
      52         709 :         int rt = getArgType(mb, p, 0), unmask = 0;
      53             :         (void) cntxt;
      54             : 
      55        4928 :         for (i = 1; i < p->argc; i++) {
      56        4221 :                 bat bid = stk->stk[getArg(p,i)].val.bval;
      57        4221 :                 b = BBPquickdesc(bid);
      58        4219 :                 if( b ){
      59        4219 :                         if (tt == TYPE_any)
      60         709 :                                 tt = b->ttype;
      61        4219 :                         if ((tt != TYPE_void && b->ttype != TYPE_void && b->ttype != TYPE_msk) && tt != b->ttype)
      62           0 :                                 throw(MAL, "mat.pack", "incompatible arguments");
      63        4219 :                         cap += BATcount(b);
      64             :                 }
      65             :         }
      66         707 :         if (tt == TYPE_any){
      67           0 :                 *ret = bat_nil;
      68           0 :                 return MAL_SUCCEED;
      69             :         }
      70             : 
      71         707 :         if (tt == TYPE_msk && rt == newBatType(TYPE_oid)) {
      72             :                 tt = TYPE_oid;
      73             :                 unmask = 1;
      74             :         }
      75         707 :         bn = COLnew(0, tt, cap, TRANSIENT);
      76         709 :         if (bn == NULL)
      77           0 :                 throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      78             : 
      79        4961 :         for (i = 1; i < p->argc; i++) {
      80        4252 :                 if (!(b = BATdescriptor(stk->stk[getArg(p,i)].val.ival))) {
      81           0 :                         BBPreclaim(bn);
      82           0 :                         throw(MAL, "mat.pack", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      83             :                 }
      84        4249 :                 if ((unmask && b->ttype == TYPE_msk) || mask_cand(b)) {
      85             :                         BAT *ob = b;
      86           0 :                         b = BATunmask(b);
      87           0 :                         BBPunfix(ob->batCacheid);
      88           0 :                         if (!b) {
      89           0 :                                 BBPreclaim(bn);
      90           0 :                                 throw(MAL, "mat.pack", GDK_EXCEPTION);
      91             :                         }
      92             :                 }
      93        4249 :                 if (BATcount(bn) == 0) {
      94         706 :                         BAThseqbase(bn, b->hseqbase);
      95         709 :                         BATtseqbase(bn, b->tseqbase);
      96             :                 }
      97        4252 :                 if (BATappend(bn, b, NULL, false) != GDK_SUCCEED) {
      98           0 :                         BBPreclaim(bn);
      99           0 :                         BBPunfix(b->batCacheid);
     100           0 :                         throw(MAL, "mat.pack", GDK_EXCEPTION);
     101             :                 }
     102        4251 :                 BBPunfix(b->batCacheid);
     103             :         }
     104         709 :         if (bn->tnil && bn->tnonil) {
     105           0 :                 BBPreclaim(bn);
     106           0 :                 throw(MAL, "mat.pack", "INTERNAL ERROR" "bn->tnil or  bn->tnonil fails ");
     107             :         }
     108         709 :         BBPkeepref(*ret = bn->batCacheid);
     109         709 :         return MAL_SUCCEED;
     110             : }
     111             : 
     112             : /*
     113             :  * Enable incremental packing. The SQL front-end requires
     114             :  * fixed oid sequences.
     115             :  */
     116             : static str
     117      975320 : MATpackIncrement(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
     118             : {
     119      975320 :         bat *ret = getArgReference_bat(stk,p,0);
     120             :         int     pieces;
     121             :         BAT *b, *bb, *bn;
     122             :         size_t newsize;
     123             : 
     124             :         (void) cntxt;
     125      975320 :         b = BATdescriptor( stk->stk[getArg(p,1)].val.ival);
     126      975161 :         if ( b == NULL)
     127           0 :                 throw(MAL, "mat.pack", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     128             : 
     129      975161 :         if ( getArgType(mb,p,2) == TYPE_int){
     130             :                 /* first step, estimate with some slack */
     131      242458 :                 pieces = stk->stk[getArg(p,2)].val.ival;
     132      242458 :                 int tt = ATOMtype(b->ttype);
     133      242458 :                 if (b->ttype == TYPE_msk)
     134             :                         tt = TYPE_oid;
     135      242458 :                 bn = COLnew(b->hseqbase, tt, (BUN)(1.2 * BATcount(b) * pieces), TRANSIENT);
     136      242453 :                 if (bn == NULL) {
     137           0 :                         BBPunfix(b->batCacheid);
     138           0 :                         throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     139             :                 }
     140             :                 /* allocate enough space for the vheap, but not for strings,
     141             :                  * since BATappend does clever things for strings */
     142      242453 :                 if ( b->tvheap && bn->tvheap && ATOMstorage(b->ttype) != TYPE_str){
     143          54 :                         newsize =  b->tvheap->size * pieces;
     144          54 :                         if (HEAPextend(bn->tvheap, newsize, true) != GDK_SUCCEED) {
     145           0 :                                 BBPunfix(b->batCacheid);
     146           0 :                                 BBPreclaim(bn);
     147           0 :                                 throw(MAL, "mat.pack", GDK_EXCEPTION);
     148             :                         }
     149             :                 }
     150      242453 :                 BATtseqbase(bn, b->tseqbase);
     151      242459 :                 if (b->ttype == TYPE_msk || mask_cand(b)) {
     152             :                         BAT *ob = b;
     153           0 :                         b = BATunmask(b);
     154           0 :                         BBPunfix(ob->batCacheid);
     155           0 :                         if (!b) {
     156           0 :                                 BBPreclaim(bn);
     157           0 :                                 throw(MAL, "mat.pack", GDK_EXCEPTION);
     158             :                         }
     159             :                 }
     160      242459 :                 if (BATappend(bn, b, NULL, false) != GDK_SUCCEED) {
     161           0 :                         BBPreclaim(bn);
     162           0 :                         BBPunfix(b->batCacheid);
     163           0 :                         throw(MAL, "mat.pack", GDK_EXCEPTION);
     164             :                 }
     165      242461 :                 bn->unused = (pieces-1); /* misuse "unused" field */
     166      242461 :                 BATsettrivprop(bn);
     167      242455 :                 BBPunfix(b->batCacheid);
     168      242461 :                 if (bn->tnil && bn->tnonil) {
     169           0 :                         BBPreclaim(bn);
     170           0 :                         throw(MAL, "mat.pack", "INTERNAL ERROR" " bn->tnil %d bn->tnonil %d", bn->tnil, bn->tnonil);
     171             :                 }
     172      242461 :                 *ret = bn->batCacheid;
     173      242461 :                 BBPretain(bn->batCacheid);
     174      242454 :                 BBPunfix(bn->batCacheid);
     175             :         } else {
     176             :                 /* remaining steps */
     177      732703 :                 if (!(bb = BATdescriptor(stk->stk[getArg(p,2)].val.ival))) {
     178           0 :                         BBPunfix(b->batCacheid);
     179           0 :                         throw(MAL, "mat.pack", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     180             :                 }
     181      732724 :                 if (bb->ttype == TYPE_msk || mask_cand(bb)) {
     182             :                         BAT *obb = bb;
     183           0 :                         bb = BATunmask(bb);
     184           0 :                         BBPunfix(obb->batCacheid);
     185           0 :                         if (!bb) {
     186           0 :                                 BBPunfix(b->batCacheid);
     187           0 :                                 throw(MAL, "mat.pack", GDK_EXCEPTION);
     188             :                         }
     189             :                 }
     190      732724 :                 if (BATcount(b) == 0) {
     191      470701 :                         BAThseqbase(b, bb->hseqbase);
     192      470735 :                         BATtseqbase(b, bb->tseqbase);
     193             :                 }
     194      732671 :                 if (BATappend(b, bb, NULL, false) != GDK_SUCCEED) {
     195           0 :                         BBPunfix(bb->batCacheid);
     196           0 :                         BBPunfix(b->batCacheid);
     197           0 :                         throw(MAL, "mat.pack", GDK_EXCEPTION);
     198             :                 }
     199      732813 :                 BBPunfix(bb->batCacheid);
     200      732674 :                 b->unused--;
     201      732674 :                 if (b->unused == 0 && (b = BATsetaccess(b, BAT_READ)) == NULL)
     202           0 :                         throw(MAL, "mat.pack", GDK_EXCEPTION);
     203      732644 :                 if (b->tnil && b->tnonil) {
     204           0 :                         BBPunfix(b->batCacheid);
     205           0 :                         throw(MAL, "mat.pack", "INTERNAL ERROR" " b->tnil or  b->tnonil fails ");
     206             :                 }
     207      732644 :                 *ret = b->batCacheid;
     208      732644 :                 BATsettrivprop(b);
     209      732543 :                 BBPretain(b->batCacheid);
     210      732751 :                 BBPunfix(b->batCacheid);
     211             :         }
     212             :         return MAL_SUCCEED;
     213             : }
     214             : 
     215             : static str
     216         709 : MATpack(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
     217             : {
     218         709 :         return MATpackInternal(cntxt,mb,stk,p);
     219             : }
     220             : 
     221             : static str
     222      251988 : MATpackValues(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
     223             : {
     224             :         int i, type, first = 1;
     225             :         bat *ret;
     226             :         BAT *bn;
     227             : 
     228             :         (void) cntxt;
     229      251988 :         type = getArgType(mb,p,first);
     230      251988 :         bn = COLnew(0, type, p->argc, TRANSIENT);
     231      251926 :         if( bn == NULL)
     232           0 :                 throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     233             : 
     234      251926 :         if (ATOMextern(type)) {
     235      807700 :                 for(i = first; i < p->argc; i++)
     236      658041 :                         if (BUNappend(bn, stk->stk[getArg(p,i)].val.pval, false) != GDK_SUCCEED)
     237           0 :                                 goto bailout;
     238             :         } else {
     239      553919 :                 for(i = first; i < p->argc; i++)
     240      451844 :                         if (BUNappend(bn, getArgReference(stk, p, i), false) != GDK_SUCCEED)
     241           0 :                                 goto bailout;
     242             :         }
     243      251734 :         ret= getArgReference_bat(stk,p,0);
     244      251734 :         BBPkeepref(*ret = bn->batCacheid);
     245      251899 :         return MAL_SUCCEED;
     246           0 :   bailout:
     247           0 :         BBPreclaim(bn);
     248           0 :         throw(MAL, "mat.pack", GDK_EXCEPTION);
     249             : }
     250             : 
     251             : #include "mel.h"
     252             : mel_func mat_init_funcs[] = {
     253             :  pattern("mat", "new", MATpack, false, "Define a Merge Association Table (MAT). Fall back to the pack operation\nwhen this is called ", args(1,2, batargany("",2),batvarargany("b",2))),
     254             :  pattern("bat", "pack", MATpackValues, false, "Materialize the values into a BAT. Avoiding a clash with mat.pack() in mergetable", args(1,2, batargany("",2),varargany("",2))),
     255             :  pattern("mat", "pack", MATpackValues, false, "Materialize the MAT (of values) into a BAT", args(1,2, batargany("",2),varargany("",2))),
     256             :  pattern("mat", "pack", MATpack, false, "Materialize the MAT into a BAT", args(1,2, batargany("",2),batvarargany("b",2))),
     257             :  pattern("mat", "packIncrement", MATpackIncrement, false, "Prepare incremental mat pack", args(1,3, batargany("",2),batargany("b",2),arg("pieces",int))),
     258             :  pattern("mat", "packIncrement", MATpackIncrement, false, "Prepare incremental mat pack", args(1,3, batargany("",2),batargany("b",2),batargany("c",2))),
     259             :  { .imp=NULL }
     260             : };
     261             : #include "mal_import.h"
     262             : #ifdef _MSC_VER
     263             : #undef read
     264             : #pragma section(".CRT$XCU",read)
     265             : #endif
     266         259 : LIB_STARTUP_FUNC(init_mat_mal)
     267         259 : { mal_module("mat", NULL, mat_init_funcs); }

Generated by: LCOV version 1.14