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