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
31str
32CMDBATnew(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
64str
65CMDBATsingle(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. */
87str
88CMDBATpartition(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}
124str
125CMDBATpartition2(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
163str
164CMDBATimprints(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}
179str
180CMDBATimprintsize(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