Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * Peter Boncz, M.L. Kersten
15 : * Binary Association Tables
16 : * This module contains the commands and patterns to manage Binary
17 : * Association Tables (BATs). The relational operations you can execute
18 : * on BATs have the form of a neat algebra, described in algebra.c
19 : *
20 : * But a database system needs more that just this algebra, since often it
21 : * is crucial to do table-updates (this would not be permitted in a strict
22 : * algebra).
23 : *
24 : * All commands needed for BAT updates, property management, basic I/O,
25 : * persistence, and storage options can be found in this module.
26 : *
27 : * All parameters to the modules are passed by reference.
28 : * In particular, this means that string values are passed to the module
29 : * layer as (str *)
30 : * and we have to de-reference them before entering the gdk library.
31 : * (Actual a design error in gdk to differentiate passing int/str)
32 : * This calls for knowledge on the underlying BAT types`s
33 : */
34 :
35 : #include "monetdb_config.h"
36 : #include "bat5.h"
37 : #include "mal_exception.h"
38 :
39 : /*
40 : * The remainder contains the wrapper code over the mserver version 4
41 : * InformationFunctions
42 : * In most cases we pass a BAT identifier, which should be unified
43 : * with a BAT descriptor. Upon failure we can simply abort the function.
44 : *
45 : * The logical head type :oid is mapped to a TYPE_void
46 : * with sequenceBase. It represents the old fashioned :vid
47 : */
48 :
49 :
50 : #define derefStr(b, v) \
51 : do { \
52 : int _tpe= ATOMstorage((b)->ttype); \
53 : if (_tpe >= TYPE_str) { \
54 : if ((v) == 0 || *(str*) (v) == 0) \
55 : (v) = (str) str_nil; \
56 : else \
57 : (v) = *(str *) (v); \
58 : } \
59 : } while (0)
60 :
61 : str
62 208728 : BKCnewBAT(bat *res, const int *tt, const BUN *cap, role_t role)
63 : {
64 208728 : BAT *bn;
65 :
66 208728 : bn = COLnew(0, *tt, *cap, role);
67 208720 : if (bn == NULL)
68 0 : throw(MAL, "bat.new", GDK_EXCEPTION);
69 208720 : *res = bn->batCacheid;
70 208720 : bn->tkey = true; /* COLnew leaves it as false */
71 208720 : BBPretain(bn->batCacheid);
72 208664 : BBPunfix(bn->batCacheid);
73 208664 : return MAL_SUCCEED;
74 : }
75 :
76 : static str
77 0 : BKCattach(bat *ret, const int *tt, const char *const *heapfile)
78 : {
79 0 : BAT *bn;
80 :
81 0 : bn = BATattach(*tt, *heapfile, TRANSIENT);
82 0 : if (bn == NULL)
83 0 : throw(MAL, "bat.attach", GDK_EXCEPTION);
84 0 : *ret = bn->batCacheid;
85 0 : BBPkeepref(bn);
86 0 : return MAL_SUCCEED;
87 : }
88 :
89 : static str
90 0 : BKCdensebat(bat *ret, const lng *size)
91 : {
92 0 : BAT *bn;
93 0 : lng sz = *size;
94 :
95 0 : if (sz < 0)
96 : sz = 0;
97 : if (sz > (lng) BUN_MAX)
98 : sz = (lng) BUN_MAX;
99 0 : bn = BATdense(0, 0, (BUN) sz);
100 0 : if (bn == NULL)
101 0 : throw(MAL, "bat.densebat", GDK_EXCEPTION);
102 0 : *ret = bn->batCacheid;
103 0 : BBPkeepref(bn);
104 0 : return MAL_SUCCEED;
105 : }
106 :
107 : str
108 43067 : BKCmirror(bat *ret, const bat *bid)
109 : {
110 43067 : BAT *b, *bn;
111 :
112 43067 : *ret = 0;
113 43067 : if (!(b = BBPquickdesc(*bid)))
114 0 : throw(MAL, "bat.mirror", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
115 43067 : if (!(bn = BATdense(b->hseqbase, b->hseqbase, BATcount(b))))
116 0 : throw(MAL, "bat.mirror", GDK_EXCEPTION);
117 43065 : *ret = bn->batCacheid;
118 43065 : BBPkeepref(bn);
119 43065 : return MAL_SUCCEED;
120 : }
121 :
122 : static str
123 4 : BKCdelete(bat *r, const bat *bid, const oid *h)
124 : {
125 4 : BAT *b;
126 :
127 4 : if ((b = BATdescriptor(*bid)) == NULL)
128 0 : throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
129 4 : if (BUNdelete(b, *h) != GDK_SUCCEED) {
130 0 : BBPunfix(b->batCacheid);
131 0 : throw(MAL, "bat.delete", GDK_EXCEPTION);
132 : }
133 4 : *r = b->batCacheid;
134 4 : BBPretain(b->batCacheid);
135 4 : BBPunfix(b->batCacheid);
136 4 : return MAL_SUCCEED;
137 : }
138 :
139 : static str
140 4 : BKCdelete_multi(bat *r, const bat *bid, const bat *sid)
141 : {
142 4 : BAT *b, *s;
143 4 : gdk_return ret;
144 :
145 4 : if ((b = BATdescriptor(*bid)) == NULL)
146 0 : throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
147 4 : if ((s = BATdescriptor(*sid)) == NULL) {
148 0 : BBPunfix(b->batCacheid);
149 0 : throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
150 : }
151 4 : ret = BATdel(b, s);
152 4 : BBPunfix(s->batCacheid);
153 4 : if (ret != GDK_SUCCEED) {
154 0 : BBPunfix(b->batCacheid);
155 0 : throw(MAL, "bat.delete", GDK_EXCEPTION);
156 : }
157 4 : *r = b->batCacheid;
158 4 : BBPretain(b->batCacheid);
159 4 : BBPunfix(b->batCacheid);
160 4 : return MAL_SUCCEED;
161 : }
162 :
163 : static str
164 7 : BKCdelete_all(bat *r, const bat *bid)
165 : {
166 7 : BAT *b;
167 :
168 7 : if ((b = BATdescriptor(*bid)) == NULL)
169 0 : throw(MAL, "bat.delete", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
170 7 : if (BATclear(b, false) != GDK_SUCCEED) {
171 0 : BBPunfix(b->batCacheid);
172 0 : throw(MAL, "bat.delete", GDK_EXCEPTION);
173 : }
174 7 : *r = b->batCacheid;
175 7 : BBPretain(b->batCacheid);
176 7 : BBPunfix(b->batCacheid);
177 7 : return MAL_SUCCEED;
178 : }
179 :
180 : static str
181 118592 : BKCappend_cand_force_wrap(bat *r, const bat *bid, const bat *uid,
182 : const bat *sid, const bit *force)
183 : {
184 118592 : BAT *b, *u, *s = NULL;
185 118592 : gdk_return ret;
186 :
187 118592 : if ((b = BATdescriptor(*bid)) == NULL)
188 0 : throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
189 118575 : if (isVIEW(b)) {
190 9400 : BAT *bn = COLcopy(b, b->ttype, true, TRANSIENT);
191 9402 : MT_lock_set(&b->theaplock);
192 9402 : restrict_t mode = b->batRestricted;
193 9402 : MT_lock_unset(&b->theaplock);
194 9404 : BBPunfix(b->batCacheid);
195 9403 : if (bn == NULL || (b = BATsetaccess(bn, mode)) == NULL)
196 0 : throw(MAL, "bat.append", GDK_EXCEPTION);
197 : }
198 118578 : if ((u = BATdescriptor(*uid)) == NULL) {
199 0 : BBPunfix(b->batCacheid);
200 0 : throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
201 : }
202 118555 : if (mask_cand(u)) {
203 0 : BAT *ou = u;
204 0 : u = BATunmask(u);
205 0 : BBPunfix(ou->batCacheid);
206 0 : if (!u) {
207 0 : BBPunfix(b->batCacheid);
208 0 : throw(MAL, "bat.append", GDK_EXCEPTION);
209 : }
210 : }
211 118555 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
212 0 : BBPunfix(b->batCacheid);
213 0 : BBPunfix(u->batCacheid);
214 0 : throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
215 : }
216 118794 : ret = BATappend(b, u, s, force ? *force : false);
217 118583 : BBPunfix(u->batCacheid);
218 118577 : BBPreclaim(s);
219 118576 : if (ret != GDK_SUCCEED) {
220 0 : BBPunfix(b->batCacheid);
221 0 : throw(MAL, "bat.append", GDK_EXCEPTION);
222 : }
223 118576 : *r = b->batCacheid;
224 118576 : BBPretain(b->batCacheid);
225 118586 : BBPunfix(b->batCacheid);
226 118586 : return MAL_SUCCEED;
227 : }
228 :
229 : static str
230 0 : BKCappend_cand_wrap(bat *r, const bat *bid, const bat *uid, const bat *sid)
231 : {
232 0 : return BKCappend_cand_force_wrap(r, bid, uid, sid, NULL);
233 : }
234 :
235 : static str
236 239 : BKCappend_wrap(bat *r, const bat *bid, const bat *uid)
237 : {
238 239 : return BKCappend_cand_force_wrap(r, bid, uid, NULL, NULL);
239 : }
240 :
241 : static str
242 118352 : BKCappend_force_wrap(bat *r, const bat *bid, const bat *uid, const bit *force)
243 : {
244 118352 : return BKCappend_cand_force_wrap(r, bid, uid, NULL, force);
245 : }
246 :
247 : static str
248 15260540 : BKCappend_val_force_wrap(bat *r, const bat *bid, const void *u,
249 : const bit *force)
250 : {
251 15260540 : BAT *b;
252 :
253 15260540 : if ((b = BATdescriptor(*bid)) == NULL)
254 0 : throw(MAL, "bat.append", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
255 15260540 : if (isVIEW(b)) {
256 739 : BAT *bn = COLcopy(b, b->ttype, true, TRANSIENT);
257 739 : MT_lock_set(&b->theaplock);
258 739 : restrict_t mode = b->batRestricted;
259 739 : MT_lock_unset(&b->theaplock);
260 739 : BBPunfix(b->batCacheid);
261 739 : if (bn == NULL || (b = BATsetaccess(bn, mode)) == NULL)
262 0 : throw(MAL, "bat.append", GDK_EXCEPTION);
263 : }
264 15260540 : derefStr(b, u);
265 30518853 : if (BUNappend(b, u, force ? *force : false) != GDK_SUCCEED) {
266 0 : BBPunfix(b->batCacheid);
267 0 : throw(MAL, "bat.append", GDK_EXCEPTION);
268 : }
269 15260540 : *r = b->batCacheid;
270 15260540 : BBPretain(b->batCacheid);
271 15260540 : BBPunfix(b->batCacheid);
272 15260540 : return MAL_SUCCEED;
273 : }
274 :
275 : static str
276 15258313 : BKCappend_val_wrap(bat *r, const bat *bid, const void *u)
277 : {
278 15258313 : return BKCappend_val_force_wrap(r, bid, u, NULL);
279 : }
280 :
281 : static str
282 103 : BKCbun_inplace(bat *r, const bat *bid, const oid *id, const void *t)
283 : {
284 103 : BAT *b;
285 :
286 103 : if ((b = BATdescriptor(*bid)) == NULL)
287 0 : throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
288 103 : derefStr(b, t);
289 103 : if (void_inplace(b, *id, t, false) != GDK_SUCCEED) {
290 0 : BBPunfix(b->batCacheid);
291 0 : throw(MAL, "bat.inplace", GDK_EXCEPTION);
292 : }
293 103 : *r = b->batCacheid;
294 103 : BBPretain(b->batCacheid);
295 103 : BBPunfix(b->batCacheid);
296 103 : return MAL_SUCCEED;
297 : }
298 :
299 : static str
300 0 : BKCbun_inplace_force(bat *r, const bat *bid, const oid *id, const void *t,
301 : const bit *force)
302 : {
303 0 : BAT *b;
304 :
305 0 : if ((b = BATdescriptor(*bid)) == NULL)
306 0 : throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
307 0 : derefStr(b, t);
308 0 : if (void_inplace(b, *id, t, *force) != GDK_SUCCEED) {
309 0 : BBPunfix(b->batCacheid);
310 0 : throw(MAL, "bat.inplace", GDK_EXCEPTION);
311 : }
312 0 : *r = b->batCacheid;
313 0 : BBPretain(b->batCacheid);
314 0 : BBPunfix(b->batCacheid);
315 0 : return MAL_SUCCEED;
316 : }
317 :
318 :
319 : static str
320 69508 : BKCbat_inplace_force(bat *r, const bat *bid, const bat *rid, const bat *uid,
321 : const bit *force)
322 : {
323 69508 : BAT *b, *p, *u;
324 :
325 69508 : if ((b = BATdescriptor(*bid)) == NULL)
326 0 : throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
327 69508 : if ((p = BATdescriptor(*rid)) == NULL) {
328 0 : BBPunfix(b->batCacheid);
329 0 : throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
330 : }
331 69505 : if ((u = BATdescriptor(*uid)) == NULL) {
332 0 : BBPunfix(b->batCacheid);
333 0 : BBPunfix(p->batCacheid);
334 0 : throw(MAL, "bat.inplace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
335 : }
336 69504 : if (BATreplace(b, p, u, *force) != GDK_SUCCEED) {
337 0 : BBPunfix(b->batCacheid);
338 0 : BBPunfix(p->batCacheid);
339 0 : BBPunfix(u->batCacheid);
340 0 : throw(MAL, "bat.inplace", GDK_EXCEPTION);
341 : }
342 69503 : *r = b->batCacheid;
343 69503 : BBPretain(b->batCacheid);
344 69506 : BBPunfix(b->batCacheid);
345 69498 : BBPunfix(p->batCacheid);
346 69497 : BBPunfix(u->batCacheid);
347 69497 : return MAL_SUCCEED;
348 : }
349 :
350 : static str
351 2 : BKCbat_inplace(bat *r, const bat *bid, const bat *rid, const bat *uid)
352 : {
353 2 : bit F = FALSE;
354 :
355 2 : return BKCbat_inplace_force(r, bid, rid, uid, &F);
356 : }
357 :
358 : /*end of SQL enhancement */
359 :
360 : static str
361 0 : BKCgetCapacity(lng *res, const bat *bid)
362 : {
363 0 : *res = lng_nil;
364 0 : BAT *b = BBPquickdesc(*bid);
365 :
366 0 : if (b == NULL)
367 0 : throw(MAL, "bat.getCapacity", ILLEGAL_ARGUMENT);
368 0 : *res = (lng) BATcapacity(b);
369 0 : return MAL_SUCCEED;
370 : }
371 :
372 : static str
373 0 : BKCgetColumnType(str *res, const bat *bid)
374 : {
375 0 : const char *ret = str_nil;
376 0 : BAT *b = BBPquickdesc(*bid);
377 :
378 0 : if (b == NULL)
379 0 : throw(MAL, "bat.getColumnType", ILLEGAL_ARGUMENT);
380 0 : ret = *bid < 0 ? ATOMname(TYPE_void) : ATOMname(b->ttype);
381 0 : *res = GDKstrdup(ret);
382 0 : if (*res == NULL)
383 0 : throw(MAL, "bat.getColumnType", SQLSTATE(HY013) MAL_MALLOC_FAIL);
384 : return MAL_SUCCEED;
385 : }
386 :
387 : static str
388 0 : BKCisSorted(bit *res, const bat *bid)
389 : {
390 0 : BAT *b;
391 :
392 0 : if ((b = BATdescriptor(*bid)) == NULL) {
393 0 : throw(MAL, "bat.isSorted", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
394 : }
395 0 : *res = BATordered(b);
396 0 : BBPunfix(b->batCacheid);
397 0 : return MAL_SUCCEED;
398 : }
399 :
400 : static str
401 0 : BKCisSortedReverse(bit *res, const bat *bid)
402 : {
403 0 : BAT *b;
404 :
405 0 : if ((b = BATdescriptor(*bid)) == NULL) {
406 0 : throw(MAL, "bat.isSorted", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
407 : }
408 0 : *res = BATordered_rev(b);
409 0 : BBPunfix(b->batCacheid);
410 0 : return MAL_SUCCEED;
411 : }
412 :
413 : /*
414 : * We must take care of the special case of a nil column (TYPE_void,seqbase=nil)
415 : * such nil columns never set tkey
416 : * a nil column of a BAT with <= 1 entries does not contain doubles => return TRUE.
417 : */
418 :
419 : static str
420 0 : BKCgetKey(bit *ret, const bat *bid)
421 : {
422 0 : BAT *b;
423 :
424 0 : if ((b = BATdescriptor(*bid)) == NULL)
425 0 : throw(MAL, "bat.setPersistence",
426 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
427 0 : MT_lock_set(&b->theaplock);
428 0 : *ret = b->tkey;
429 0 : MT_lock_unset(&b->theaplock);
430 0 : BBPunfix(b->batCacheid);
431 0 : return MAL_SUCCEED;
432 : }
433 :
434 : static str
435 2 : BKCpersists(void *r, const bat *bid, const bit *flg)
436 : {
437 2 : BAT *b;
438 :
439 2 : (void) r;
440 2 : if ((b = BATdescriptor(*bid)) == NULL) {
441 0 : throw(MAL, "bat.setPersistence",
442 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
443 : }
444 2 : if (BATmode(b, (*flg != TRUE)) != GDK_SUCCEED) {
445 0 : BBPunfix(b->batCacheid);
446 0 : throw(MAL, "bat.setPersistence", ILLEGAL_ARGUMENT);
447 : }
448 2 : BBPunfix(b->batCacheid);
449 2 : return MAL_SUCCEED;
450 : }
451 :
452 : static str
453 1 : BKCsetPersistent(void *r, const bat *bid)
454 : {
455 1 : bit flag = TRUE;
456 1 : return BKCpersists(r, bid, &flag);
457 : }
458 :
459 : static str
460 2 : BKCisPersistent(bit *res, const bat *bid)
461 : {
462 2 : BAT *b;
463 :
464 2 : if ((b = BATdescriptor(*bid)) == NULL) {
465 0 : throw(MAL, "bat.setPersistence",
466 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
467 : }
468 2 : MT_lock_set(&b->theaplock);
469 2 : *res = !b->batTransient;
470 2 : MT_lock_unset(&b->theaplock);
471 2 : BBPunfix(b->batCacheid);
472 2 : return MAL_SUCCEED;
473 : }
474 :
475 : static str
476 1 : BKCsetTransient(void *r, const bat *bid)
477 : {
478 1 : bit flag = FALSE;
479 1 : return BKCpersists(r, bid, &flag);
480 : }
481 :
482 : static str
483 2 : BKCisTransient(bit *res, const bat *bid)
484 : {
485 2 : BAT *b;
486 :
487 2 : if ((b = BATdescriptor(*bid)) == NULL) {
488 0 : throw(MAL, "bat.setTransient", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
489 : }
490 2 : MT_lock_set(&b->theaplock);
491 2 : *res = b->batTransient;
492 2 : MT_lock_unset(&b->theaplock);
493 2 : BBPunfix(b->batCacheid);
494 2 : return MAL_SUCCEED;
495 : }
496 :
497 : static str
498 3 : BKCsetAccess(bat *res, const bat *bid, const char *const *param)
499 : {
500 3 : BAT *b;
501 3 : restrict_t m;
502 :
503 3 : if ((b = BATdescriptor(*bid)) == NULL)
504 0 : throw(MAL, "bat.setAccess", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
505 3 : switch (*param[0]) {
506 : case 'r':
507 : m = BAT_READ;
508 : break;
509 0 : case 'a':
510 0 : m = BAT_APPEND;
511 0 : break;
512 0 : case 'w':
513 0 : m = BAT_WRITE;
514 0 : break;
515 0 : default:
516 0 : *res = 0;
517 0 : BBPunfix(b->batCacheid);
518 0 : throw(MAL, "bat.setAccess",
519 : ILLEGAL_ARGUMENT " Got %c" " expected 'r','a', or 'w'",
520 0 : *param[0]);
521 : }
522 3 : if ((b = BATsetaccess(b, m)) == NULL)
523 0 : throw(MAL, "bat.setAccess", OPERATION_FAILED);
524 3 : *res = b->batCacheid;
525 3 : BBPretain(b->batCacheid);
526 3 : BBPunfix(b->batCacheid);
527 3 : return MAL_SUCCEED;
528 : }
529 :
530 : static str
531 0 : BKCgetAccess(str *res, const bat *bid)
532 : {
533 0 : BAT *b;
534 :
535 0 : if ((b = BATdescriptor(*bid)) == NULL)
536 0 : throw(MAL, "bat.getAccess", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
537 0 : switch (BATgetaccess(b)) {
538 0 : case BAT_READ:
539 0 : *res = GDKstrdup("read");
540 0 : break;
541 0 : case BAT_APPEND:
542 0 : *res = GDKstrdup("append");
543 0 : break;
544 0 : case BAT_WRITE:
545 0 : *res = GDKstrdup("write");
546 0 : break;
547 : default:
548 0 : MT_UNREACHABLE();
549 : }
550 0 : BBPunfix(b->batCacheid);
551 0 : if (*res == NULL)
552 0 : throw(MAL, "bat.getAccess", SQLSTATE(HY013) MAL_MALLOC_FAIL);
553 : return MAL_SUCCEED;
554 : }
555 :
556 : /*
557 : * Property management
558 : * All property operators should ensure exclusive access to the BAT
559 : * descriptor.
560 : * Where necessary use the primary view to access the properties
561 : */
562 : static inline char *
563 0 : pre(const char *s1, const char *s2, char *buf)
564 : {
565 0 : snprintf(buf, 64, "%s%s", s1, s2);
566 0 : return buf;
567 : }
568 :
569 : static inline char *
570 0 : local_itoa(ssize_t i, char *buf)
571 : {
572 0 : snprintf(buf, 32, "%zd", i);
573 0 : return buf;
574 : }
575 :
576 : static inline char *
577 0 : local_utoa(size_t i, char *buf)
578 : {
579 0 : snprintf(buf, 32, "%zu", i);
580 0 : return buf;
581 : }
582 :
583 : static inline char *
584 0 : oidtostr(oid i, char *p, size_t len)
585 : {
586 0 : if (OIDtoStr(&p, &len, &i, false) < 0)
587 : return NULL;
588 0 : return p;
589 : }
590 :
591 : static gdk_return
592 0 : infoHeap(BAT *bk, BAT *bv, Heap *hp, str nme)
593 : {
594 0 : char buf[1024], *p = buf;
595 :
596 0 : if (!hp)
597 : return GDK_SUCCEED;
598 0 : while (*nme)
599 0 : *p++ = *nme++;
600 0 : strcpy(p, "free");
601 0 : if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
602 0 : BUNappend(bv, local_utoa(hp->free, buf), false) != GDK_SUCCEED)
603 0 : return GDK_FAIL;
604 0 : strcpy(p, "size");
605 0 : if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
606 0 : BUNappend(bv, local_utoa(hp->size, buf), false) != GDK_SUCCEED)
607 0 : return GDK_FAIL;
608 0 : strcpy(p, "storage");
609 0 : if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
610 0 : 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)
611 0 : return GDK_FAIL;
612 0 : strcpy(p, "newstorage");
613 0 : if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
614 0 : BUNappend(bv, (hp->newstorage == STORE_MEM) ? "malloced" : (hp->newstorage == STORE_PRIV) ? "private map" : "memory mapped", false) != GDK_SUCCEED)
615 0 : return GDK_FAIL;
616 0 : strcpy(p, "filename");
617 0 : if (BUNappend(bk, buf, false) != GDK_SUCCEED ||
618 0 : BUNappend(bv, hp->filename[0] ? hp->filename : "no file",
619 : false) != GDK_SUCCEED)
620 0 : return GDK_FAIL;
621 : return GDK_SUCCEED;
622 : }
623 :
624 : #define COLLISION (8 * sizeof(size_t))
625 :
626 : static gdk_return
627 0 : HASHinfo(BAT *bk, BAT *bv, Hash *h, str s)
628 : {
629 0 : BUN i;
630 0 : BUN j;
631 0 : BUN k;
632 0 : BUN cnt[COLLISION + 1];
633 0 : char buf[32];
634 0 : char prebuf[64];
635 :
636 0 : if (BUNappend(bk, pre(s, "type", prebuf), false) != GDK_SUCCEED ||
637 0 : BUNappend(bv, ATOMname(h->type), false) != GDK_SUCCEED ||
638 0 : BUNappend(bk, pre(s, "mask", prebuf), false) != GDK_SUCCEED ||
639 0 : BUNappend(bv, local_utoa(h->nbucket, buf), false) != GDK_SUCCEED)
640 0 : return GDK_FAIL;
641 :
642 0 : for (i = 0; i < COLLISION + 1; i++) {
643 0 : cnt[i] = 0;
644 : }
645 0 : for (i = 0; i < h->nbucket; i++) {
646 0 : j = HASHlist(h, i);
647 0 : for (k = 0; j; k++)
648 0 : j >>= 1;
649 0 : cnt[k]++;
650 : }
651 :
652 0 : for (i = 0; i < COLLISION + 1; i++)
653 0 : if (cnt[i]) {
654 0 : if (BUNappend(bk,
655 0 : pre(s, local_utoa(i ? (((size_t) 1) << (i - 1)) : 0,
656 : buf),
657 : prebuf),
658 : false) != GDK_SUCCEED
659 0 : || BUNappend(bv, local_utoa((size_t) cnt[i], buf),
660 : false) != GDK_SUCCEED)
661 0 : return GDK_FAIL;
662 : }
663 : return GDK_SUCCEED;
664 : }
665 :
666 : static str
667 0 : BKCinfo(bat *ret1, bat *ret2, const bat *bid)
668 : {
669 0 : const char *mode, *accessmode;
670 0 : BAT *bk = NULL, *bv = NULL, *b;
671 0 : char bf[oidStrlen];
672 0 : char buf[32];
673 :
674 0 : if ((b = BATdescriptor(*bid)) == NULL) {
675 0 : throw(MAL, "bat.info", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
676 : }
677 :
678 0 : bk = COLnew(0, TYPE_str, 128, TRANSIENT);
679 0 : bv = COLnew(0, TYPE_str, 128, TRANSIENT);
680 0 : if (bk == NULL || bv == NULL) {
681 0 : BBPreclaim(bk);
682 0 : BBPreclaim(bv);
683 0 : BBPunfix(b->batCacheid);
684 0 : throw(MAL, "bat.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
685 : }
686 :
687 0 : BATiter bi = bat_iterator(b);
688 0 : if (bi.transient) {
689 : mode = "transient";
690 : } else {
691 0 : mode = "persistent";
692 : }
693 :
694 0 : switch (bi.restricted) {
695 : case BAT_READ:
696 : accessmode = "read-only";
697 : break;
698 0 : case BAT_WRITE:
699 0 : accessmode = "updatable";
700 0 : break;
701 0 : case BAT_APPEND:
702 0 : accessmode = "append-only";
703 0 : break;
704 0 : default:
705 0 : accessmode = "unknown";
706 : }
707 :
708 0 : if (BUNappend(bk, "batId", false) != GDK_SUCCEED
709 0 : || BUNappend(bv, BATgetId(b), false) != GDK_SUCCEED
710 0 : || BUNappend(bk, "batCacheid", false) != GDK_SUCCEED
711 0 : || BUNappend(bv, local_itoa((ssize_t) b->batCacheid, buf),
712 : false) != GDK_SUCCEED
713 0 : || BUNappend(bk, "tparentid", false) != GDK_SUCCEED
714 0 : || BUNappend(bv, local_itoa((ssize_t) bi.h->parentid, buf),
715 : false) != GDK_SUCCEED
716 0 : || BUNappend(bk, "batCount", false) != GDK_SUCCEED
717 0 : || BUNappend(bv, local_utoa((size_t) bi.count, buf),
718 : false) != GDK_SUCCEED
719 0 : || BUNappend(bk, "batCapacity", false) != GDK_SUCCEED
720 0 : || BUNappend(bv, local_utoa((size_t) b->batCapacity, buf),
721 : false) != GDK_SUCCEED
722 0 : || BUNappend(bk, "head", false) != GDK_SUCCEED
723 0 : || BUNappend(bv, ATOMname(TYPE_void), false) != GDK_SUCCEED
724 0 : || BUNappend(bk, "tail", false) != GDK_SUCCEED
725 0 : || BUNappend(bv, ATOMname(bi.type), false) != GDK_SUCCEED
726 0 : || BUNappend(bk, "batPersistence", false) != GDK_SUCCEED
727 0 : || BUNappend(bv, mode, false) != GDK_SUCCEED
728 0 : || BUNappend(bk, "batRestricted", false) != GDK_SUCCEED
729 0 : || BUNappend(bv, accessmode, false) != GDK_SUCCEED
730 0 : || BUNappend(bk, "batRefcnt", false) != GDK_SUCCEED
731 0 : || BUNappend(bv, local_itoa((ssize_t) BBP_refs(b->batCacheid), buf),
732 : false) != GDK_SUCCEED
733 0 : || BUNappend(bk, "batLRefcnt", false) != GDK_SUCCEED
734 0 : || BUNappend(bv, local_itoa((ssize_t) BBP_lrefs(b->batCacheid), buf),
735 : false) != GDK_SUCCEED
736 0 : || BUNappend(bk, "batDirty", false) != GDK_SUCCEED
737 0 : || BUNappend(bv, BATdirtybi(bi) ? "dirty" : "clean",
738 : false) != GDK_SUCCEED
739 0 : || BUNappend(bk, "hseqbase", false) != GDK_SUCCEED
740 0 : || BUNappend(bv, oidtostr(b->hseqbase, bf, sizeof(bf)),
741 : FALSE) != GDK_SUCCEED
742 0 : || BUNappend(bk, "tdense", false) != GDK_SUCCEED
743 0 : || BUNappend(bv, local_itoa((ssize_t) BATtdensebi(&bi), buf),
744 : false) != GDK_SUCCEED
745 0 : || BUNappend(bk, "tseqbase", false) != GDK_SUCCEED
746 0 : || BUNappend(bv, oidtostr(bi.tseq, bf, sizeof(bf)),
747 : FALSE) != GDK_SUCCEED
748 0 : || BUNappend(bk, "tsorted", false) != GDK_SUCCEED
749 0 : || BUNappend(bv, local_itoa((ssize_t) bi.sorted, buf),
750 : false) != GDK_SUCCEED
751 0 : || BUNappend(bk, "trevsorted", false) != GDK_SUCCEED
752 0 : || BUNappend(bv, local_itoa((ssize_t) bi.revsorted, buf),
753 : false) != GDK_SUCCEED
754 0 : || BUNappend(bk, "tkey", false) != GDK_SUCCEED
755 0 : || BUNappend(bv, local_itoa((ssize_t) bi.key, buf),
756 : false) != GDK_SUCCEED
757 0 : || BUNappend(bk, "tvarsized", false) != GDK_SUCCEED
758 0 : || BUNappend(bv,
759 0 : local_itoa((ssize_t)
760 : (bi.type == TYPE_void
761 0 : || bi.vh != NULL), buf), false) != GDK_SUCCEED
762 0 : || BUNappend(bk, "tnosorted", false) != GDK_SUCCEED
763 0 : || BUNappend(bv, local_utoa(bi.nosorted, buf), false) != GDK_SUCCEED
764 0 : || BUNappend(bk, "tnorevsorted", false) != GDK_SUCCEED
765 0 : || BUNappend(bv, local_utoa(bi.norevsorted, buf), false) != GDK_SUCCEED
766 0 : || BUNappend(bk, "tnokey[0]", false) != GDK_SUCCEED
767 0 : || BUNappend(bv, local_utoa(bi.nokey[0], buf), false) != GDK_SUCCEED
768 0 : || BUNappend(bk, "tnokey[1]", false) != GDK_SUCCEED
769 0 : || BUNappend(bv, local_utoa(bi.nokey[1], buf), false) != GDK_SUCCEED
770 0 : || BUNappend(bk, "tnonil", false) != GDK_SUCCEED
771 0 : || BUNappend(bv, local_utoa(bi.nonil, buf), false) != GDK_SUCCEED
772 0 : || BUNappend(bk, "tnil", false) != GDK_SUCCEED
773 0 : || BUNappend(bv, local_utoa(bi.nil, buf), false) != GDK_SUCCEED
774 0 : || BUNappend(bk, "batInserted", false) != GDK_SUCCEED
775 0 : || BUNappend(bv, local_utoa(b->batInserted, buf), false) != GDK_SUCCEED
776 0 : || BUNappend(bk, "ttop", false) != GDK_SUCCEED
777 0 : || BUNappend(bv, local_utoa(bi.hfree, buf), false) != GDK_SUCCEED
778 0 : || BUNappend(bk, "batCopiedtodisk", false) != GDK_SUCCEED
779 0 : || BUNappend(bv, local_itoa((ssize_t) bi.copiedtodisk, buf),
780 : false) != GDK_SUCCEED
781 0 : || BUNappend(bk, "theap.dirty", false) != GDK_SUCCEED
782 0 : || BUNappend(bv, bi.hdirty ? "dirty" : "clean", false) != GDK_SUCCEED
783 0 : || infoHeap(bk, bv, bi.h, "tail.") != GDK_SUCCEED
784 0 : || BUNappend(bk, "tvheap->dirty", false) != GDK_SUCCEED
785 0 : || BUNappend(bv, bi.vhdirty ? "dirty" : "clean", false) != GDK_SUCCEED
786 0 : || infoHeap(bk, bv, bi.vh, "theap.") != GDK_SUCCEED) {
787 0 : bat_iterator_end(&bi);
788 0 : BBPreclaim(bk);
789 0 : BBPreclaim(bv);
790 0 : BBPunfix(b->batCacheid);
791 0 : throw(MAL, "bat.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
792 : }
793 : /* dump index information */
794 0 : MT_rwlock_rdlock(&b->thashlock);
795 0 : if (b->thash && HASHinfo(bk, bv, b->thash, "thash->") != GDK_SUCCEED) {
796 0 : MT_rwlock_rdunlock(&b->thashlock);
797 0 : bat_iterator_end(&bi);
798 0 : BBPreclaim(bk);
799 0 : BBPreclaim(bv);
800 0 : BBPunfix(b->batCacheid);
801 0 : throw(MAL, "bat.info", SQLSTATE(HY013) MAL_MALLOC_FAIL);
802 : }
803 0 : MT_rwlock_rdunlock(&b->thashlock);
804 0 : bat_iterator_end(&bi);
805 0 : assert(BATcount(bk) == BATcount(bv));
806 0 : BBPunfix(b->batCacheid);
807 0 : *ret1 = bk->batCacheid;
808 0 : BBPkeepref(bk);
809 0 : *ret2 = bv->batCacheid;
810 0 : BBPkeepref(bv);
811 0 : return MAL_SUCCEED;
812 : }
813 :
814 : // get the actual size of all constituents, also for views
815 : #define ROUND_UP(x,y) ((y)*(((x)+(y)-1)/(y)))
816 :
817 : static str
818 0 : BKCgetSize(lng *tot, const bat *bid)
819 : {
820 0 : BAT *b;
821 0 : lng size = 0;
822 0 : lng blksize = (lng) MT_pagesize();
823 0 : if ((b = BATdescriptor(*bid)) == NULL) {
824 0 : throw(MAL, "bat.getDiskSize", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
825 : }
826 :
827 0 : size = sizeof(bat);
828 :
829 0 : MT_lock_set(&b->theaplock);
830 0 : if (!isVIEW(b)) {
831 0 : BUN cnt = BATcapacity(b);
832 0 : size += ROUND_UP(b->theap->free, blksize);
833 0 : if (b->tvheap)
834 0 : size += ROUND_UP(b->tvheap->free, blksize);
835 0 : MT_lock_unset(&b->theaplock);
836 :
837 0 : if (b->thash)
838 0 : size += ROUND_UP(sizeof(BUN) * cnt, blksize);
839 0 : size += IMPSimprintsize(b);
840 : } else {
841 0 : MT_lock_unset(&b->theaplock);
842 : }
843 0 : *tot = size;
844 0 : BBPunfix(*bid);
845 0 : return MAL_SUCCEED;
846 : }
847 :
848 : static str
849 3 : BKCgetVHeapSize(lng *tot, const bat *bid)
850 : {
851 3 : BAT *b;
852 3 : lng size = 0;
853 3 : if ((b = BATdescriptor(*bid)) == NULL) {
854 0 : throw(MAL, "bat.getVHeapSize", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
855 : }
856 3 : if (ATOMvarsized(b->ttype)) {
857 3 : MT_lock_set(&b->theaplock);
858 3 : if (b->tvheap)
859 3 : size += b->tvheap->size;
860 3 : MT_lock_unset(&b->theaplock);
861 : }
862 :
863 3 : *tot = size;
864 3 : BBPunfix(*bid);
865 3 : return MAL_SUCCEED;
866 : }
867 :
868 : /*
869 : * Synced BATs
870 : */
871 : static str
872 0 : BKCisSynced(bit *ret, const bat *bid1, const bat *bid2)
873 : {
874 0 : BAT *b1, *b2;
875 :
876 0 : if ((b1 = BATdescriptor(*bid1)) == NULL) {
877 0 : throw(MAL, "bat.isSynced", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
878 : }
879 0 : if ((b2 = BATdescriptor(*bid2)) == NULL) {
880 0 : BBPunfix(b1->batCacheid);
881 0 : throw(MAL, "bat.isSynced", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
882 : }
883 0 : *ret = ALIGNsynced(b1, b2) != 0;
884 0 : BBPunfix(b1->batCacheid);
885 0 : BBPunfix(b2->batCacheid);
886 0 : return MAL_SUCCEED;
887 : }
888 :
889 : /*
890 : * Role Management
891 : */
892 : static str
893 9 : BKCsetName(void *r, const bat *bid, const char *const *s)
894 : {
895 9 : BAT *b;
896 9 : int ret;
897 9 : int c;
898 9 : const char *t = *s;
899 :
900 9 : (void) r;
901 9 : if ((b = BATdescriptor(*bid)) == NULL)
902 0 : throw(MAL, "bat.setName", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
903 :
904 52 : for (; (c = *t) != 0; t++)
905 43 : if (c != '_' && !GDKisalnum(c)) {
906 0 : BBPunfix(b->batCacheid);
907 0 : throw(MAL, "bat.setName",
908 : ILLEGAL_ARGUMENT ": identifier expected: %s", *s);
909 : }
910 :
911 9 : t = *s;
912 9 : ret = BBPrename(b, t);
913 9 : BBPunfix(b->batCacheid);
914 9 : switch (ret) {
915 0 : case BBPRENAME_ILLEGAL:
916 0 : GDKclrerr();
917 0 : throw(MAL, "bat.setName",
918 : ILLEGAL_ARGUMENT ": illegal temporary name: '%s'", t);
919 0 : case BBPRENAME_LONG:
920 0 : GDKclrerr();
921 0 : throw(MAL, "bat.setName", ILLEGAL_ARGUMENT ": name too long: '%s'", t);
922 0 : case BBPRENAME_MEMORY:
923 0 : GDKclrerr();
924 0 : throw(MAL, "bat.setName", SQLSTATE(HY013) MAL_MALLOC_FAIL);
925 1 : case BBPRENAME_ALREADY:
926 1 : GDKclrerr();
927 : /* fall through */
928 : case 0:
929 : break;
930 : }
931 : return MAL_SUCCEED;
932 : }
933 :
934 : static str
935 0 : BKCgetBBPname(str *ret, const bat *bid)
936 : {
937 0 : BAT *b;
938 :
939 0 : if ((b = BATdescriptor(*bid)) == NULL) {
940 0 : throw(MAL, "bat.getName", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
941 : }
942 0 : *ret = GDKstrdup(BBP_logical(b->batCacheid));
943 0 : BBPunfix(b->batCacheid);
944 0 : return *ret ? MAL_SUCCEED : createException(MAL, "bat.getName",
945 : SQLSTATE(HY013)
946 : MAL_MALLOC_FAIL);
947 : }
948 :
949 : static str
950 0 : BKCsave(bit *res, const char *const *input)
951 : {
952 0 : bat bid = BBPindex(*input);
953 0 : BAT *b;
954 :
955 0 : *res = FALSE;
956 0 : if (!is_bat_nil(bid)) {
957 0 : if (BBPfix(bid) > 0) {
958 0 : b = BBP_cache(bid);
959 0 : if (b && BATdirty(b)) {
960 0 : if (BBPsave(b) == GDK_SUCCEED)
961 0 : *res = TRUE;
962 : }
963 0 : BBPunfix(bid);
964 0 : return MAL_SUCCEED;
965 : }
966 0 : throw(MAL, "bat.save", "fix failed");
967 : }
968 : return MAL_SUCCEED;
969 : }
970 :
971 : static str
972 0 : BKCsave2(void *r, const bat *bid)
973 : {
974 0 : BAT *b;
975 :
976 0 : (void) r;
977 0 : if ((b = BATdescriptor(*bid)) == NULL) {
978 0 : throw(MAL, "bat.save", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
979 : }
980 0 : MT_lock_set(&b->theaplock);
981 0 : if (!b->batTransient) {
982 0 : MT_lock_unset(&b->theaplock);
983 0 : BBPunfix(b->batCacheid);
984 0 : throw(MAL, "bat.save", "Only save transient columns.");
985 : }
986 0 : MT_lock_unset(&b->theaplock);
987 :
988 0 : if (b && BATdirty(b))
989 0 : BBPsave(b);
990 0 : BBPunfix(b->batCacheid);
991 0 : return MAL_SUCCEED;
992 : }
993 :
994 : /*
995 : * Accelerator Control
996 : */
997 : static str
998 0 : BKCsetHash(bit *ret, const bat *bid)
999 : {
1000 0 : BAT *b;
1001 :
1002 0 : (void) ret;
1003 0 : if ((b = BATdescriptor(*bid)) == NULL) {
1004 0 : throw(MAL, "bat.setHash", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1005 : }
1006 0 : *ret = BAThash(b) == GDK_SUCCEED;
1007 0 : BBPunfix(b->batCacheid);
1008 0 : return MAL_SUCCEED;
1009 : }
1010 :
1011 : static str
1012 0 : BKCsetImprints(bit *ret, const bat *bid)
1013 : {
1014 0 : BAT *b;
1015 :
1016 0 : (void) ret;
1017 0 : if ((b = BATdescriptor(*bid)) == NULL) {
1018 0 : throw(MAL, "bat.setImprints", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1019 : }
1020 0 : *ret = BATimprints(b) == GDK_SUCCEED;
1021 0 : BBPunfix(b->batCacheid);
1022 0 : return MAL_SUCCEED;
1023 : }
1024 :
1025 : static str
1026 0 : BKCgetSequenceBase(oid *r, const bat *bid)
1027 : {
1028 0 : BAT *b;
1029 :
1030 0 : if ((b = BATdescriptor(*bid)) == NULL) {
1031 0 : throw(MAL, "bat.setSequenceBase",
1032 : SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1033 : }
1034 0 : *r = b->hseqbase;
1035 0 : BBPunfix(b->batCacheid);
1036 0 : return MAL_SUCCEED;
1037 : }
1038 :
1039 : static str
1040 78201 : BKCmergecand(bat *ret, const bat *aid, const bat *bid)
1041 : {
1042 78201 : BAT *a, *b, *bn;
1043 :
1044 78201 : if ((a = BATdescriptor(*aid)) == NULL) {
1045 0 : throw(MAL, "bat.mergecand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1046 : }
1047 78201 : if ((b = BATdescriptor(*bid)) == NULL) {
1048 0 : BBPunfix(a->batCacheid);
1049 0 : throw(MAL, "bat.mergecand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1050 : }
1051 78198 : bn = BATmergecand(a, b);
1052 78190 : BBPunfix(a->batCacheid);
1053 78190 : BBPunfix(b->batCacheid);
1054 78184 : if (bn == NULL)
1055 0 : throw(MAL, "bat.mergecand", GDK_EXCEPTION);
1056 78184 : *ret = bn->batCacheid;
1057 78184 : BBPkeepref(bn);
1058 78184 : return MAL_SUCCEED;
1059 : }
1060 :
1061 : static str
1062 0 : BKCintersectcand(bat *ret, const bat *aid, const bat *bid)
1063 : {
1064 0 : BAT *a, *b, *bn;
1065 :
1066 0 : if ((a = BATdescriptor(*aid)) == NULL) {
1067 0 : throw(MAL, "bat.intersectcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1068 : }
1069 0 : if ((b = BATdescriptor(*bid)) == NULL) {
1070 0 : BBPunfix(a->batCacheid);
1071 0 : throw(MAL, "bat.intersectcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1072 : }
1073 0 : bn = BATintersectcand(a, b);
1074 0 : BBPunfix(a->batCacheid);
1075 0 : BBPunfix(b->batCacheid);
1076 0 : if (bn == NULL)
1077 0 : throw(MAL, "bat.intersectcand", GDK_EXCEPTION);
1078 0 : *ret = bn->batCacheid;
1079 0 : BBPkeepref(bn);
1080 0 : return MAL_SUCCEED;
1081 : }
1082 :
1083 : static str
1084 0 : BKCdiffcand(bat *ret, const bat *aid, const bat *bid)
1085 : {
1086 0 : BAT *a, *b, *bn;
1087 :
1088 0 : if ((a = BATdescriptor(*aid)) == NULL) {
1089 0 : throw(MAL, "bat.diffcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1090 : }
1091 0 : if ((b = BATdescriptor(*bid)) == NULL) {
1092 0 : BBPunfix(a->batCacheid);
1093 0 : throw(MAL, "bat.diffcand", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1094 : }
1095 0 : bn = BATdiffcand(a, b);
1096 0 : BBPunfix(a->batCacheid);
1097 0 : BBPunfix(b->batCacheid);
1098 0 : if (bn == NULL)
1099 0 : throw(MAL, "bat.diffcand", GDK_EXCEPTION);
1100 0 : *ret = bn->batCacheid;
1101 0 : BBPkeepref(bn);
1102 0 : return MAL_SUCCEED;
1103 : }
1104 :
1105 : #include "mel.h"
1106 : mel_func bat5_init_funcs[] = {
1107 : command("bat", "mirror", BKCmirror, false, "Returns the head-mirror image of a BAT (two head columns).", args(1,2, batarg("",oid),batargany("b",2))),
1108 : command("bat", "delete", BKCdelete, false, "Delete BUN indicated by head value, exchanging with last BUN", args(1,3, batargany("",1),batargany("b",1),arg("h",oid))),
1109 : command("bat", "delete", BKCdelete_multi, false, "Delete multiple BUN, shifting BUNs up", args(1,3, batargany("",1),batargany("b",1),batarg("d",oid))),
1110 : command("bat", "delete", BKCdelete_all, false, "Delete all entries.", args(1,2, batargany("",1),batargany("b",1))),
1111 : command("bat", "replace", BKCbun_inplace, false, "Replace the tail value of one BUN that has some head value.", args(1,4, batargany("",1),batargany("b",1),arg("h",oid),argany("t",1))),
1112 : command("bat", "replace", BKCbun_inplace_force, false, "Replace the tail value of one BUN that has some head value.", args(1,5, batargany("",1),batargany("b",1),arg("h",oid),argany("t",1),arg("force",bit))),
1113 : command("bat", "replace", BKCbat_inplace, false, "Perform replace for all BUNs of the second BAT into the first.", args(1,4, batargany("",1),batargany("b",1),batarg("rid",oid),batargany("val",1))),
1114 : command("bat", "replace", BKCbat_inplace_force, false, "Perform replace for all BUNs of the second BAT into the first.", args(1,5, batargany("",1),batargany("b",1),batarg("rid",oid),batargany("val",1),arg("force",bit))),
1115 : command("bat", "append", BKCappend_wrap, false, "append the content of u to i", args(1,3, batargany("",1),batargany("i",1),batargany("u",1))),
1116 : command("bat", "append", BKCappend_force_wrap, false, "append the content of u to i", args(1,4, batargany("",1),batargany("i",1),batargany("u",1),arg("force",bit))),
1117 : command("bat", "append", BKCappend_cand_wrap, false, "append the content of u with candidate list s to i", args(1,4, batargany("",1),batargany("i",1),batargany("u",1),batarg("s",oid))),
1118 : command("bat", "append", BKCappend_cand_force_wrap, false, "append the content of u with candidate list s to i", args(1,5, batargany("",1),batargany("i",1),batargany("u",1),batarg("s",oid),arg("force",bit))),
1119 : command("bat", "append", BKCappend_val_force_wrap, false, "append the value u to i", args(1,4, batargany("",1),batargany("i",1),argany("u",1),arg("force",bit))),
1120 : command("bat", "attach", BKCattach, false, "Returns a new BAT with dense head and tail of the given type and uses\nthe given file to initialize the tail. The file will be owned by the\nserver.", args(1,3, batargany("",1),arg("tt",int),arg("heapfile",str))),
1121 : command("bat", "densebat", BKCdensebat, false, "Creates a new [void,void] BAT of size 'sz'.", args(1,2, batarg("",oid),arg("sz",lng))),
1122 : command("bat", "info", BKCinfo, false, "Produce a table containing information about a BAT in [attribute,value] format. \nIt contains all properties of the BAT record. ", args(2,3, batarg("",str),batarg("",str),batargany("b",1))),
1123 : command("bat", "getSize", BKCgetSize, false, "Calculate the actual size of the BAT descriptor, heaps, hashes and imprint indices in bytes\nrounded to the memory page size (see bbp.getPageSize()).", args(1,2, arg("",lng),batargany("b",1))),
1124 : command("bat", "getVHeapSize", BKCgetVHeapSize, false, "Calculate the vheap size for varsized bats", args(1,2, arg("",lng),batargany("b",1))),
1125 : command("bat", "getCapacity", BKCgetCapacity, false, "Returns the current allocation size (in max number of elements) of a BAT.", args(1,2, arg("",lng),batargany("b",1))),
1126 : command("bat", "getColumnType", BKCgetColumnType, false, "Returns the type of the tail column of a BAT, as an integer type number.", args(1,2, arg("",str),batargany("b",1))),
1127 : command("bat", "isaKey", BKCgetKey, false, "Return whether the column tail values are unique (key).", args(1,2, arg("",bit),batargany("b",1))),
1128 : command("bat", "setAccess", BKCsetAccess, false, "Try to change the update access privileges \nto this BAT. Mode:\nr[ead-only] - allow only read access.\na[append-only] - allow reads and update.\nw[riteable] - allow all operations.\nBATs are updatable by default. On making a BAT read-only, \nall subsequent updates fail with an error message.\nReturns the BAT itself.", args(1,3, batargany("",1),batargany("b",1),arg("mode",str))),
1129 : command("bat", "getAccess", BKCgetAccess, false, "Return the access mode attached to this BAT as a character.", args(1,2, arg("",str),batargany("b",1))),
1130 : command("bat", "getSequenceBase", BKCgetSequenceBase, false, "Get the sequence base for the void column of a BAT.", args(1,2, arg("",oid),batargany("b",1))),
1131 : command("bat", "isSorted", BKCisSorted, false, "Returns true if BAT values are ordered.", args(1,2, arg("",bit),batargany("b",1))),
1132 : command("bat", "isSortedReverse", BKCisSortedReverse, false, "Returns true if BAT values are reversely ordered.", args(1,2, arg("",bit),batargany("b",1))),
1133 : command("bat", "append", BKCappend_val_wrap, false, "append the value u to i", args(1,3, batargany("",1),batargany("i",1),argany("u",1))),
1134 : command("bat", "setName", BKCsetName, false, "Give a logical name to a BAT. ", args(1,3, arg("",void),batargany("b",1),arg("s",str))),
1135 : command("bat", "getName", BKCgetBBPname, false, "Gives back the logical name of a BAT.", args(1,2, arg("",str),batargany("b",1))),
1136 : command("bat", "isTransient", BKCisTransient, false, "", args(1,2, arg("",bit),batargany("b",1))),
1137 : command("bat", "setTransient", BKCsetTransient, false, "Make the BAT transient. Returns \nboolean which indicates if the\nBAT administration has indeed changed.", args(1,2, arg("",void),batargany("b",1))),
1138 : command("bat", "isPersistent", BKCisPersistent, false, "", args(1,2, arg("",bit),batargany("b",1))),
1139 : command("bat", "setPersistent", BKCsetPersistent, false, "Make the BAT persistent.", args(1,2, arg("",void),batargany("b",1))),
1140 : command("bat", "save", BKCsave2, false, "", args(1,2, arg("",void),batargany("nme",1))),
1141 : command("bat", "save", BKCsave, false, "Save a BAT to storage, if it was loaded and dirty. \nReturns whether IO was necessary. Please realize that \ncalling this function violates the atomic commit protocol!!", args(1,2, arg("",bit),arg("nme",str))),
1142 : command("bat", "setHash", BKCsetHash, false, "Create a hash structure on the column", args(1,2, arg("",bit),batargany("b",1))),
1143 : command("bat", "setImprints", BKCsetImprints, false, "Create an imprints structure on the column", args(1,2, arg("",bit),batargany("b",1))),
1144 : command("bat", "isSynced", BKCisSynced, false, "Tests whether two BATs are synced or not. ", args(1,3, arg("",bit),batargany("b1",1),batargany("b2",2))),
1145 : command("bat", "mergecand", BKCmergecand, false, "Merge two candidate lists into one", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
1146 : command("bat", "intersectcand", BKCintersectcand, false, "Intersect two candidate lists into one", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
1147 : command("bat", "diffcand", BKCdiffcand, false, "Calculate difference of two candidate lists", args(1,3, batarg("",oid),batarg("a",oid),batarg("b",oid))),
1148 : { .imp=NULL }
1149 : };
1150 : #include "mal_import.h"
1151 : #ifdef _MSC_VER
1152 : #undef read
1153 : #pragma section(".CRT$XCU",read)
1154 : #endif
1155 329 : LIB_STARTUP_FUNC(init_bat5_mal)
1156 329 : { mal_module("bat5", NULL, bat5_init_funcs); }
|