LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - iterator.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 85 118 72.0 %
Date: 2021-01-13 20:07:21 Functions: 9 12 75.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             :  * author M.L.Kersten
      11             :  * BAT Iterators
      12             :  * Many low level algorithms rely on an iterator to break a
      13             :  * collection into smaller pieces. Each piece is subsequently processed
      14             :  * by a block.
      15             :  *
      16             :  * For very large BATs it may make sense to break it into chunks
      17             :  * and process them separately to solve a query. An iterator pair is
      18             :  * provided to chop a BAT into fixed size elements.
      19             :  * Each chunk is made available as a BATview.
      20             :  * It provides read-only access to an underlying BAT. Adjusting the bounds
      21             :  * is cheap, once the BATview descriptor has been constructed.
      22             :  *
      23             :  * The smallest granularity is a single BUN, which can be used
      24             :  * to realize an iterator over the individual BAT elements.
      25             :  * For larger sized chunks, the operators return a BATview.
      26             :  *
      27             :  * All iterators require storage space to administer the
      28             :  * location of the next element. The BAT iterator module uses a simple
      29             :  * lng variable, which also acts as a cursor for barrier statements.
      30             :  *
      31             :  * The larger chunks produced are currently static, i.e.
      32             :  * their size is a parameter of the call. Dynamic chunk sizes
      33             :  * are interesting for time-series query processing. (See another module)
      34             :  *
      35             :  */
      36             : 
      37             : #include "monetdb_config.h"
      38             : #include "mal.h"
      39             : #include "mal_interpreter.h"
      40             : 
      41             : /*
      42             :  * We start with the large chunk iterator.
      43             :  * The definition of the control statements require the same
      44             :  * control variables, which means that the BATview is accessible
      45             :  * to determine how far to advance when the next chunk is retrieved.
      46             :  * The number of elements in the chunk is limited by the granule
      47             :  * size.
      48             :  */
      49             : static str
      50           9 : ITRnewChunk(lng *res, bat *vid, bat *bid, lng *granule)
      51             : {
      52             :         BAT *b, *view;
      53             :         BUN cnt;
      54             : 
      55           9 :         if ((b = BATdescriptor(*bid)) == NULL) {
      56           0 :                 throw(MAL, "chop.newChunk", INTERNAL_BAT_ACCESS);
      57             :         }
      58           9 :         cnt = BATcount(b);
      59           9 :         view = VIEWcreate(b->hseqbase, b);
      60           9 :         if (view == NULL) {
      61           0 :                 BBPunfix(b->batCacheid);
      62           0 :                 throw(MAL, "chop.newChunk", GDK_EXCEPTION);
      63             :         }
      64             : 
      65             :         /*  printf("set bat chunk bound to " LLFMT " 0 - " BUNFMT "\n",
      66             :          *granule, MIN(cnt,(BUN) *granule)); */
      67           9 :         VIEWbounds(b, view, 0, MIN(cnt, (BUN) * granule));
      68           9 :         *vid = view->batCacheid;
      69           9 :         BBPkeepref(view->batCacheid);
      70           9 :         BBPunfix(b->batCacheid);
      71           9 :         *res = 0;
      72           9 :         return MAL_SUCCEED;
      73             : }
      74             : 
      75             : /*
      76             :  * The nextChunk version advances the reader,
      77             :  * which also means that the view descriptor is already available.
      78             :  * The granule size may differ in each call.
      79             :  */
      80             : static str
      81       22223 : ITRnextChunk(lng *res, bat *vid, bat *bid, lng *granule)
      82             : {
      83             :         BAT *b, *view;
      84             :         BUN i;
      85             : 
      86       22223 :         if ((b = BATdescriptor(*bid)) == NULL) {
      87           0 :                         throw(MAL, "iterator.nextChunk", INTERNAL_BAT_ACCESS);
      88             :         }
      89       22223 :         if ((view = BATdescriptor(*vid)) == NULL) {
      90           0 :                 BBPunfix(b->batCacheid);
      91           0 :                 throw(MAL, "iterator.nextChunk", INTERNAL_BAT_ACCESS);
      92             :         }
      93       22223 :         i = (BUN) (*res + BATcount(view));
      94       22223 :         if (i >= BUNlast(b)) {
      95           9 :                 *res = lng_nil;
      96           9 :                 *vid = 0;
      97           9 :                 BBPunfix(view->batCacheid);
      98           9 :                 BBPunfix(b->batCacheid);
      99           9 :                 return MAL_SUCCEED;
     100             :         }
     101             :         /* printf("set bat chunk bound to " BUNFMT " - " BUNFMT " \n",
     102             :            i, i+(BUN) *granule-1); */
     103       22214 :         VIEWbounds(b, view, i, i + (BUN) * granule);
     104       22214 :         BAThseqbase(view, is_oid_nil(b->hseqbase) ? oid_nil : b->hseqbase + i);
     105       22214 :         BBPkeepref(*vid = view->batCacheid);
     106       22214 :         BBPunfix(b->batCacheid);
     107       22214 :         *res = i;
     108       22214 :         return MAL_SUCCEED;
     109             : }
     110             : 
     111             : /*
     112             :  * @-
     113             :  * The BUN- and BAT-stream manipulate a long handle, i.e.
     114             :  * the destination variable. It assumes it has been set to
     115             :  * zero as part of runtime stack initialization. Subsequently,
     116             :  * it fetches a bun and returns the increment to the control
     117             :  * variable. If it returns zero the control variable has been reset
     118             :  * to zero and end of stream has been reached.
     119             :  */
     120             : static str
     121         148 : ITRbunIterator(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     122             : {
     123             :         BATiter bi;
     124             :         BAT *b;
     125             :         oid *head;
     126             :         bat *bid;
     127             :         ValPtr tail;
     128             : 
     129             :         (void) cntxt;
     130             :         (void) mb;
     131         148 :         head = getArgReference_oid(stk, pci, 0);
     132         148 :         tail = &stk->stk[pci->argv[1]];
     133         148 :         bid = getArgReference_bat(stk, pci, 2);
     134             : 
     135         148 :         if ((b = BATdescriptor(*bid)) == NULL) {
     136           0 :                 throw(MAL, "iterator.nextChunk", INTERNAL_BAT_ACCESS);
     137             :         }
     138             : 
     139         148 :         if (BATcount(b) == 0) {
     140          78 :                 *head = oid_nil;
     141          78 :                 BBPunfix(b->batCacheid);
     142          78 :                 return MAL_SUCCEED;
     143             :         }
     144          70 :         *head = 0;
     145             : 
     146          70 :         bi = bat_iterator(b);
     147          70 :         if (VALinit(tail, b->ttype, BUNtail(bi, *head)) == NULL) {
     148           0 :                 BBPunfix(b->batCacheid);
     149           0 :                 throw(MAL, "iterator.nextChunk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     150             :         }
     151          70 :         BBPunfix(b->batCacheid);
     152          70 :         return MAL_SUCCEED;
     153             : }
     154             : 
     155             : static str
     156         440 : ITRbunNext(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     157             : {
     158             :         BATiter bi;
     159             :         BAT *b;
     160             :         oid *head;
     161             :         bat *bid;
     162             :         ValPtr tail;
     163             : 
     164             :         (void) cntxt;
     165             :         (void) mb;
     166         440 :         head = getArgReference_oid(stk, pci, 0);
     167         440 :         tail = &stk->stk[pci->argv[1]];
     168         440 :         bid = getArgReference_bat(stk, pci, 2);
     169             : 
     170         440 :         if ((b = BATdescriptor(*bid)) == NULL) {
     171           0 :                 throw(MAL, "iterator.nextChunk", INTERNAL_BAT_ACCESS);
     172             :         }
     173             : 
     174         440 :         *head = *head + 1;
     175         440 :         if (*head >= BUNlast(b)) {
     176          65 :                 *head = oid_nil;
     177          65 :                 BBPunfix(b->batCacheid);
     178          65 :                 return MAL_SUCCEED;
     179             :         }
     180         375 :         bi = bat_iterator(b);
     181         375 :         if (VALinit(tail, b->ttype, BUNtail(bi, *head)) == NULL) {
     182           0 :                 BBPunfix(b->batCacheid);
     183           0 :                 throw(MAL, "iterator.nextChunk", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     184             :         }
     185         375 :         BBPunfix(b->batCacheid);
     186         375 :         return MAL_SUCCEED;
     187             : }
     188             : 
     189      110002 : static str ITRnext_oid(oid *i, oid *step, oid *last){
     190      110002 :         oid v = *i;
     191      110002 :         v = v + *step;
     192      110002 :         *i = v;
     193      110002 :         if ( *last <= v )
     194           3 :                 *i = oid_nil;
     195      110002 :         return MAL_SUCCEED;
     196             : }
     197    14211200 : static str ITRnext_lng(lng *i, lng *step, lng *last){
     198    14211200 :         lng v = *i;
     199    14211200 :         v = v + *step;
     200    14211200 :         *i = v;
     201    14211200 :         if ( *last <= v )
     202          15 :                 *i = lng_nil;
     203    14211200 :         return MAL_SUCCEED;
     204             : }
     205             : #ifdef HAVE_HGE
     206           0 : static str ITRnext_hge(hge *i, hge *step, hge *last){
     207           0 :         hge v = *i;
     208           0 :         v = v + *step;
     209           0 :         *i = v;
     210           0 :         if ( *last <= v )
     211           0 :                 *i = hge_nil;
     212           0 :         return MAL_SUCCEED;
     213             : }
     214             : #endif
     215          16 : static str ITRnext_int(int *i, int *step, int *last){
     216          16 :         int v = *i;
     217          16 :         v = v + *step;
     218          16 :         *i = v;
     219          16 :         if ( *last <= v )
     220           4 :                 *i = int_nil;
     221          16 :         return MAL_SUCCEED;
     222             : }
     223           0 : static str ITRnext_sht(sht *i, sht *step, sht *last){
     224           0 :         sht v = *i;
     225           0 :         v = v + *step;
     226           0 :         *i = v;
     227           0 :         if ( *last <= v )
     228           0 :                 *i = int_nil;
     229           0 :         return MAL_SUCCEED;
     230             : }
     231           2 : static str ITRnext_flt(flt *i, flt *step, flt *last){
     232           2 :         flt v = *i;
     233           2 :         v = v + *step;
     234           2 :         *i = v;
     235           2 :         if ( *last <= v )
     236           1 :                 *i = flt_nil;
     237           2 :         return MAL_SUCCEED;
     238             : }
     239           0 : static str ITRnext_dbl(dbl *i, dbl *step, dbl *last){
     240           0 :         dbl v = *i;
     241           0 :         v = v + *step;
     242           0 :         *i = v;
     243           0 :         if ( *last <= v )
     244           0 :                 *i = dbl_nil;
     245           0 :         return MAL_SUCCEED;
     246             : }
     247             : 
     248             : #include "mel.h"
     249             : mel_func iterator_init_funcs[] = {
     250             :  command("iterator", "new", ITRnewChunk, false, "Create an iterator with fixed granule size.\nThe result is a view.", args(2,4, arg("",lng),batargany("",2),batargany("b",2),arg("size",lng))),
     251             :  command("iterator", "next", ITRnextChunk, false, "Produce the next chunk for processing.", args(2,4, arg("",lng),batargany("",2),batargany("b",2),arg("size",lng))),
     252             :  pattern("iterator", "new", ITRbunIterator, false, "Process the buns one by one extracted from a void table.", args(2,3, arg("h",oid),argany("t",2),batargany("b",2))),
     253             :  pattern("iterator", "next", ITRbunNext, false, "Produce the next bun for processing.", args(2,3, arg("h",oid),argany("t",2),batargany("b",2))),
     254             :  command("iterator", "next", ITRnext_oid, false, "", args(1,3, arg("",oid),arg("step",oid),arg("last",oid))),
     255             :  command("iterator", "next", ITRnext_sht, false, "", args(1,3, arg("",sht),arg("step",sht),arg("last",sht))),
     256             :  command("iterator", "next", ITRnext_int, false, "", args(1,3, arg("",int),arg("step",int),arg("last",int))),
     257             :  command("iterator", "next", ITRnext_lng, false, "", args(1,3, arg("",lng),arg("step",lng),arg("last",lng))),
     258             :  command("iterator", "next", ITRnext_flt, false, "", args(1,3, arg("",flt),arg("step",flt),arg("last",flt))),
     259             :  command("iterator", "next", ITRnext_dbl, false, "Advances the iterator with a fixed value", args(1,3, arg("",dbl),arg("step",dbl),arg("last",dbl))),
     260             : #ifdef HAVE_HGE
     261             :  command("iterator", "next", ITRnext_hge, false, "", args(1,3, arg("",hge),arg("step",hge),arg("last",hge))),
     262             : #endif
     263             :  { .imp=NULL }
     264             : };
     265             : #include "mal_import.h"
     266             : #ifdef _MSC_VER
     267             : #undef read
     268             : #pragma section(".CRT$XCU",read)
     269             : #endif
     270         255 : LIB_STARTUP_FUNC(init_iterator_mal)
     271         255 : { mal_module("iterator", NULL, iterator_init_funcs); }

Generated by: LCOV version 1.14