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 | * Peter Boncz, M.L. Kersten |
11 | * Binary Association Tables |
12 | * This module contains the commands and patterns to manage Binary |
13 | * Association Tables (BATs). The relational operations you can execute |
14 | * on BATs have the form of a neat algebra, described in algebra.c |
15 | * |
16 | * But a database system needs more that just this algebra, since often it |
17 | * is crucial to do table-updates (this would not be permitted in a strict |
18 | * algebra). |
19 | * |
20 | * All commands needed for BAT updates, property management, basic I/O, |
21 | * persistence, and storage options can be found in this module. |
22 | * |
23 | * All parameters to the modules are passed by reference. |
24 | * In particular, this means that string values are passed to the module |
25 | * layer as (str *) |
26 | * and we have to de-reference them before entering the gdk library. |
27 | * (Actual a design error in gdk to differentiate passing int/str) |
28 | * This calls for knowledge on the underlying BAT types`s |
29 | */ |
30 | |
31 | #include "monetdb_config.h" |
32 | #include "bat5.h" |
33 | #include "mal_exception.h" |
34 | |
35 | /* set access mode to bat, replacing input with output */ |
36 | static BAT * |
37 | setaccess(BAT *b, restrict_t mode) |
38 | { |
39 | BAT *bn = b; |
40 | |
41 | if (BATsetaccess(b, mode) != GDK_SUCCEED) { |
42 | if (b->batSharecnt && mode != BAT_READ) { |
43 | bn = COLcopy(b, b->ttype, true, TRANSIENT); |
44 | if (bn != NULL && |
45 | BATsetaccess(bn, mode) != GDK_SUCCEED) { |
46 | BBPreclaim(bn); |
47 | bn = NULL; |
48 | } |
49 | } else { |
50 | bn = NULL; |
51 | } |
52 | BBPunfix(b->batCacheid); |
53 | } |
54 | return bn; |
55 | } |
56 | |
57 | static char * |
58 | pre(str s1, str s2) |
59 | { |
60 | static char buf[64]; |
61 | |
62 | snprintf(buf, 64, "%s%s" , s1, s2); |
63 | return buf; |
64 | } |
65 | static char * |
66 | local_itoa(ssize_t i) |
67 | { |
68 | static char buf[32]; |
69 | |
70 | snprintf(buf, 32, "%zd" , i); |
71 | return buf; |
72 | } |
73 | static char * |
74 | local_utoa(size_t i) |
75 | { |
76 | static char buf[32]; |
77 | |
78 | snprintf(buf, 32, "%zu" , i); |
79 | return buf; |
80 | } |
81 | |
82 | #define COLLISION (8 * sizeof(size_t)) |
83 | |
84 | static gdk_return |
85 | HASHinfo(BAT *bk, BAT *bv, Hash *h, str s) |
86 | { |
87 | BUN i; |
88 | BUN j; |
89 | BUN k; |
90 | BUN cnt[COLLISION + 1]; |
91 | |
92 | if (BUNappend(bk, pre(s, "type" ), false) != GDK_SUCCEED || |
93 | BUNappend(bv, ATOMname(h->type),false) != GDK_SUCCEED || |
94 | BUNappend(bk, pre(s, "mask" ), false) != GDK_SUCCEED || |
95 | BUNappend(bv, local_utoa(h->lim),false) != GDK_SUCCEED) |
96 | return GDK_FAIL; |
97 | |
98 | for (i = 0; i < COLLISION + 1; i++) { |
99 | cnt[i] = 0; |
100 | } |
101 | for (i = 0; i <= h->mask; i++) { |
102 | j = HASHlist(h, i); |
103 | for (k = 0; j; k++) |
104 | j >>= 1; |
105 | cnt[k]++; |
106 | } |
107 | |
108 | for (i = 0; i < COLLISION + 1; i++) |
109 | if (cnt[i]) { |
110 | if (BUNappend(bk, pre(s, local_utoa(i?(((size_t)1)<<(i-1)):0)), false) != GDK_SUCCEED || |
111 | BUNappend(bv, local_utoa((size_t) cnt[i]), false) != GDK_SUCCEED) |
112 | return GDK_FAIL; |
113 | } |
114 | return GDK_SUCCEED; |
115 | } |
116 | |
117 | static gdk_return |
118 | infoHeap(BAT *bk, BAT*bv, Heap *hp, str nme) |
119 | { |
120 | char buf[1024], *p = buf; |
121 | |
122 | if (!hp) |
123 | return GDK_SUCCEED; |
124 | while (*nme) |
125 | *p++ = *nme++; |
126 | strcpy(p, "free" ); |
127 | if (BUNappend(bk, buf, false) != GDK_SUCCEED || |
128 | BUNappend(bv, local_utoa(hp->free), false) != GDK_SUCCEED) |
129 | return GDK_FAIL; |
130 | strcpy(p, "size" ); |
131 | if (BUNappend(bk, buf, false) != GDK_SUCCEED || |
132 | BUNappend(bv, local_utoa(hp->size), false) != GDK_SUCCEED) |
133 | return GDK_FAIL; |
134 | strcpy(p, "storage" ); |
135 | if (BUNappend(bk, buf, false) != GDK_SUCCEED || |
136 | BUNappend(bv, (hp->base == NULL || hp->base == (char*)1) ? "absent" : (hp->storage == STORE_MMAP) ? (hp->filename[0] ? "memory mapped" : "anonymous vm" ) : (hp->storage == STORE_PRIV) ? "private map" : "malloced" , false) != GDK_SUCCEED) |
137 | return GDK_FAIL; |
138 | strcpy(p, "newstorage" ); |
139 | if (BUNappend(bk, buf, false) != GDK_SUCCEED || |
140 | BUNappend(bv, (hp->newstorage == STORE_MEM) ? "malloced" : (hp->newstorage == STORE_PRIV) ? "private map" : "memory mapped" , false) != GDK_SUCCEED) |
141 | return GDK_FAIL; |
142 | strcpy(p, "filename" ); |
143 | if (BUNappend(bk, buf, false) != GDK_SUCCEED || |
144 | BUNappend(bv, hp->filename[0] ? hp->filename : "no file" , false) != GDK_SUCCEED) |
145 | return GDK_FAIL; |
146 | return GDK_SUCCEED; |
147 | } |
148 | |
149 | static inline char * |
150 | oidtostr(oid i, char *p, size_t len) |
151 | { |
152 | if (OIDtoStr(&p, &len, &i, false) < 0) |
153 | return NULL; |
154 | return p; |
155 | } |
156 | |
157 | /* |
158 | * The remainder contains the wrapper code over the mserver version 4 |
159 | * InformationFunctions |
160 | * In most cases we pass a BAT identifier, which should be unified |
161 | * with a BAT descriptor. Upon failure we can simply abort the function. |
162 | * |
163 | * The logical head type :oid is mapped to a TYPE_void |
164 | * with sequenceBase. It represents the old fashioned :vid |
165 | */ |
166 | |
167 | |
168 | str |
169 | BKCnewBAT(bat *res, const int *tt, const BUN *cap, role_t role) |
170 | { |
171 | BAT *bn; |
172 | |
173 | bn = COLnew(0, *tt, *cap, role); |
174 | if (bn == NULL) |
175 | throw(MAL, "bat.new" , GDK_EXCEPTION); |
176 | *res = bn->batCacheid; |
177 | BBPkeepref(*res); |
178 | return MAL_SUCCEED; |
179 | } |
180 | |
181 | str |
182 | BKCattach(bat *ret, const int *tt, const char * const *heapfile) |
183 | { |
184 | BAT *bn; |
185 | |
186 | bn = BATattach(*tt, *heapfile, TRANSIENT); |
187 | if (bn == NULL) |
188 | throw(MAL, "bat.attach" , GDK_EXCEPTION); |
189 | if( !bn->batTransient) |
190 | BATmsync(bn); |
191 | *ret = bn->batCacheid; |
192 | BBPkeepref(*ret); |
193 | return MAL_SUCCEED; |
194 | } |
195 | |
196 | str |
197 | BKCdensebat(bat *ret, const lng *size) |
198 | { |
199 | BAT *bn; |
200 | lng sz = *size; |
201 | |
202 | if (sz < 0) |
203 | sz = 0; |
204 | if (sz > (lng) BUN_MAX) |
205 | sz = (lng) BUN_MAX; |
206 | bn = BATdense(0, 0, (BUN) sz); |
207 | if (bn == NULL) |
208 | throw(MAL, "bat.densebat" , GDK_EXCEPTION); |
209 | *ret = bn->batCacheid; |
210 | BBPkeepref(*ret); |
211 | return MAL_SUCCEED; |
212 | } |
213 | |
214 | str |
215 | BKCmirror(bat *ret, const bat *bid) |
216 | { |
217 | BAT *b, *bn; |
218 | |
219 | *ret = 0; |
220 | if ((b = BATdescriptor(*bid)) == NULL) { |
221 | throw(MAL, "bat.mirror" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
222 | } |
223 | bn = BATdense(b->hseqbase, b->hseqbase, BATcount(b)); |
224 | BBPunfix(b->batCacheid); |
225 | if (bn == NULL) { |
226 | throw(MAL, "bat.mirror" , GDK_EXCEPTION); |
227 | } |
228 | *ret = bn->batCacheid; |
229 | BBPkeepref(*ret); |
230 | return MAL_SUCCEED; |
231 | } |
232 | |
233 | char * |
234 | BKCdelete(bat *r, const bat *bid, const oid *h) |
235 | { |
236 | BAT *b; |
237 | |
238 | if ((b = BATdescriptor(*bid)) == NULL) |
239 | throw(MAL, "bat.delete" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
240 | if ((b = setaccess(b, BAT_WRITE)) == NULL) |
241 | throw(MAL, "bat.delete" , OPERATION_FAILED); |
242 | if (BUNdelete(b, *h) != GDK_SUCCEED) { |
243 | BBPunfix(b->batCacheid); |
244 | throw(MAL, "bat.delete" , GDK_EXCEPTION); |
245 | } |
246 | BBPkeepref(*r = b->batCacheid); |
247 | return MAL_SUCCEED; |
248 | } |
249 | |
250 | str |
251 | BKCdelete_multi(bat *r, const bat *bid, const bat *sid) |
252 | { |
253 | BAT *b, *s; |
254 | gdk_return ret; |
255 | |
256 | if ((b = BATdescriptor(*bid)) == NULL) |
257 | throw(MAL, "bat.delete" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
258 | if ((s = BATdescriptor(*sid)) == NULL) { |
259 | BBPunfix(b->batCacheid); |
260 | throw(MAL, "bat.delete" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
261 | } |
262 | ret = BATdel(b, s); |
263 | BBPunfix(s->batCacheid); |
264 | if (ret != GDK_SUCCEED) { |
265 | BBPunfix(b->batCacheid); |
266 | throw(MAL, "bat.delete" , GDK_EXCEPTION); |
267 | } |
268 | BBPkeepref(*r = b->batCacheid); |
269 | return MAL_SUCCEED; |
270 | } |
271 | |
272 | str |
273 | BKCdelete_all(bat *r, const bat *bid) |
274 | { |
275 | BAT *b; |
276 | |
277 | if ((b = BATdescriptor(*bid)) == NULL) |
278 | throw(MAL, "bat.delete" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
279 | if (BATclear(b, false) != GDK_SUCCEED) { |
280 | BBPunfix(b->batCacheid); |
281 | throw(MAL, "bat.delete_all" , GDK_EXCEPTION); |
282 | } |
283 | if( !b->batTransient) |
284 | BATmsync(b); |
285 | BBPkeepref(*r = b->batCacheid); |
286 | return MAL_SUCCEED; |
287 | } |
288 | |
289 | char * |
290 | BKCappend_cand_force_wrap(bat *r, const bat *bid, const bat *uid, const bat *sid, const bit *force) |
291 | { |
292 | BAT *b, *u, *s = NULL; |
293 | gdk_return ret; |
294 | |
295 | if ((b = BATdescriptor(*bid)) == NULL) |
296 | throw(MAL, "bat.append" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
297 | if ((b = setaccess(b, BAT_WRITE)) == NULL) |
298 | throw(MAL, "bat.append" , OPERATION_FAILED); |
299 | if ((u = BATdescriptor(*uid)) == NULL) { |
300 | BBPunfix(b->batCacheid); |
301 | throw(MAL, "bat.append" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
302 | } |
303 | if (sid && *sid && (s = BATdescriptor(*sid)) == NULL) { |
304 | BBPunfix(b->batCacheid); |
305 | BBPunfix(u->batCacheid); |
306 | throw(MAL, "bat.append" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
307 | } |
308 | ret = BATappend(b, u, s, force ? *force : false); |
309 | BBPunfix(u->batCacheid); |
310 | if (s) |
311 | BBPunfix(s->batCacheid); |
312 | if (ret != GDK_SUCCEED) { |
313 | BBPunfix(b->batCacheid); |
314 | throw(MAL, "bat.append" , GDK_EXCEPTION); |
315 | } |
316 | if( !b->batTransient) |
317 | BATmsync(b); |
318 | BBPkeepref(*r = b->batCacheid); |
319 | return MAL_SUCCEED; |
320 | } |
321 | |
322 | char * |
323 | BKCappend_cand_wrap(bat *r, const bat *bid, const bat *uid, const bat *sid) |
324 | { |
325 | return BKCappend_cand_force_wrap(r, bid, uid, sid, NULL); |
326 | } |
327 | |
328 | char * |
329 | BKCappend_wrap(bat *r, const bat *bid, const bat *uid) |
330 | { |
331 | return BKCappend_cand_force_wrap(r, bid, uid, NULL, NULL); |
332 | } |
333 | |
334 | char * |
335 | BKCappend_force_wrap(bat *r, const bat *bid, const bat *uid, const bit *force) |
336 | { |
337 | return BKCappend_cand_force_wrap(r, bid, uid, NULL, force); |
338 | } |
339 | |
340 | str |
341 | BKCappend_val_force_wrap(bat *r, const bat *bid, const void *u, const bit *force) |
342 | { |
343 | BAT *b; |
344 | |
345 | if ((b = BATdescriptor(*bid)) == NULL) |
346 | throw(MAL, "bat.append" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
347 | if ((b = setaccess(b, BAT_WRITE)) == NULL) |
348 | throw(MAL, "bat.append" , OPERATION_FAILED); |
349 | if (b->ttype >= TYPE_str && ATOMstorage(b->ttype) >= TYPE_str) { |
350 | if (u == 0 || *(str*)u == 0) |
351 | u = (ptr) str_nil; |
352 | else |
353 | u = (ptr) *(str *)u; |
354 | } |
355 | if (BUNappend(b, u, force ? *force : false) != GDK_SUCCEED) { |
356 | BBPunfix(b->batCacheid); |
357 | throw(MAL, "bat.append" , GDK_EXCEPTION); |
358 | } |
359 | BBPkeepref(*r = b->batCacheid); |
360 | return MAL_SUCCEED; |
361 | } |
362 | |
363 | str |
364 | BKCappend_val_wrap(bat *r, const bat *bid, const void *u) |
365 | { |
366 | return BKCappend_val_force_wrap(r, bid, u, NULL); |
367 | } |
368 | |
369 | str |
370 | BKCbun_inplace(bat *r, const bat *bid, const oid *id, const void *t) |
371 | { |
372 | BAT *b; |
373 | |
374 | if ((b = BATdescriptor(*bid)) == NULL) |
375 | throw(MAL, "bat.inplace" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
376 | if (void_inplace(b, *id, t, false) != GDK_SUCCEED) { |
377 | BBPunfix(b->batCacheid); |
378 | throw(MAL, "bat.inplace" , GDK_EXCEPTION); |
379 | } |
380 | BBPkeepref(*r = b->batCacheid); |
381 | return MAL_SUCCEED; |
382 | } |
383 | |
384 | str |
385 | BKCbun_inplace_force(bat *r, const bat *bid, const oid *id, const void *t, const bit *force) |
386 | { |
387 | BAT *b; |
388 | |
389 | if ((b = BATdescriptor(*bid)) == NULL) |
390 | throw(MAL, "bat.inplace" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
391 | if (void_inplace(b, *id, t, *force) != GDK_SUCCEED) { |
392 | BBPunfix(b->batCacheid); |
393 | throw(MAL, "bat.inplace" , GDK_EXCEPTION); |
394 | } |
395 | BBPkeepref(*r = b->batCacheid); |
396 | return MAL_SUCCEED; |
397 | } |
398 | |
399 | |
400 | str |
401 | BKCbat_inplace_force(bat *r, const bat *bid, const bat *rid, const bat *uid, const bit *force) |
402 | { |
403 | BAT *b, *p, *u; |
404 | |
405 | if ((b = BATdescriptor(*bid)) == NULL) |
406 | throw(MAL, "bat.inplace" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
407 | if ((p = BATdescriptor(*rid)) == NULL) { |
408 | BBPunfix(b->batCacheid); |
409 | throw(MAL, "bat.inplace" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
410 | } |
411 | if ((u = BATdescriptor(*uid)) == NULL) { |
412 | BBPunfix(b->batCacheid); |
413 | BBPunfix(p->batCacheid); |
414 | throw(MAL, "bat.inplace" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
415 | } |
416 | if (void_replace_bat(b, p, u, *force) != GDK_SUCCEED) { |
417 | BBPunfix(b->batCacheid); |
418 | BBPunfix(p->batCacheid); |
419 | BBPunfix(u->batCacheid); |
420 | throw(MAL, "bat.inplace" , GDK_EXCEPTION); |
421 | } |
422 | BBPkeepref(*r = b->batCacheid); |
423 | BBPunfix(p->batCacheid); |
424 | BBPunfix(u->batCacheid); |
425 | return MAL_SUCCEED; |
426 | } |
427 | |
428 | str |
429 | BKCbat_inplace(bat *r, const bat *bid, const bat *rid, const bat *uid) |
430 | { |
431 | bit F = FALSE; |
432 | |
433 | return BKCbat_inplace_force(r, bid, rid, uid, &F); |
434 | } |
435 | |
436 | /*end of SQL enhancement */ |
437 | |
438 | str |
439 | BKCgetCapacity(lng *res, const bat *bid) |
440 | { |
441 | *res = lng_nil; |
442 | if (BBPcheck(*bid, "bat.getCapacity" )) { |
443 | BAT *b = BBPquickdesc(*bid, false); |
444 | |
445 | if (b != NULL) |
446 | *res = (lng) BATcapacity(b); |
447 | } |
448 | return MAL_SUCCEED; |
449 | } |
450 | |
451 | str |
452 | BKCgetColumnType(str *res, const bat *bid) |
453 | { |
454 | const char *ret = str_nil; |
455 | |
456 | if (BBPcheck(*bid, "bat.getColumnType" )) { |
457 | BAT *b = BBPquickdesc(*bid, false); |
458 | |
459 | if (b) { |
460 | ret = *bid < 0 ? ATOMname(TYPE_void) : ATOMname(b->ttype); |
461 | } |
462 | } |
463 | *res = GDKstrdup(ret); |
464 | if(*res == NULL) |
465 | throw(MAL,"bat.getColumnType" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
466 | return MAL_SUCCEED; |
467 | } |
468 | |
469 | str |
470 | BKCgetRole(str *res, const bat *bid) |
471 | { |
472 | BAT *b; |
473 | |
474 | if ((b = BATdescriptor(*bid)) == NULL) { |
475 | throw(MAL, "bat.getRole" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
476 | } |
477 | *res = GDKstrdup(b->tident); |
478 | BBPunfix(b->batCacheid); |
479 | if(*res == NULL) |
480 | throw(MAL,"bat.getRole" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
481 | return MAL_SUCCEED; |
482 | } |
483 | |
484 | str |
485 | BKCsetkey(bat *res, const bat *bid, const bit *param) |
486 | { |
487 | BAT *b; |
488 | int unique; |
489 | |
490 | if ((b = BATdescriptor(*bid)) == NULL) { |
491 | throw(MAL, "bat.setKey" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
492 | } |
493 | unique = b->tunique; |
494 | if (*param) { |
495 | if (!BATkeyed(b)) { |
496 | BBPunfix(b->batCacheid); |
497 | throw(MAL, "bat.setKey" , "values of bat not unique, cannot set key property" ); |
498 | } |
499 | BATkey(b, true); |
500 | b->tunique = true; |
501 | } else { |
502 | b->tunique = false; |
503 | } |
504 | if (b->tunique != unique) |
505 | b->batDirtydesc = true; |
506 | *res = b->batCacheid; |
507 | BBPkeepref(b->batCacheid); |
508 | return MAL_SUCCEED; |
509 | } |
510 | |
511 | str |
512 | BKCisSorted(bit *res, const bat *bid) |
513 | { |
514 | BAT *b; |
515 | |
516 | if ((b = BATdescriptor(*bid)) == NULL) { |
517 | throw(MAL, "bat.isSorted" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
518 | } |
519 | *res = BATordered(b); |
520 | BBPunfix(b->batCacheid); |
521 | return MAL_SUCCEED; |
522 | } |
523 | |
524 | str |
525 | BKCisSortedReverse(bit *res, const bat *bid) |
526 | { |
527 | BAT *b; |
528 | |
529 | if ((b = BATdescriptor(*bid)) == NULL) { |
530 | throw(MAL, "bat.isSorted" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
531 | } |
532 | *res = BATordered_rev(b); |
533 | BBPunfix(b->batCacheid); |
534 | return MAL_SUCCEED; |
535 | } |
536 | |
537 | /* |
538 | * We must take care of the special case of a nil column (TYPE_void,seqbase=nil) |
539 | * such nil columns never set tkey |
540 | * a nil column of a BAT with <= 1 entries does not contain doubles => return TRUE. |
541 | */ |
542 | |
543 | str |
544 | BKCgetKey(bit *ret, const bat *bid) |
545 | { |
546 | BAT *b; |
547 | |
548 | if ((b = BATdescriptor(*bid)) == NULL) |
549 | throw(MAL, "bat.setPersistence" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
550 | *ret = BATkeyed(b); |
551 | BBPunfix(b->batCacheid); |
552 | return MAL_SUCCEED; |
553 | } |
554 | |
555 | static str |
556 | BKCpersists(void *r, const bat *bid, const bit *flg) |
557 | { |
558 | BAT *b; |
559 | |
560 | (void) r; |
561 | if ((b = BATdescriptor(*bid)) == NULL) { |
562 | throw(MAL, "bat.setPersistence" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
563 | } |
564 | if (BATmode(b, (*flg != TRUE)) != GDK_SUCCEED) { |
565 | BBPunfix(b->batCacheid); |
566 | throw(MAL, "bat.setPersistence" , ILLEGAL_ARGUMENT); |
567 | } |
568 | BBPunfix(b->batCacheid); |
569 | return MAL_SUCCEED; |
570 | } |
571 | |
572 | str |
573 | BKCsetPersistent(void *r, const bat *bid) |
574 | { |
575 | bit flag= TRUE; |
576 | return BKCpersists(r, bid, &flag); |
577 | } |
578 | |
579 | str |
580 | BKCisPersistent(bit *res, const bat *bid) |
581 | { |
582 | BAT *b; |
583 | |
584 | if ((b = BATdescriptor(*bid)) == NULL) { |
585 | throw(MAL, "bat.setPersistence" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
586 | } |
587 | *res = !b->batTransient; |
588 | BBPunfix(b->batCacheid); |
589 | return MAL_SUCCEED; |
590 | } |
591 | |
592 | str |
593 | BKCsetTransient(void *r, const bat *bid) |
594 | { |
595 | bit flag = FALSE; |
596 | return BKCpersists(r, bid, &flag); |
597 | } |
598 | |
599 | str |
600 | BKCisTransient(bit *res, const bat *bid) |
601 | { |
602 | BAT *b; |
603 | |
604 | if ((b = BATdescriptor(*bid)) == NULL) { |
605 | throw(MAL, "bat.setTransient" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
606 | } |
607 | *res = b->batTransient; |
608 | BBPunfix(b->batCacheid); |
609 | return MAL_SUCCEED; |
610 | } |
611 | |
612 | str |
613 | BKCsetAccess(bat *res, const bat *bid, const char * const *param) |
614 | { |
615 | BAT *b; |
616 | restrict_t m; |
617 | |
618 | if ((b = BATdescriptor(*bid)) == NULL) |
619 | throw(MAL, "bat.setAccess" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
620 | switch (*param[0]) { |
621 | case 'r': |
622 | m = BAT_READ; |
623 | break; |
624 | case 'a': |
625 | m = BAT_APPEND; |
626 | break; |
627 | case 'w': |
628 | m = BAT_WRITE; |
629 | break; |
630 | default: |
631 | *res = 0; |
632 | BBPunfix(b->batCacheid); |
633 | throw(MAL, "bat.setAccess" , ILLEGAL_ARGUMENT " Got %c" " expected 'r','a', or 'w'" , *param[0]); |
634 | } |
635 | if ((b = setaccess(b, m)) == NULL) |
636 | throw(MAL, "bat.setAccess" , OPERATION_FAILED); |
637 | BBPkeepref(*res = b->batCacheid); |
638 | return MAL_SUCCEED; |
639 | } |
640 | |
641 | str |
642 | BKCgetAccess(str *res, const bat *bid) |
643 | { |
644 | BAT *b; |
645 | |
646 | if ((b = BATdescriptor(*bid)) == NULL) |
647 | throw(MAL, "bat.getAccess" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
648 | switch (BATgetaccess(b)) { |
649 | case BAT_READ: |
650 | *res = GDKstrdup("read" ); |
651 | break; |
652 | case BAT_APPEND: |
653 | *res = GDKstrdup("append" ); |
654 | break; |
655 | case BAT_WRITE: |
656 | *res = GDKstrdup("write" ); |
657 | break; |
658 | } |
659 | BBPunfix(b->batCacheid); |
660 | if(*res == NULL) |
661 | throw(MAL,"bat.getAccess" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
662 | return MAL_SUCCEED; |
663 | } |
664 | |
665 | /* |
666 | * Property management |
667 | * All property operators should ensure exclusive access to the BAT |
668 | * descriptor. |
669 | * Where necessary use the primary view to access the properties |
670 | */ |
671 | str |
672 | BKCinfo(bat *ret1, bat *ret2, const bat *bid) |
673 | { |
674 | const char *mode, *accessmode; |
675 | BAT *bk = NULL, *bv= NULL, *b; |
676 | char bf[oidStrlen]; |
677 | |
678 | if ((b = BATdescriptor(*bid)) == NULL) { |
679 | throw(MAL, "bat.getInfo" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
680 | } |
681 | |
682 | bk = COLnew(0, TYPE_str, 128, TRANSIENT); |
683 | bv = COLnew(0, TYPE_str, 128, TRANSIENT); |
684 | if (bk == NULL || bv == NULL) { |
685 | BBPreclaim(bk); |
686 | BBPreclaim(bv); |
687 | BBPunfix(b->batCacheid); |
688 | throw(MAL, "bat.getInfo" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
689 | } |
690 | |
691 | if (b->batTransient) { |
692 | mode = "transient" ; |
693 | } else { |
694 | mode = "persistent" ; |
695 | } |
696 | |
697 | switch (b->batRestricted) { |
698 | case BAT_READ: |
699 | accessmode = "read-only" ; |
700 | break; |
701 | case BAT_WRITE: |
702 | accessmode = "updatable" ; |
703 | break; |
704 | case BAT_APPEND: |
705 | accessmode = "append-only" ; |
706 | break; |
707 | default: |
708 | accessmode = "unknown" ; |
709 | } |
710 | |
711 | if (BUNappend(bk, "batId" , false) != GDK_SUCCEED || |
712 | BUNappend(bv, BATgetId(b), false) != GDK_SUCCEED || |
713 | BUNappend(bk, "batCacheid" , false) != GDK_SUCCEED || |
714 | BUNappend(bv, local_itoa((ssize_t)(b->batCacheid)), false) != GDK_SUCCEED || |
715 | BUNappend(bk, "tparentid" , false) != GDK_SUCCEED || |
716 | BUNappend(bv, local_itoa((ssize_t)(b->theap.parentid)), false) != GDK_SUCCEED || |
717 | BUNappend(bk, "batSharecnt" , false) != GDK_SUCCEED || |
718 | BUNappend(bv, local_itoa((ssize_t)(b->batSharecnt)), false) != GDK_SUCCEED || |
719 | BUNappend(bk, "batCount" , false) != GDK_SUCCEED || |
720 | BUNappend(bv, local_utoa((size_t)b->batCount), false) != GDK_SUCCEED || |
721 | BUNappend(bk, "batCapacity" , false) != GDK_SUCCEED || |
722 | BUNappend(bv, local_utoa((size_t)b->batCapacity), false) != GDK_SUCCEED || |
723 | BUNappend(bk, "head" , false) != GDK_SUCCEED || |
724 | BUNappend(bv, ATOMname(TYPE_void), false) != GDK_SUCCEED || |
725 | BUNappend(bk, "tail" , false) != GDK_SUCCEED || |
726 | BUNappend(bv, ATOMname(b->ttype), false) != GDK_SUCCEED || |
727 | BUNappend(bk, "batPersistence" , false) != GDK_SUCCEED || |
728 | BUNappend(bv, mode, false) != GDK_SUCCEED || |
729 | BUNappend(bk, "batRestricted" , false) != GDK_SUCCEED || |
730 | BUNappend(bv, accessmode, false) != GDK_SUCCEED || |
731 | BUNappend(bk, "batRefcnt" , false) != GDK_SUCCEED || |
732 | BUNappend(bv, local_itoa((ssize_t)(BBP_refs(b->batCacheid))), false) != GDK_SUCCEED || |
733 | BUNappend(bk, "batLRefcnt" , false) != GDK_SUCCEED || |
734 | BUNappend(bv, local_itoa((ssize_t)(BBP_lrefs(b->batCacheid))), false) != GDK_SUCCEED || |
735 | BUNappend(bk, "batDirty" , false) != GDK_SUCCEED || |
736 | BUNappend(bv, BATdirty(b) ? "dirty" : "clean" , false) != GDK_SUCCEED || |
737 | |
738 | BUNappend(bk, "hseqbase" , false) != GDK_SUCCEED || |
739 | BUNappend(bv, oidtostr(b->hseqbase, bf, sizeof(bf)), FALSE) != GDK_SUCCEED || |
740 | |
741 | BUNappend(bk, "tident" , false) != GDK_SUCCEED || |
742 | BUNappend(bv, b->tident, false) != GDK_SUCCEED || |
743 | BUNappend(bk, "tdense" , false) != GDK_SUCCEED || |
744 | BUNappend(bv, local_itoa((ssize_t)BATtdense(b)), false) != GDK_SUCCEED || |
745 | BUNappend(bk, "tseqbase" , false) != GDK_SUCCEED || |
746 | BUNappend(bv, oidtostr(b->tseqbase, bf, sizeof(bf)), FALSE) != GDK_SUCCEED || |
747 | BUNappend(bk, "tsorted" , false) != GDK_SUCCEED || |
748 | BUNappend(bv, local_itoa((ssize_t)BATtordered(b)), false) != GDK_SUCCEED || |
749 | BUNappend(bk, "trevsorted" , false) != GDK_SUCCEED || |
750 | BUNappend(bv, local_itoa((ssize_t)BATtrevordered(b)), false) != GDK_SUCCEED || |
751 | BUNappend(bk, "tkey" , false) != GDK_SUCCEED || |
752 | BUNappend(bv, local_itoa((ssize_t)(b->tkey)), false) != GDK_SUCCEED || |
753 | BUNappend(bk, "tvarsized" , false) != GDK_SUCCEED || |
754 | BUNappend(bv, local_itoa((ssize_t)(b->tvarsized)), false) != GDK_SUCCEED || |
755 | BUNappend(bk, "tnosorted" , false) != GDK_SUCCEED || |
756 | BUNappend(bv, local_utoa(b->tnosorted), false) != GDK_SUCCEED || |
757 | BUNappend(bk, "tnorevsorted" , false) != GDK_SUCCEED || |
758 | BUNappend(bv, local_utoa(b->tnorevsorted), false) != GDK_SUCCEED || |
759 | BUNappend(bk, "tnokey[0]" , false) != GDK_SUCCEED || |
760 | BUNappend(bv, local_utoa(b->tnokey[0]), false) != GDK_SUCCEED || |
761 | BUNappend(bk, "tnokey[1]" , false) != GDK_SUCCEED || |
762 | BUNappend(bv, local_utoa(b->tnokey[1]), false) != GDK_SUCCEED || |
763 | BUNappend(bk, "tnonil" , false) != GDK_SUCCEED || |
764 | BUNappend(bv, local_utoa(b->tnonil), false) != GDK_SUCCEED || |
765 | BUNappend(bk, "tnil" , false) != GDK_SUCCEED || |
766 | BUNappend(bv, local_utoa(b->tnil), false) != GDK_SUCCEED || |
767 | |
768 | BUNappend(bk, "batInserted" , false) != GDK_SUCCEED || |
769 | BUNappend(bv, local_utoa(b->batInserted), false) != GDK_SUCCEED || |
770 | BUNappend(bk, "ttop" , false) != GDK_SUCCEED || |
771 | BUNappend(bv, local_utoa(b->theap.free), false) != GDK_SUCCEED || |
772 | BUNappend(bk, "batCopiedtodisk" , false) != GDK_SUCCEED || |
773 | BUNappend(bv, local_itoa((ssize_t)(b->batCopiedtodisk)), false) != GDK_SUCCEED || |
774 | BUNappend(bk, "batDirtydesc" , false) != GDK_SUCCEED || |
775 | BUNappend(bv, b->batDirtydesc ? "dirty" : "clean" , false) != GDK_SUCCEED || |
776 | |
777 | BUNappend(bk, "theap.dirty" , false) != GDK_SUCCEED || |
778 | BUNappend(bv, b->theap.dirty ? "dirty" : "clean" , false) != GDK_SUCCEED || |
779 | infoHeap(bk, bv, &b->theap, "tail." ) != GDK_SUCCEED || |
780 | |
781 | BUNappend(bk, "tvheap->dirty" , false) != GDK_SUCCEED || |
782 | BUNappend(bv, (b->tvheap && b->tvheap->dirty) ? "dirty" : "clean" , false) != GDK_SUCCEED || |
783 | infoHeap(bk, bv, b->tvheap, "theap." ) != GDK_SUCCEED || |
784 | |
785 | /* dump index information */ |
786 | (b->thash && |
787 | HASHinfo(bk, bv, b->thash, "thash->" ) != GDK_SUCCEED)) { |
788 | BBPreclaim(bk); |
789 | BBPreclaim(bv); |
790 | BBPunfix(b->batCacheid); |
791 | throw(MAL, "bat.getInfo" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
792 | } |
793 | |
794 | assert(BATcount(bk) == BATcount(bv)); |
795 | |
796 | BBPunfix(*bid); |
797 | BBPkeepref(*ret1 = bk->batCacheid); |
798 | BBPkeepref(*ret2 = bv->batCacheid); |
799 | return MAL_SUCCEED; |
800 | } |
801 | |
802 | // get the actual size of all constituents, also for views |
803 | #define ROUND_UP(x,y) ((y)*(((x)+(y)-1)/(y))) |
804 | |
805 | str |
806 | BKCgetSize(lng *tot, const bat *bid){ |
807 | BAT *b; |
808 | lng size = 0; |
809 | lng blksize = (lng) MT_pagesize(); |
810 | if ((b = BATdescriptor(*bid)) == NULL) { |
811 | throw(MAL, "bat.getDiskSize" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
812 | } |
813 | |
814 | size = sizeof (bat); |
815 | if ( !isVIEW(b)) { |
816 | BUN cnt = BATcapacity(b); |
817 | size += ROUND_UP(b->theap.free, blksize); |
818 | if (b->tvheap) |
819 | size += ROUND_UP(b->tvheap->free, blksize); |
820 | if (b->thash) |
821 | size += ROUND_UP(sizeof(BUN) * cnt, blksize); |
822 | size += IMPSimprintsize(b); |
823 | } |
824 | *tot = size; |
825 | BBPunfix(*bid); |
826 | return MAL_SUCCEED; |
827 | } |
828 | |
829 | /* |
830 | * Synced BATs |
831 | */ |
832 | str |
833 | BKCisSynced(bit *ret, const bat *bid1, const bat *bid2) |
834 | { |
835 | BAT *b1, *b2; |
836 | |
837 | if ((b1 = BATdescriptor(*bid1)) == NULL) { |
838 | throw(MAL, "bat.isSynced" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
839 | } |
840 | if ((b2 = BATdescriptor(*bid2)) == NULL) { |
841 | BBPunfix(b1->batCacheid); |
842 | throw(MAL, "bat.isSynced" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
843 | } |
844 | *ret = ALIGNsynced(b1, b2) != 0; |
845 | BBPunfix(b1->batCacheid); |
846 | BBPunfix(b2->batCacheid); |
847 | return MAL_SUCCEED; |
848 | } |
849 | |
850 | /* |
851 | * Role Management |
852 | */ |
853 | str |
854 | BKCsetColumn(void *r, const bat *bid, const char * const *tname) |
855 | { |
856 | BAT *b; |
857 | |
858 | (void) r; |
859 | if ((b = BATdescriptor(*bid)) == NULL) { |
860 | throw(MAL, "bat.setColumn" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
861 | } |
862 | if (tname == 0 || *tname == 0 || **tname == 0){ |
863 | BBPunfix(b->batCacheid); |
864 | throw(MAL, "bat.setColumn" , ILLEGAL_ARGUMENT " Column name missing" ); |
865 | } |
866 | if (BATroles(b, *tname) != GDK_SUCCEED) { |
867 | BBPunfix(b->batCacheid); |
868 | throw(MAL, "bat.setColumn" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
869 | } |
870 | BBPunfix(b->batCacheid); |
871 | return MAL_SUCCEED; |
872 | } |
873 | |
874 | str |
875 | BKCsetName(void *r, const bat *bid, const char * const *s) |
876 | { |
877 | BAT *b; |
878 | int ret; |
879 | int c; |
880 | const char *t = *s; |
881 | |
882 | (void) r; |
883 | if ((b = BATdescriptor(*bid)) == NULL) |
884 | throw(MAL, "bat.setName" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
885 | |
886 | for ( ; (c = *t) != 0; t++) |
887 | if (c != '_' && !GDKisalnum(c)) { |
888 | BBPunfix(b->batCacheid); |
889 | throw(MAL, "bat.setName" , ILLEGAL_ARGUMENT ": identifier expected: %s" , *s); |
890 | } |
891 | |
892 | t = *s; |
893 | ret = BBPrename(b->batCacheid, t); |
894 | BBPunfix(b->batCacheid); |
895 | switch (ret) { |
896 | case BBPRENAME_ILLEGAL: |
897 | GDKclrerr(); |
898 | throw(MAL, "bat.setName" , ILLEGAL_ARGUMENT ": illegal temporary name: '%s'" , t); |
899 | case BBPRENAME_LONG: |
900 | GDKclrerr(); |
901 | throw(MAL, "bat.setName" , ILLEGAL_ARGUMENT ": name too long: '%s'" , t); |
902 | case BBPRENAME_ALREADY: |
903 | GDKclrerr(); |
904 | /* fall through */ |
905 | case 0: |
906 | break; |
907 | } |
908 | return MAL_SUCCEED; |
909 | } |
910 | |
911 | str |
912 | BKCgetBBPname(str *ret, const bat *bid) |
913 | { |
914 | BAT *b; |
915 | |
916 | if ((b = BATdescriptor(*bid)) == NULL) { |
917 | throw(MAL, "bat.getName" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
918 | } |
919 | *ret = GDKstrdup(BBPname(b->batCacheid)); |
920 | BBPunfix(b->batCacheid); |
921 | return *ret ? MAL_SUCCEED : createException(MAL, "bat.getName" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
922 | } |
923 | |
924 | str |
925 | BKCsave(bit *res, const char * const *input) |
926 | { |
927 | bat bid = BBPindex(*input); |
928 | BAT *b; |
929 | |
930 | *res = FALSE; |
931 | if (!is_bat_nil(bid)) { |
932 | if (BBPfix(bid) > 0) { |
933 | b = BBP_cache(bid); |
934 | if (b && BATdirty(b)) { |
935 | if (BBPsave(b) == GDK_SUCCEED) |
936 | *res = TRUE; |
937 | } |
938 | BBPunfix(bid); |
939 | return MAL_SUCCEED; |
940 | } |
941 | throw(MAL, "bat.save" , "fix failed" ); |
942 | } |
943 | return MAL_SUCCEED; |
944 | } |
945 | |
946 | str |
947 | BKCsave2(void *r, const bat *bid) |
948 | { |
949 | BAT *b; |
950 | |
951 | (void) r; |
952 | if ((b = BATdescriptor(*bid)) == NULL) { |
953 | throw(MAL, "bat.save" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
954 | } |
955 | if ( !b->batTransient){ |
956 | BBPunfix(b->batCacheid); |
957 | throw(MAL, "bat.save" , "Only save transient columns." ); |
958 | } |
959 | |
960 | if (b && BATdirty(b)) |
961 | BBPsave(b); |
962 | BBPunfix(b->batCacheid); |
963 | return MAL_SUCCEED; |
964 | } |
965 | |
966 | /* |
967 | * Accelerator Control |
968 | */ |
969 | str |
970 | BKCsetHash(bit *ret, const bat *bid) |
971 | { |
972 | BAT *b; |
973 | |
974 | (void) ret; |
975 | if ((b = BATdescriptor(*bid)) == NULL) { |
976 | throw(MAL, "bat.setHash" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
977 | } |
978 | *ret = BAThash(b) == GDK_SUCCEED; |
979 | BBPunfix(b->batCacheid); |
980 | return MAL_SUCCEED; |
981 | } |
982 | |
983 | str |
984 | BKCsetImprints(bit *ret, const bat *bid) |
985 | { |
986 | BAT *b; |
987 | |
988 | (void) ret; |
989 | if ((b = BATdescriptor(*bid)) == NULL) { |
990 | throw(MAL, "bat.setImprints" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
991 | } |
992 | *ret = BATimprints(b) == GDK_SUCCEED; |
993 | BBPunfix(b->batCacheid); |
994 | return MAL_SUCCEED; |
995 | } |
996 | |
997 | str |
998 | BKCgetSequenceBase(oid *r, const bat *bid) |
999 | { |
1000 | BAT *b; |
1001 | |
1002 | if ((b = BATdescriptor(*bid)) == NULL) { |
1003 | throw(MAL, "bat.setSequenceBase" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1004 | } |
1005 | *r = b->hseqbase; |
1006 | BBPunfix(b->batCacheid); |
1007 | return MAL_SUCCEED; |
1008 | } |
1009 | |
1010 | /* |
1011 | * Shrinking a void-headed BAT using a list of oids to ignore. |
1012 | */ |
1013 | #define shrinkloop(Type) \ |
1014 | do { \ |
1015 | Type *p = (Type*)Tloc(b, 0); \ |
1016 | Type *q = (Type*)Tloc(b, BUNlast(b)); \ |
1017 | Type *r = (Type*)Tloc(bn, 0); \ |
1018 | cnt=0; \ |
1019 | for (;p<q; oidx++, p++) { \ |
1020 | if ( o < ol && *o == oidx ){ \ |
1021 | o++; \ |
1022 | } else { \ |
1023 | cnt++; \ |
1024 | *r++ = *p; \ |
1025 | } \ |
1026 | } \ |
1027 | } while (0) |
1028 | |
1029 | str |
1030 | BKCshrinkBAT(bat *ret, const bat *bid, const bat *did) |
1031 | { |
1032 | BAT *b, *d, *bn, *bs; |
1033 | BUN cnt =0; |
1034 | oid oidx = 0, *o, *ol; |
1035 | gdk_return res; |
1036 | |
1037 | if ((b = BATdescriptor(*bid)) == NULL) { |
1038 | throw(MAL, "bat.shrink" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1039 | } |
1040 | if ((d = BATdescriptor(*did)) == NULL) { |
1041 | BBPunfix(b->batCacheid); |
1042 | throw(MAL, "bat.shrink" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1043 | } |
1044 | bn= COLnew(0, b->ttype, BATcount(b) - BATcount(d), b->batRole); |
1045 | if (bn == NULL) { |
1046 | BBPunfix(b->batCacheid); |
1047 | BBPunfix(d->batCacheid); |
1048 | throw(MAL, "bat.shrink" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1049 | } |
1050 | res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false); |
1051 | BBPunfix(d->batCacheid); |
1052 | if (res != GDK_SUCCEED) { |
1053 | BBPunfix(b->batCacheid); |
1054 | BBPunfix(bn->batCacheid); |
1055 | throw(MAL, "bat.shrink" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1056 | } |
1057 | |
1058 | o = (oid*)Tloc(bs, 0); |
1059 | ol= (oid*)Tloc(bs, BUNlast(bs)); |
1060 | |
1061 | switch(ATOMstorage(b->ttype) ){ |
1062 | case TYPE_bte: shrinkloop(bte); break; |
1063 | case TYPE_sht: shrinkloop(sht); break; |
1064 | case TYPE_int: shrinkloop(int); break; |
1065 | case TYPE_lng: shrinkloop(lng); break; |
1066 | #ifdef HAVE_HGE |
1067 | case TYPE_hge: shrinkloop(hge); break; |
1068 | #endif |
1069 | case TYPE_flt: shrinkloop(flt); break; |
1070 | case TYPE_dbl: shrinkloop(dbl); break; |
1071 | case TYPE_oid: shrinkloop(oid); break; |
1072 | default: |
1073 | if (ATOMvarsized(bn->ttype)) { |
1074 | BUN p = 0; |
1075 | BUN q = BUNlast(b); |
1076 | BATiter bi = bat_iterator(b); |
1077 | |
1078 | cnt=0; |
1079 | for (;p<q; oidx++, p++) { |
1080 | if ( o < ol && *o == oidx ){ |
1081 | o++; |
1082 | } else { |
1083 | if (BUNappend(bn, BUNtail(bi, p), false) != GDK_SUCCEED) { |
1084 | BBPunfix(b->batCacheid); |
1085 | BBPunfix(bn->batCacheid); |
1086 | throw(MAL, "bat.shrink" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1087 | } |
1088 | cnt++; |
1089 | } |
1090 | } |
1091 | } else { |
1092 | switch( b->twidth){ |
1093 | case 1:shrinkloop(bte); break; |
1094 | case 2:shrinkloop(sht); break; |
1095 | case 4:shrinkloop(int); break; |
1096 | case 8:shrinkloop(lng); break; |
1097 | #ifdef HAVE_HGE |
1098 | case 16:shrinkloop(hge); break; |
1099 | #endif |
1100 | default: |
1101 | BBPunfix(b->batCacheid); |
1102 | BBPunfix(bn->batCacheid); |
1103 | throw(MAL, "bat.shrink" , "Illegal argument type" ); |
1104 | } |
1105 | } |
1106 | } |
1107 | |
1108 | BATsetcount(bn, cnt); |
1109 | bn->tsorted = false; |
1110 | bn->trevsorted = false; |
1111 | bn->tseqbase = oid_nil; |
1112 | bn->tkey = b->tkey; |
1113 | bn->tnonil = b->tnonil; |
1114 | bn->tnil = b->tnil; |
1115 | |
1116 | |
1117 | BBPunfix(b->batCacheid); |
1118 | BBPunfix(bs->batCacheid); |
1119 | BBPkeepref(*ret= bn->batCacheid); |
1120 | return MAL_SUCCEED; |
1121 | } |
1122 | |
1123 | #if 0 |
1124 | str |
1125 | BKCshrinkBATmap(bat *ret, const bat *bid, const bat *did) |
1126 | { |
1127 | BAT *b, *d, *bn, *bs; |
1128 | oid lim,oidx = 0, *o, *ol; |
1129 | oid *r; |
1130 | gdk_return res; |
1131 | |
1132 | if ((b = BATdescriptor(*bid)) == NULL) { |
1133 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1134 | } |
1135 | if ((d = BATdescriptor(*did)) == NULL) { |
1136 | BBPunfix(b->batCacheid); |
1137 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1138 | } |
1139 | |
1140 | bn= COLnew(b->hseqbase, TYPE_oid, BATcount(b) , TRANSIENT); |
1141 | if (bn == NULL) { |
1142 | BBPunfix(b->batCacheid); |
1143 | BBPunfix(d->batCacheid); |
1144 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1145 | } |
1146 | res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false); |
1147 | BBPunfix(d->batCacheid); |
1148 | if (res != GDK_SUCCEED) { |
1149 | BBPunfix(b->batCacheid); |
1150 | BBPunfix(bn->batCacheid); |
1151 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1152 | } |
1153 | |
1154 | o = (oid*)Tloc(bs, 0); |
1155 | ol= (oid*)Tloc(bs, BUNlast(bs)); |
1156 | r = (oid*)Tloc(bn, 0); |
1157 | |
1158 | lim = BATcount(b); |
1159 | |
1160 | for (;oidx<lim; oidx++) { |
1161 | if ( o < ol && *o == oidx ){ |
1162 | o++; |
1163 | } else { |
1164 | *r++ = oidx; |
1165 | } |
1166 | } |
1167 | |
1168 | BATsetcount(bn, BATcount(b)-BATcount(bs)); |
1169 | bn->tsorted = false; |
1170 | bn->trevsorted = false; |
1171 | bn->tseqbase = oid_nil; |
1172 | |
1173 | |
1174 | BBPunfix(b->batCacheid); |
1175 | BBPunfix(bs->batCacheid); |
1176 | BBPkeepref(*ret= bn->batCacheid); |
1177 | return MAL_SUCCEED; |
1178 | } |
1179 | #endif /* unused */ |
1180 | |
1181 | /* |
1182 | * Shrinking a void-headed BAT using a list of oids to ignore. |
1183 | */ |
1184 | #define reuseloop(Type) \ |
1185 | do { \ |
1186 | Type *p = (Type*)Tloc(b, 0); \ |
1187 | Type *q = (Type*)Tloc(b, BUNlast(b)); \ |
1188 | Type *r = (Type*)Tloc(bn, 0); \ |
1189 | for (;p<q; oidx++, p++) { \ |
1190 | if ( *o == oidx ){ \ |
1191 | while ( ol>o && ol[-1] == bidx) { \ |
1192 | bidx--; \ |
1193 | q--; \ |
1194 | ol--; \ |
1195 | } \ |
1196 | *r++ = *(--q); \ |
1197 | o += (o < ol); \ |
1198 | bidx--; \ |
1199 | } else \ |
1200 | *r++ = *p; \ |
1201 | } \ |
1202 | } while (0) |
1203 | |
1204 | str |
1205 | BKCreuseBAT(bat *ret, const bat *bid, const bat *did) |
1206 | { |
1207 | BAT *b, *d, *bn, *bs; |
1208 | oid oidx = 0, bidx, *o, *ol; |
1209 | gdk_return res; |
1210 | |
1211 | if ((b = BATdescriptor(*bid)) == NULL) { |
1212 | throw(MAL, "bat.reuse" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1213 | } |
1214 | if ((d = BATdescriptor(*did)) == NULL) { |
1215 | BBPunfix(b->batCacheid); |
1216 | throw(MAL, "bat.reuse" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1217 | } |
1218 | bn= COLnew(b->hseqbase, b->ttype, BATcount(b) - BATcount(d), b->batRole); |
1219 | if (bn == NULL) { |
1220 | BBPunfix(b->batCacheid); |
1221 | BBPunfix(d->batCacheid); |
1222 | throw(MAL, "bat.reuse" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1223 | } |
1224 | res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false); |
1225 | BBPunfix(d->batCacheid); |
1226 | if (res != GDK_SUCCEED) { |
1227 | BBPunfix(b->batCacheid); |
1228 | BBPunfix(bn->batCacheid); |
1229 | throw(MAL, "bat.reuse" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1230 | } |
1231 | |
1232 | oidx = b->hseqbase; |
1233 | bidx = oidx + BATcount(b)-1; |
1234 | o = (oid*)Tloc(bs, 0); |
1235 | ol= (oid*)Tloc(bs, BUNlast(bs)); |
1236 | |
1237 | switch(ATOMstorage(b->ttype) ){ |
1238 | case TYPE_bte: reuseloop(bte); break; |
1239 | case TYPE_sht: reuseloop(sht); break; |
1240 | case TYPE_int: reuseloop(int); break; |
1241 | case TYPE_lng: reuseloop(lng); break; |
1242 | #ifdef HAVE_HGE |
1243 | case TYPE_hge: reuseloop(hge); break; |
1244 | #endif |
1245 | case TYPE_flt: reuseloop(flt); break; |
1246 | case TYPE_dbl: reuseloop(dbl); break; |
1247 | case TYPE_oid: reuseloop(oid); break; |
1248 | case TYPE_str: /* to be done based on its index width */ |
1249 | default: |
1250 | if (ATOMvarsized(bn->ttype)) { |
1251 | BUN p = 0; |
1252 | BUN q = BUNlast(b); |
1253 | BATiter bi = bat_iterator(b); |
1254 | |
1255 | for (;p<q; oidx++, p++) { |
1256 | if ( *o == oidx ){ |
1257 | while ( ol > o && ol[-1] == bidx) { |
1258 | bidx--; |
1259 | q--; |
1260 | ol--; |
1261 | } |
1262 | if (BUNappend(bn, BUNtail(bi, --q), false) != GDK_SUCCEED) { |
1263 | BBPunfix(b->batCacheid); |
1264 | BBPunfix(bn->batCacheid); |
1265 | throw(MAL, "bat.shrink" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1266 | } |
1267 | o += (o < ol); |
1268 | bidx--; |
1269 | } else { |
1270 | if (BUNappend(bn, BUNtail(bi, p), false) != GDK_SUCCEED) { |
1271 | BBPunfix(b->batCacheid); |
1272 | BBPunfix(bn->batCacheid); |
1273 | throw(MAL, "bat.shrink" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
1274 | } |
1275 | } |
1276 | } |
1277 | } else { |
1278 | switch( b->twidth){ |
1279 | case 1:reuseloop(bte); break; |
1280 | case 2:reuseloop(sht); break; |
1281 | case 4:reuseloop(int); break; |
1282 | case 8:reuseloop(lng); break; |
1283 | #ifdef HAVE_HGE |
1284 | case 16:reuseloop(hge); break; |
1285 | #endif |
1286 | default: |
1287 | BBPunfix(b->batCacheid); |
1288 | BBPunfix(bn->batCacheid); |
1289 | throw(MAL, "bat.shrink" , "Illegal argument type" ); |
1290 | } |
1291 | } |
1292 | } |
1293 | |
1294 | BATsetcount(bn, BATcount(b) - BATcount(bs)); |
1295 | bn->tsorted = false; |
1296 | bn->trevsorted = false; |
1297 | bn->tseqbase = oid_nil; |
1298 | bn->tkey = b->tkey; |
1299 | |
1300 | |
1301 | BBPunfix(b->batCacheid); |
1302 | BBPunfix(bs->batCacheid); |
1303 | BBPkeepref(*ret= bn->batCacheid); |
1304 | return MAL_SUCCEED; |
1305 | } |
1306 | |
1307 | str |
1308 | BKCreuseBATmap(bat *ret, const bat *bid, const bat *did) |
1309 | { |
1310 | BAT *b, *d, *bn, *bs; |
1311 | oid bidx, oidx = 0, *o, *ol; |
1312 | oid *r; |
1313 | gdk_return res; |
1314 | |
1315 | if ((b = BATdescriptor(*bid)) == NULL) { |
1316 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1317 | } |
1318 | if ((d = BATdescriptor(*did)) == NULL) { |
1319 | BBPunfix(b->batCacheid); |
1320 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1321 | } |
1322 | bn= COLnew(b->hseqbase, TYPE_oid, BATcount(b) - BATcount(d), TRANSIENT); |
1323 | if (bn == NULL) { |
1324 | BBPunfix(b->batCacheid); |
1325 | BBPunfix(d->batCacheid); |
1326 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1327 | } |
1328 | res = BATsort(&bs, NULL, NULL, d, NULL, NULL, false, false, false); |
1329 | BBPunfix(d->batCacheid); |
1330 | if (res != GDK_SUCCEED) { |
1331 | BBPunfix(b->batCacheid); |
1332 | BBPunfix(bn->batCacheid); |
1333 | throw(MAL, "bat.shrinkMap" , SQLSTATE(HY001) MAL_MALLOC_FAIL ); |
1334 | } |
1335 | |
1336 | oidx = b->hseqbase; |
1337 | bidx = oidx + BATcount(b)-1; |
1338 | o = (oid*)Tloc(bs, 0); |
1339 | ol = (oid*)Tloc(bs, BUNlast(bs)); |
1340 | r = (oid*)Tloc(bn, 0); |
1341 | |
1342 | for (; oidx <= bidx; oidx++) { |
1343 | if ( *o == oidx ){ |
1344 | while ( ol > o && ol[-1] == bidx) { |
1345 | bidx--; |
1346 | ol--; |
1347 | } |
1348 | *r++ = bidx; |
1349 | o += (o < ol); |
1350 | bidx--; |
1351 | } else { |
1352 | *r++ = oidx; |
1353 | } |
1354 | } |
1355 | |
1356 | BATsetcount(bn, BATcount(b)-BATcount(bs)); |
1357 | bn->tsorted = false; |
1358 | bn->trevsorted = false; |
1359 | bn->tseqbase = oid_nil; |
1360 | |
1361 | |
1362 | BBPunfix(b->batCacheid); |
1363 | BBPunfix(bs->batCacheid); |
1364 | BBPkeepref(*ret= bn->batCacheid); |
1365 | return MAL_SUCCEED; |
1366 | } |
1367 | |
1368 | str |
1369 | BKCmergecand(bat *ret, const bat *aid, const bat *bid) |
1370 | { |
1371 | BAT *a, *b, *bn; |
1372 | |
1373 | if ((a = BATdescriptor(*aid)) == NULL) { |
1374 | throw(MAL, "bat.mergecand" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1375 | } |
1376 | if ((b = BATdescriptor(*bid)) == NULL) { |
1377 | BBPunfix(a->batCacheid); |
1378 | throw(MAL, "bat.mergecand" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1379 | } |
1380 | bn = BATmergecand(a, b); |
1381 | BBPunfix(a->batCacheid); |
1382 | BBPunfix(b->batCacheid); |
1383 | if (bn == NULL) |
1384 | throw(MAL, "bat.mergecand" , OPERATION_FAILED); |
1385 | *ret = bn->batCacheid; |
1386 | BBPkeepref(*ret); |
1387 | return MAL_SUCCEED; |
1388 | } |
1389 | |
1390 | str |
1391 | BKCintersectcand(bat *ret, const bat *aid, const bat *bid) |
1392 | { |
1393 | BAT *a, *b, *bn; |
1394 | |
1395 | if ((a = BATdescriptor(*aid)) == NULL) { |
1396 | throw(MAL, "bat.intersectcand" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1397 | } |
1398 | if ((b = BATdescriptor(*bid)) == NULL) { |
1399 | BBPunfix(a->batCacheid); |
1400 | throw(MAL, "bat.intersectcand" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1401 | } |
1402 | bn = BATintersectcand(a, b); |
1403 | BBPunfix(a->batCacheid); |
1404 | BBPunfix(b->batCacheid); |
1405 | if (bn == NULL) |
1406 | throw(MAL, "bat.intersectcand" , OPERATION_FAILED); |
1407 | *ret = bn->batCacheid; |
1408 | BBPkeepref(*ret); |
1409 | return MAL_SUCCEED; |
1410 | } |
1411 | |
1412 | str |
1413 | BKCdiffcand(bat *ret, const bat *aid, const bat *bid) |
1414 | { |
1415 | BAT *a, *b, *bn; |
1416 | |
1417 | if ((a = BATdescriptor(*aid)) == NULL) { |
1418 | throw(MAL, "bat.diffcand" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1419 | } |
1420 | if ((b = BATdescriptor(*bid)) == NULL) { |
1421 | BBPunfix(a->batCacheid); |
1422 | throw(MAL, "bat.diffcand" , SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); |
1423 | } |
1424 | bn = BATdiffcand(a, b); |
1425 | BBPunfix(a->batCacheid); |
1426 | BBPunfix(b->batCacheid); |
1427 | if (bn == NULL) |
1428 | throw(MAL, "bat.diffcand" , OPERATION_FAILED); |
1429 | *ret = bn->batCacheid; |
1430 | BBPkeepref(*ret); |
1431 | return MAL_SUCCEED; |
1432 | } |
1433 | |