LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - mat.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 45 68 66.2 %
Date: 2021-01-13 20:07:21 Functions: 4 4 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             : MATpackInternal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
      46             : {
      47             :         int i;
      48             :         bat *ret = getArgReference_bat(stk,p,0);
      49             :         BAT *b, *bn;
      50             :         BUN cap = 0;
      51             :         int tt = TYPE_any;
      52             :         (void) cntxt;
      53             :         (void) mb;
      54             : 
      55             :         for (i = 1; i < p->argc; i++) {
      56             :                 bat bid = stk->stk[getArg(p,i)].val.bval;
      57             :                 b = BBPquickdesc(bid, false);
      58             :                 if( b ){
      59             :                         if (tt == TYPE_any)
      60             :                                 tt = b->ttype;
      61             :                         if ((tt != TYPE_void && b->ttype != TYPE_void) && tt != b->ttype)
      62             :                                 throw(MAL, "mat.pack", "incompatible arguments");
      63             :                         cap += BATcount(b);
      64             :                 }
      65             :         }
      66             :         if (tt == TYPE_any){
      67             :                 *ret = bat_nil;
      68             :                 return MAL_SUCCEED;
      69             :         }
      70             : 
      71             :         bn = COLnew(0, tt, cap, TRANSIENT);
      72             :         if (bn == NULL)
      73             :                 throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      74             : 
      75             :         for (i = 1; i < p->argc; i++) {
      76             :                 b = BATdescriptor(stk->stk[getArg(p,i)].val.ival);
      77             :                 if( b ){
      78             :                         if (BATcount(bn) == 0) {
      79             :                                 BAThseqbase(bn, b->hseqbase);
      80             :                                 BATtseqbase(bn, b->tseqbase);
      81             :                         }
      82             :                         if (BATappend(bn, b, NULL, false) != GDK_SUCCEED) {
      83             :                                 BBPunfix(bn->batCacheid);
      84             :                                 BBPunfix(b->batCacheid);
      85             :                                 throw(MAL, "mat.pack", GDK_EXCEPTION);
      86             :                         }
      87             :                         BBPunfix(b->batCacheid);
      88             :                 }
      89             :         }
      90             :         if( !(!bn->tnil || !bn->tnonil)){
      91             :                 BBPkeepref(*ret = bn->batCacheid);
      92             :                 throw(MAL, "mat.pack", "INTERNAL ERROR" "bn->tnil or  bn->tnonil fails ");
      93             :         }
      94             :         BBPkeepref(*ret = bn->batCacheid);
      95             :         return MAL_SUCCEED;
      96             : }
      97             : 
      98             : /*
      99             :  * Enable incremental packing. The SQL front-end requires
     100             :  * fixed oid sequences.
     101             :  */
     102             : static str
     103      631679 : MATpackIncrement(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
     104             : {
     105      631679 :         bat *ret = getArgReference_bat(stk,p,0);
     106             :         int     pieces;
     107             :         BAT *b, *bb, *bn;
     108             :         size_t newsize;
     109             : 
     110             :         (void) cntxt;
     111      631679 :         b = BATdescriptor( stk->stk[getArg(p,1)].val.ival);
     112      631666 :         if ( b == NULL)
     113           0 :                 throw(MAL, "mat.pack", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     114             : 
     115      631666 :         if ( getArgType(mb,p,2) == TYPE_int){
     116             :                 /* first step, estimate with some slack */
     117      158488 :                 pieces = stk->stk[getArg(p,2)].val.ival;
     118      315143 :                 bn = COLnew(b->hseqbase, ATOMtype(b->ttype), (BUN)(1.2 * BATcount(b) * pieces), TRANSIENT);
     119      158488 :                 if (bn == NULL) {
     120           0 :                         BBPunfix(b->batCacheid);
     121           0 :                         throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     122             :                 }
     123             :                 /* allocate enough space for the vheap, but not for strings,
     124             :                  * since BATappend does clever things for strings */
     125      158488 :                 if ( b->tvheap && bn->tvheap && ATOMstorage(b->ttype) != TYPE_str){
     126          48 :                         newsize =  b->tvheap->size * pieces;
     127          48 :                         if (HEAPextend(bn->tvheap, newsize, true) != GDK_SUCCEED) {
     128           0 :                                 BBPunfix(b->batCacheid);
     129           0 :                                 BBPunfix(bn->batCacheid);
     130           0 :                                 throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     131             :                         }
     132             :                 }
     133      158488 :                 BATtseqbase(bn, b->tseqbase);
     134      158483 :                 if (BATappend(bn, b, NULL, false) != GDK_SUCCEED) {
     135           0 :                         BBPunfix(bn->batCacheid);
     136           0 :                         BBPunfix(b->batCacheid);
     137           0 :                         throw(MAL, "mat.pack", GDK_EXCEPTION);
     138             :                 }
     139      158475 :                 bn->unused = (pieces-1); /* misuse "unused" field */
     140      158475 :                 BBPkeepref(*ret = bn->batCacheid);
     141      158476 :                 BBPunfix(b->batCacheid);
     142      158474 :                 if( !(!bn->tnil || !bn->tnonil))
     143           0 :                         throw(MAL, "mat.packIncrement", "INTERNAL ERROR" " bn->tnil %d bn->tnonil %d", bn->tnil, bn->tnonil);
     144             :         } else {
     145             :                 /* remaining steps */
     146      473178 :                 bb = BATdescriptor(stk->stk[getArg(p,2)].val.ival);
     147      473043 :                 if ( bb ){
     148      473043 :                         if (BATcount(b) == 0) {
     149      271251 :                                 BAThseqbase(b, bb->hseqbase);
     150      271308 :                                 BATtseqbase(b, bb->tseqbase);
     151             :                         }
     152      473037 :                         if (BATappend(b, bb, NULL, false) != GDK_SUCCEED) {
     153           0 :                                 BBPunfix(bb->batCacheid);
     154           0 :                                 BBPunfix(b->batCacheid);
     155           0 :                                 throw(MAL, "mat.pack", GDK_EXCEPTION);
     156             :                         }
     157      473090 :                         BBPunfix(bb->batCacheid);
     158             :                 }
     159      473044 :                 b->unused--;
     160      473044 :                 if(b->unused == 0)
     161      158473 :                         if (BATsetaccess(b, BAT_READ) != GDK_SUCCEED) {
     162           0 :                                 BBPunfix(b->batCacheid);
     163           0 :                                 throw(MAL, "mat.pack", GDK_EXCEPTION);
     164             :                         }
     165      473043 :                 if( !(!b->tnil || !b->tnonil)){
     166           0 :                         BBPkeepref(*ret = b->batCacheid);
     167           0 :                         throw(MAL, "mat.pack", "INTERNAL ERROR" " b->tnil or  b->tnonil fails ");
     168             :                 }
     169      473043 :                 BBPkeepref(*ret = b->batCacheid);
     170             :         }
     171             :         return MAL_SUCCEED;
     172             : }
     173             : 
     174             : static str
     175         651 : MATpack(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
     176             : {
     177         651 :         return MATpackInternal(cntxt,mb,stk,p);
     178             : }
     179             : 
     180             : static str
     181      147772 : MATpackValues(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
     182             : {
     183             :         int i, type, first = 1;
     184             :         bat *ret;
     185             :         BAT *bn;
     186             : 
     187             :         (void) cntxt;
     188      147772 :         type = getArgType(mb,p,first);
     189      147772 :         bn = COLnew(0, type, p->argc, TRANSIENT);
     190      147780 :         if( bn == NULL)
     191           0 :                 throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     192             : 
     193      147780 :         if (ATOMextern(type)) {
     194      501676 :                 for(i = first; i < p->argc; i++)
     195      414384 :                         if (BUNappend(bn, stk->stk[getArg(p,i)].val.pval, false) != GDK_SUCCEED)
     196           0 :                                 goto bailout;
     197             :         } else {
     198      347053 :                 for(i = first; i < p->argc; i++)
     199      286591 :                         if (BUNappend(bn, getArgReference(stk, p, i), false) != GDK_SUCCEED)
     200           0 :                                 goto bailout;
     201             :         }
     202      147754 :         ret= getArgReference_bat(stk,p,0);
     203      147754 :         BBPkeepref(*ret = bn->batCacheid);
     204      147724 :         return MAL_SUCCEED;
     205           0 :   bailout:
     206           0 :         BBPreclaim(bn);
     207           0 :         throw(MAL, "mat.pack", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     208             : }
     209             : 
     210             : #include "mel.h"
     211             : mel_func mat_init_funcs[] = {
     212             :  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))),
     213             :  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))),
     214             :  pattern("mat", "pack", MATpackValues, false, "Materialize the MAT (of values) into a BAT", args(1,2, batargany("",2),varargany("",2))),
     215             :  pattern("mat", "pack", MATpack, false, "Materialize the MAT into a BAT", args(1,2, batargany("",2),batvarargany("b",2))),
     216             :  pattern("mat", "packIncrement", MATpackIncrement, false, "Prepare incremental mat pack", args(1,3, batargany("",2),batargany("b",2),arg("pieces",int))),
     217             :  pattern("mat", "packIncrement", MATpackIncrement, false, "Prepare incremental mat pack", args(1,3, batargany("",2),batargany("b",2),batargany("c",2))),
     218             :  { .imp=NULL }
     219             : };
     220             : #include "mal_import.h"
     221             : #ifdef _MSC_VER
     222             : #undef read
     223             : #pragma section(".CRT$XCU",read)
     224             : #endif
     225         255 : LIB_STARTUP_FUNC(init_mat_mal)
     226         255 : { mal_module("mat", NULL, mat_init_funcs); }

Generated by: LCOV version 1.14