LCOV - code coverage report
Current view: top level - monetdb5/modules/atoms - blob.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 88 154 57.1 %
Date: 2024-12-20 20:06:10 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             :  * @f blob
      15             :  * @v 1.0
      16             :  * @a Wilko Quak, Peter Boncz, M. Kersten, N. Nes
      17             :  * @+ The blob data type
      18             :  * The datatype 'blob' introduced here illustrates the power
      19             :  * in the hands of a programmer to extend the functionality of the
      20             :  * Monet GDK library. It consists of an interface specification for
      21             :  * the necessary operators, a startup routine to register the
      22             :  * type in thekernel, and some additional operators used outside
      23             :  * the kernel itself.
      24             :  *
      25             :  * The 'blob' data type is used in many database engines to
      26             :  * store a variable sized atomary value.
      27             :  * Its definition forms a generic base to store arbitrary structures
      28             :  * in the database, without knowing its internal coding, layout,
      29             :  * or interpretation.
      30             :  *
      31             :  * The blob memory layout consists of first 4 bytes containing
      32             :  * the bytes-size of the blob (excluding the integer), and then just binary data.
      33             :  *
      34             :  * @+ Module Definition
      35             :  */
      36             : #include "monetdb_config.h"
      37             : #include "mal_client.h"
      38             : #include "mal_interpreter.h"
      39             : #include "mal_exception.h"
      40             : 
      41             : static str
      42           1 : BLOBnitems(int *ret, blob **b)
      43             : {
      44           1 :         if (is_blob_nil(*b)) {
      45           1 :                 *ret = int_nil;
      46             :         } else {
      47           0 :                 assert((*b)->nitems < INT_MAX);
      48           0 :                 *ret = (int) (*b)->nitems;
      49             :         }
      50           1 :         return MAL_SUCCEED;
      51             : }
      52             : 
      53             : static str
      54          85 : BLOBnitems_bulk(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
      55             : {
      56          85 :         BATiter bi;
      57          85 :         BAT *bn = NULL, *b = NULL, *bs = NULL;
      58          85 :         int *restrict vals;
      59          85 :         str msg = MAL_SUCCEED;
      60          85 :         bool nils = false;
      61          85 :         struct canditer ci1 = { 0 };
      62          85 :         oid off1;
      63          85 :         bat *res = getArgReference_bat(stk, pci, 0),
      64          85 :                 *bid = getArgReference_bat(stk, pci, 1),
      65          85 :                 *sid1 = pci->argc == 3 ? getArgReference_bat(stk, pci, 2) : NULL;
      66             : 
      67          85 :         (void) cntxt;
      68          85 :         (void) mb;
      69          85 :         if (!(b = BATdescriptor(*bid))) {
      70           0 :                 msg = createException(MAL, "blob.nitems_bulk",
      71             :                                                           SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      72           0 :                 goto bailout;
      73             :         }
      74          85 :         if (sid1 && !is_bat_nil(*sid1) && !(bs = BATdescriptor(*sid1))) {
      75           0 :                 msg = createException(MAL, "blob.nitems_bulk",
      76             :                                                           SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
      77           0 :                 goto bailout;
      78             :         }
      79          85 :         canditer_init(&ci1, b, bs);
      80          85 :         if (!(bn = COLnew(ci1.hseq, TYPE_int, ci1.ncand, TRANSIENT))) {
      81           0 :                 msg = createException(MAL, "blob.nitems_bulk",
      82             :                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
      83           0 :                 goto bailout;
      84             :         }
      85             : 
      86          85 :         off1 = b->hseqbase;
      87          85 :         bi = bat_iterator(b);
      88          85 :         vals = Tloc(bn, 0);
      89          85 :         if (ci1.tpe == cand_dense) {
      90     5333430 :                 for (BUN i = 0; i < ci1.ncand; i++) {
      91     5333345 :                         oid p1 = (canditer_next_dense(&ci1) - off1);
      92     5333345 :                         const blob *b = BUNtvar(bi, p1);
      93             : 
      94     5333345 :                         if (is_blob_nil(b)) {
      95           2 :                                 vals[i] = int_nil;
      96           2 :                                 nils = true;
      97             :                         } else {
      98     5333343 :                                 assert((int) b->nitems < INT_MAX);
      99     5333343 :                                 vals[i] = (int) b->nitems;
     100             :                         }
     101             :                 }
     102             :         } else {
     103           0 :                 for (BUN i = 0; i < ci1.ncand; i++) {
     104           0 :                         oid p1 = (canditer_next(&ci1) - off1);
     105           0 :                         const blob *b = BUNtvar(bi, p1);
     106             : 
     107           0 :                         if (is_blob_nil(b)) {
     108           0 :                                 vals[i] = int_nil;
     109           0 :                                 nils = true;
     110             :                         } else {
     111           0 :                                 assert((int) b->nitems < INT_MAX);
     112           0 :                                 vals[i] = (int) b->nitems;
     113             :                         }
     114             :                 }
     115             :         }
     116          85 :         bat_iterator_end(&bi);
     117             : 
     118          85 :         BATsetcount(bn, ci1.ncand);
     119          85 :         bn->tnil = nils;
     120          85 :         bn->tnonil = !nils;
     121          85 :         bn->tkey = BATcount(bn) <= 1;
     122          85 :         bn->tsorted = BATcount(bn) <= 1;
     123          85 :         bn->trevsorted = BATcount(bn) <= 1;
     124          85 :         *res = bn->batCacheid;
     125          85 :         BBPkeepref(bn);
     126          85 :   bailout:
     127          85 :         BBPreclaim(b);
     128          85 :         BBPreclaim(bs);
     129          85 :         return msg;
     130             : }
     131             : 
     132             : static str
     133           1 : BLOBtoblob(blob **retval, const char *const *s)
     134             : {
     135           1 :         size_t len = strLen(*s);
     136           1 :         blob *b = (blob *) GDKmalloc(blobsize(len));
     137             : 
     138           1 :         if (b == NULL)
     139           0 :                 throw(MAL, "blob.toblob", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     140           1 :         b->nitems = len;
     141           1 :         memcpy(b->data, *s, len);
     142           1 :         *retval = b;
     143           1 :         return MAL_SUCCEED;
     144             : }
     145             : 
     146             : static str
     147           1 : BLOBblob_blob(blob **d, const blob *const*s)
     148             : {
     149           1 :         size_t len = blobsize((*s)->nitems);
     150           1 :         blob *b;
     151             : 
     152           1 :         *d = b = GDKmalloc(len);
     153           1 :         if (b == NULL)
     154           0 :                 throw(MAL, "blob", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     155           1 :         b->nitems = (*s)->nitems;
     156           1 :         if (!is_blob_nil(b) && b->nitems != 0)
     157           0 :                 memcpy(b->data, (*s)->data, b->nitems);
     158             :         return MAL_SUCCEED;
     159             : }
     160             : 
     161             : static str
     162           1 : BLOBblob_blob_bulk(bat *res, const bat *bid, const bat *sid)
     163             : {
     164           1 :         BAT *b = NULL, *s = NULL, *dst = NULL;
     165           1 :         BATiter bi;
     166           1 :         str msg = NULL;
     167           1 :         struct canditer ci;
     168           1 :         oid off;
     169           1 :         bool nils = false;
     170             : 
     171           1 :         if (sid && !is_bat_nil(*sid)) {
     172           0 :                 if ((s = BATdescriptor(*sid)) == NULL) {
     173           0 :                         msg = createException(SQL, "batcalc.blob_blob_bulk",
     174             :                                                                   SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     175           0 :                         goto bailout;
     176             :                 }
     177             :         } else {
     178           1 :                 BBPretain(*res = *bid); /* nothing to convert, return */
     179           1 :                 return MAL_SUCCEED;
     180             :         }
     181           0 :         if ((b = BATdescriptor(*bid)) == NULL) {
     182           0 :                 msg = createException(SQL, "batcalc.blob_blob_bulk",
     183             :                                                           SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     184           0 :                 goto bailout;
     185             :         }
     186           0 :         off = b->hseqbase;
     187           0 :         canditer_init(&ci, b, s);
     188           0 :         if (!(dst = COLnew(ci.hseq, TYPE_blob, ci.ncand, TRANSIENT))) {
     189           0 :                 msg = createException(SQL, "batcalc.blob_blob_bulk",
     190             :                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     191           0 :                 goto bailout;
     192             :         }
     193             : 
     194           0 :         bi = bat_iterator(b);
     195           0 :         if (ci.tpe == cand_dense) {
     196           0 :                 for (BUN i = 0; i < ci.ncand; i++) {
     197           0 :                         oid p = (canditer_next_dense(&ci) - off);
     198           0 :                         const blob *v = BUNtvar(bi, p);
     199             : 
     200           0 :                         if (tfastins_nocheckVAR(dst, i, v) != GDK_SUCCEED) {
     201           0 :                                 msg = createException(SQL, "batcalc.blob_blob_bulk",
     202             :                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     203           0 :                                 goto bailout1;
     204             :                         }
     205           0 :                         nils |= is_blob_nil(v);
     206             :                 }
     207             :         } else {
     208           0 :                 for (BUN i = 0; i < ci.ncand; i++) {
     209           0 :                         oid p = (canditer_next(&ci) - off);
     210           0 :                         const blob *v = BUNtvar(bi, p);
     211             : 
     212           0 :                         if (tfastins_nocheckVAR(dst, i, v) != GDK_SUCCEED) {
     213           0 :                                 msg = createException(SQL, "batcalc.blob_blob_bulk",
     214             :                                                                           SQLSTATE(HY013) MAL_MALLOC_FAIL);
     215           0 :                                 goto bailout1;
     216             :                         }
     217           0 :                         nils |= is_blob_nil(v);
     218             :                 }
     219             :         }
     220           0 :   bailout1:
     221           0 :         bat_iterator_end(&bi);
     222             : 
     223           0 :   bailout:
     224           0 :         BBPreclaim(b);
     225           0 :         BBPreclaim(s);
     226           0 :         if (dst && !msg) {
     227           0 :                 BATsetcount(dst, ci.ncand);
     228           0 :                 dst->tnil = nils;
     229           0 :                 dst->tnonil = !nils;
     230           0 :                 dst->tkey = BATcount(dst) <= 1;
     231           0 :                 dst->tsorted = BATcount(dst) <= 1;
     232           0 :                 dst->trevsorted = BATcount(dst) <= 1;
     233           0 :                 *res = dst->batCacheid;
     234           0 :                 BBPkeepref(dst);
     235           0 :         } else if (dst)
     236           0 :                 BBPreclaim(dst);
     237             :         return msg;
     238             : }
     239             : 
     240             : static str
     241          24 : BLOBblob_fromstr(blob **b, const char *const*s)
     242             : {
     243          24 :         size_t len = 0;
     244             : 
     245          24 :         if (BATatoms[TYPE_blob].atomFromStr(*s, &len, (void **) b, false) < 0)
     246           3 :                 throw(MAL, "blob", GDK_EXCEPTION);
     247             :         return MAL_SUCCEED;
     248             : }
     249             : 
     250             : static str
     251           9 : BLOBblob_fromstr_bulk(bat *res, const bat *bid, const bat *sid)
     252             : {
     253           9 :         BAT *b, *s = NULL, *bn;
     254             : 
     255           9 :         if ((b = BATdescriptor(*bid)) == NULL)
     256           0 :                 throw(MAL, "batcalc.blob", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     257           9 :         if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
     258           0 :                 BBPunfix(b->batCacheid);
     259           0 :                 throw(MAL, "batcalc.blob", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
     260             :         }
     261           9 :         bn = BATconvert(b, s, TYPE_blob, 0, 0, 0);
     262           9 :         BBPunfix(b->batCacheid);
     263           9 :         BBPreclaim(s);
     264           9 :         if (bn == NULL)
     265           0 :                 throw(MAL, "batcalc.blob", GDK_EXCEPTION);
     266           9 :         *res = bn->batCacheid;
     267           9 :         BBPkeepref(bn);
     268           9 :         return MAL_SUCCEED;
     269             : }
     270             : 
     271             : #include "mel.h"
     272             : static mel_func blob_init_funcs[] = {
     273             :  command("blob", "blob", BLOBblob_blob, false, "Noop routine.", args(1,2, arg("",blob),arg("s",blob))),
     274             :  command("blob", "blob", BLOBblob_fromstr, false, "", args(1,2, arg("",blob),arg("s",str))),
     275             :  command("blob", "toblob", BLOBtoblob, false, "store a string as a blob.", args(1,2, arg("",blob),arg("v",str))),
     276             :  command("blob", "nitems", BLOBnitems, false, "get the number of bytes in this blob.", args(1,2, arg("",int),arg("b",blob))),
     277             :  pattern("batblob", "nitems", BLOBnitems_bulk, false, "", args(1,2, batarg("",int),batarg("b",blob))),
     278             :  pattern("batblob", "nitems", BLOBnitems_bulk, false, "", args(1,3, batarg("",int),batarg("b",blob),batarg("s",oid))),
     279             :  command("calc", "blob", BLOBblob_blob, false, "", args(1,2, arg("",blob),arg("b",blob))),
     280             :  command("batcalc", "blob", BLOBblob_blob_bulk, false, "", args(1,3, batarg("",blob),batarg("b",blob),batarg("s",oid))),
     281             :  command("calc", "blob", BLOBblob_fromstr, false, "", args(1,2, arg("",blob),arg("s",str))),
     282             :  command("batcalc", "blob", BLOBblob_fromstr_bulk, false, "", args(1,3, batarg("",blob),batarg("b",str),batarg("s",oid))),
     283             :  { .imp=NULL }
     284             : };
     285             : #include "mal_import.h"
     286             : #ifdef _MSC_VER
     287             : #undef read
     288             : #pragma section(".CRT$XCU",read)
     289             : #endif
     290         325 : LIB_STARTUP_FUNC(init_blob_mal)
     291         325 : { mal_module("blob", NULL, blob_init_funcs); }

Generated by: LCOV version 1.14