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 */
36static BAT *
37setaccess(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
57static char *
58pre(str s1, str s2)
59{
60 static char buf[64];
61
62 snprintf(buf, 64, "%s%s", s1, s2);
63 return buf;
64}
65static char *
66local_itoa(ssize_t i)
67{
68 static char buf[32];
69
70 snprintf(buf, 32, "%zd", i);
71 return buf;
72}
73static char *
74local_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
84static gdk_return
85HASHinfo(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
117static gdk_return
118infoHeap(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
149static inline char *
150oidtostr(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
168str
169BKCnewBAT(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
181str
182BKCattach(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
196str
197BKCdensebat(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
214str
215BKCmirror(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
233char *
234BKCdelete(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
250str
251BKCdelete_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
272str
273BKCdelete_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
289char *
290BKCappend_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
322char *
323BKCappend_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
328char *
329BKCappend_wrap(bat *r, const bat *bid, const bat *uid)
330{
331 return BKCappend_cand_force_wrap(r, bid, uid, NULL, NULL);
332}
333
334char *
335BKCappend_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
340str
341BKCappend_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
363str
364BKCappend_val_wrap(bat *r, const bat *bid, const void *u)
365{
366 return BKCappend_val_force_wrap(r, bid, u, NULL);
367}
368
369str
370BKCbun_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
384str
385BKCbun_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
400str
401BKCbat_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
428str
429BKCbat_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
438str
439BKCgetCapacity(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
451str
452BKCgetColumnType(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
469str
470BKCgetRole(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
484str
485BKCsetkey(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
511str
512BKCisSorted(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
524str
525BKCisSortedReverse(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
543str
544BKCgetKey(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
555static str
556BKCpersists(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
572str
573BKCsetPersistent(void *r, const bat *bid)
574{
575 bit flag= TRUE;
576 return BKCpersists(r, bid, &flag);
577}
578
579str
580BKCisPersistent(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
592str
593BKCsetTransient(void *r, const bat *bid)
594{
595 bit flag = FALSE;
596 return BKCpersists(r, bid, &flag);
597}
598
599str
600BKCisTransient(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
612str
613BKCsetAccess(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
641str
642BKCgetAccess(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 */
671str
672BKCinfo(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
805str
806BKCgetSize(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 */
832str
833BKCisSynced(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 */
853str
854BKCsetColumn(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
874str
875BKCsetName(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
911str
912BKCgetBBPname(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
924str
925BKCsave(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
946str
947BKCsave2(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 */
969str
970BKCsetHash(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
983str
984BKCsetImprints(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
997str
998BKCgetSequenceBase(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
1029str
1030BKCshrinkBAT(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
1124str
1125BKCshrinkBATmap(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
1204str
1205BKCreuseBAT(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
1307str
1308BKCreuseBATmap(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
1368str
1369BKCmergecand(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
1390str
1391BKCintersectcand(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
1412str
1413BKCdiffcand(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