| 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 - 2019 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 "batExtensions.h" |
| 25 | |
| 26 | /* |
| 27 | * BAT enhancements |
| 28 | * The code to enhance the kernel. |
| 29 | */ |
| 30 | |
| 31 | str |
| 32 | CMDBATnew(Client cntxt, MalBlkPtr m, MalStkPtr s, InstrPtr p){ |
| 33 | int tt; |
| 34 | role_t kind = TRANSIENT; |
| 35 | BUN cap = 0; |
| 36 | bat *res; |
| 37 | |
| 38 | (void) cntxt; |
| 39 | res = getArgReference_bat(s, p, 0); |
| 40 | tt = getArgType(m, p, 1); |
| 41 | if (p->argc > 2) { |
| 42 | lng lcap; |
| 43 | |
| 44 | if (getArgType(m, p, 2) == TYPE_lng) |
| 45 | lcap = *getArgReference_lng(s, p, 2); |
| 46 | else if (getArgType(m, p, 2) == TYPE_int) |
| 47 | lcap = (lng) *getArgReference_int(s, p, 2); |
| 48 | else |
| 49 | throw(MAL, "bat.new" , ILLEGAL_ARGUMENT " Incorrect type for size" ); |
| 50 | if (lcap < 0) |
| 51 | throw(MAL, "bat.new" , POSITIVE_EXPECTED); |
| 52 | if (lcap > (lng) BUN_MAX) |
| 53 | throw(MAL, "bat.new" , ILLEGAL_ARGUMENT " Capacity too large" ); |
| 54 | cap = (BUN) lcap; |
| 55 | if( p->argc == 4 && getVarConstant(m,getArg(p,3)).val.ival) |
| 56 | kind = PERSISTENT; |
| 57 | } |
| 58 | |
| 59 | if (tt == TYPE_any || isaBatType(tt)) |
| 60 | throw(MAL, "bat.new" , SEMANTIC_TYPE_ERROR); |
| 61 | return (str) BKCnewBAT(res, &tt, &cap, kind); |
| 62 | } |
| 63 | |
| 64 | str |
| 65 | CMDBATsingle(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
| 66 | { |
| 67 | BAT *b; |
| 68 | int * ret= getArgReference_bat(stk,pci,0); |
| 69 | void *u =(void*) getArgReference(stk,pci,1); |
| 70 | |
| 71 | (void)cntxt; |
| 72 | |
| 73 | b = COLnew(0,getArgType(mb,pci,1),0, TRANSIENT); |
| 74 | if( b == 0) |
| 75 | throw(MAL,"bat.single" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 76 | if (ATOMextern(b->ttype)) |
| 77 | u = (ptr) *(str *)u; |
| 78 | if (BUNappend(b, u, false) != GDK_SUCCEED) { |
| 79 | BBPreclaim(b); |
| 80 | throw(MAL, "bat.single" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 81 | } |
| 82 | BBPkeepref(*ret = b->batCacheid); |
| 83 | return MAL_SUCCEED; |
| 84 | } |
| 85 | |
| 86 | /* If the optimizer has not determined the partition bounds we derive one here. */ |
| 87 | str |
| 88 | CMDBATpartition(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
| 89 | { |
| 90 | BAT *b,*bn; |
| 91 | bat *ret; |
| 92 | int i; |
| 93 | bat bid; |
| 94 | oid lval,hval=0, step; |
| 95 | |
| 96 | (void) mb; |
| 97 | (void) cntxt; |
| 98 | bid = *getArgReference_bat(stk, pci, pci->retc); |
| 99 | |
| 100 | if ((b = BATdescriptor(bid)) == NULL) { |
| 101 | throw(MAL, "bat.partition" , INTERNAL_BAT_ACCESS); |
| 102 | } |
| 103 | step = BATcount(b) / pci->retc + 1; |
| 104 | |
| 105 | /* create the slices slightly overshoot to make sure it all is taken*/ |
| 106 | for(i=0; i<pci->retc; i++){ |
| 107 | lval = i*step; |
| 108 | hval = lval + step; |
| 109 | if (i == pci->retc-1) |
| 110 | hval = BATcount(b); |
| 111 | bn = BATslice(b, lval,hval); |
| 112 | if (bn== NULL){ |
| 113 | BBPunfix(b->batCacheid); |
| 114 | throw(MAL, "bat.partition" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 115 | } |
| 116 | BAThseqbase(bn, lval); |
| 117 | stk->stk[getArg(pci,i)].val.bval = bn->batCacheid; |
| 118 | ret= getArgReference_bat(stk,pci,i); |
| 119 | BBPkeepref(*ret = bn->batCacheid); |
| 120 | } |
| 121 | BBPunfix(b->batCacheid); |
| 122 | return MAL_SUCCEED; |
| 123 | } |
| 124 | str |
| 125 | CMDBATpartition2(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) |
| 126 | { |
| 127 | BAT *b,*bn; |
| 128 | bat *ret,bid; |
| 129 | int pieces= *getArgReference_int(stk, pci, 2); |
| 130 | int idx = *getArgReference_int(stk, pci, 3); |
| 131 | oid lval,hval=0, step; |
| 132 | |
| 133 | (void) mb; |
| 134 | (void) cntxt; |
| 135 | if ( pieces <=0 ) |
| 136 | throw(MAL, "bat.partition" , POSITIVE_EXPECTED); |
| 137 | if ( idx >= pieces || idx <0 ) |
| 138 | throw(MAL, "bat.partition" , ILLEGAL_ARGUMENT " Illegal piece index" ); |
| 139 | |
| 140 | bid = *getArgReference_bat(stk, pci, pci->retc); |
| 141 | |
| 142 | if ((b = BATdescriptor(bid)) == NULL) { |
| 143 | throw(MAL, "bat.partition" , INTERNAL_BAT_ACCESS); |
| 144 | } |
| 145 | step = BATcount(b) / pieces; |
| 146 | |
| 147 | lval = idx * step; |
| 148 | if ( idx == pieces-1) |
| 149 | hval = BATcount(b); |
| 150 | else |
| 151 | hval = lval+step; |
| 152 | bn = BATslice(b, lval,hval); |
| 153 | BAThseqbase(bn, lval + b->hseqbase); |
| 154 | BBPunfix(b->batCacheid); |
| 155 | if (bn== NULL){ |
| 156 | throw(MAL, "bat.partition" , INTERNAL_OBJ_CREATE); |
| 157 | } |
| 158 | ret= getArgReference_bat(stk,pci,0); |
| 159 | BBPkeepref(*ret = bn->batCacheid); |
| 160 | return MAL_SUCCEED; |
| 161 | } |
| 162 | |
| 163 | str |
| 164 | CMDBATimprints(void *ret, bat *bid) |
| 165 | { |
| 166 | BAT *b; |
| 167 | gdk_return r; |
| 168 | |
| 169 | (void) ret; |
| 170 | if ((b = BATdescriptor(*bid)) == NULL) |
| 171 | throw(MAL, "bat.imprints" , INTERNAL_BAT_ACCESS); |
| 172 | |
| 173 | r = BATimprints(b); |
| 174 | BBPunfix(b->batCacheid); |
| 175 | if (r != GDK_SUCCEED) |
| 176 | throw(MAL, "bat.imprints" , GDK_EXCEPTION); |
| 177 | return MAL_SUCCEED; |
| 178 | } |
| 179 | str |
| 180 | CMDBATimprintsize(lng *ret, bat *bid) |
| 181 | { |
| 182 | BAT *b; |
| 183 | |
| 184 | if ((b = BATdescriptor(*bid)) == NULL) |
| 185 | throw(MAL, "bat.imprints" , INTERNAL_BAT_ACCESS); |
| 186 | |
| 187 | *ret = IMPSimprintsize(b); |
| 188 | BBPunfix(b->batCacheid); |
| 189 | return MAL_SUCCEED; |
| 190 | } |
| 191 | |