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 : #include "monetdb_config.h"
14 : #include "bat_table.h"
15 : #include "bat_utils.h"
16 : #include "bat_storage.h"
17 :
18 : static BAT *
19 1168735 : delta_cands(sql_trans *tr, sql_table *t)
20 : {
21 1168735 : sqlstore *store = tr->store;
22 1168735 : BAT *cands = store->storage_api.bind_cands(tr, t, 1, 0);
23 :
24 1168786 : if (cands && (cands->ttype == TYPE_msk || mask_cand(cands))) {
25 102560 : BAT *ncands = BATunmask(cands);
26 102560 : BBPreclaim(cands);
27 102560 : cands = ncands;
28 : }
29 1168786 : return cands;
30 : }
31 :
32 : static BAT *
33 4374307 : full_column(sql_trans *tr, sql_column *c)
34 : {
35 : /* return full normalized column bat
36 : * b := b.copy()
37 : b := b.replace(u);
38 : */
39 4374307 : sqlstore *store = tr->store;
40 4374307 : BAT *b = store->storage_api.bind_col(tr, c, RDONLY), *ui = NULL, *uv = NULL;
41 4375230 : int res = store->storage_api.bind_updates(tr, c, &ui, &uv);
42 :
43 4375512 : if (!b || !ui || !uv || res == LOG_ERR) {
44 0 : bat_destroy(b);
45 0 : bat_destroy(ui);
46 0 : bat_destroy(uv);
47 0 : return NULL;
48 : }
49 4375512 : if (BATcount(ui)) {
50 2035 : BAT *r = COLcopy(b, b->ttype, true, TRANSIENT);
51 2035 : bat_destroy(b);
52 2035 : b = r;
53 2035 : if (!b || BATreplace(b, ui, uv, true) != GDK_SUCCEED) {
54 0 : bat_destroy(b);
55 0 : bat_destroy(ui);
56 0 : bat_destroy(uv);
57 0 : return NULL;
58 : }
59 : }
60 4375512 : bat_destroy(ui);
61 4375557 : bat_destroy(uv);
62 4375557 : return b;
63 : }
64 :
65 : static oid
66 1046867 : column_find_row(sql_trans *tr, sql_column *c, const void *value, ...)
67 : {
68 1046867 : va_list va;
69 1046867 : BAT *b = NULL, *s = NULL, *r = NULL;
70 1046867 : oid rid = oid_nil;
71 1046867 : sql_column *n = NULL;
72 :
73 1046867 : va_start(va, value);
74 1046867 : s = delta_cands(tr, c->t);
75 1046924 : if (!s)
76 0 : goto return_nil;
77 1046924 : b = full_column(tr, c);
78 1047137 : if (!b) {
79 0 : bat_destroy(s);
80 0 : goto return_nil;
81 : }
82 1047137 : r = BATselect(b, s, value, NULL, true, false, false, false);
83 1046914 : bat_destroy(s);
84 1046721 : bat_destroy(b);
85 1046970 : if (!r)
86 0 : goto return_nil;
87 : s = r;
88 2077759 : while ((n = va_arg(va, sql_column *)) != NULL) {
89 1030789 : value = va_arg(va, void *);
90 1030789 : c = n;
91 :
92 1030789 : b = full_column(tr, c);
93 1030789 : if (!b) {
94 0 : bat_destroy(s);
95 0 : goto return_nil;
96 : }
97 1030789 : r = BATselect(b, s, value, NULL, true, false, false, false);
98 1030789 : bat_destroy(s);
99 1030789 : bat_destroy(b);
100 1030789 : if (!r)
101 0 : goto return_nil;
102 : s = r;
103 : }
104 1046955 : va_end(va);
105 1046955 : if (BATcount(s) == 1) {
106 498837 : rid = BUNtoid(s, 0);
107 : }
108 1046955 : bat_destroy(s);
109 1046955 : return rid;
110 0 : return_nil:
111 0 : va_end(va);
112 0 : return oid_nil;
113 : }
114 :
115 : static void *
116 188880 : column_find_value(sql_trans *tr, sql_column *c, oid rid)
117 : {
118 188880 : BUN q = BUN_NONE;
119 188880 : BAT *b;
120 188880 : void *res = NULL;
121 :
122 188880 : b = full_column(tr, c);
123 188956 : if (b) {
124 188956 : if (rid < b->hseqbase || rid >= b->hseqbase + BATcount(b))
125 : q = BUN_NONE;
126 : else
127 188956 : q = rid - b->hseqbase;
128 : }
129 188956 : if (q != BUN_NONE) {
130 188956 : BATiter bi = bat_iterator(b);
131 188955 : const void *r;
132 188955 : size_t sz;
133 :
134 188955 : r = BUNtail(bi, q);
135 188955 : sz = ATOMlen(b->ttype, r);
136 188952 : res = GDKmalloc(sz);
137 188949 : if (res)
138 188949 : memcpy(res, r, sz);
139 188949 : bat_iterator_end(&bi);
140 : }
141 188954 : bat_destroy(b);
142 188914 : return res;
143 : }
144 :
145 : #define column_find_tpe(TPE) \
146 : static TPE \
147 : column_find_##TPE(sql_trans *tr, sql_column *c, oid rid) \
148 : { \
149 : BUN q = BUN_NONE; \
150 : BAT *b; \
151 : TPE res = -1; \
152 : \
153 : b = full_column(tr, c); \
154 : if (b) { \
155 : if (rid < b->hseqbase || rid >= b->hseqbase + BATcount(b)) \
156 : q = BUN_NONE; \
157 : else \
158 : q = rid - b->hseqbase; \
159 : } \
160 : if (q != BUN_NONE) { \
161 : BATiter bi = bat_iterator(b); \
162 : res = *(TPE*)BUNtloc(bi, q); \
163 : bat_iterator_end(&bi); \
164 : } \
165 : bat_destroy(b); \
166 : return res; \
167 : }
168 :
169 475172 : column_find_tpe(sqlid)
170 1156874 : column_find_tpe(bte)
171 0 : column_find_tpe(sht)
172 1086365 : column_find_tpe(int)
173 74747 : column_find_tpe(lng)
174 :
175 : static const char *
176 570492 : column_find_string_start(sql_trans *tr, sql_column *c, oid rid, ptr *cbat)
177 : {
178 570492 : BUN q = BUN_NONE;
179 570492 : BAT **b = (BAT**) cbat;
180 570492 : const char *res = NULL;
181 :
182 570492 : *b = full_column(tr, c);
183 570492 : if (*b) {
184 570492 : if (rid < (*b)->hseqbase || rid >= (*b)->hseqbase + BATcount(*b))
185 : q = BUN_NONE;
186 : else
187 570492 : q = rid - (*b)->hseqbase;
188 : }
189 570492 : if (q != BUN_NONE) {
190 570492 : BATiter bi = bat_iterator(*b);
191 570492 : res = BUNtvar(bi, q);
192 570492 : bat_iterator_end(&bi);
193 : }
194 570492 : return res;
195 : }
196 :
197 : static void
198 570492 : column_find_string_end(ptr cbat)
199 : {
200 570492 : BAT *b = (BAT*) cbat;
201 570492 : bat_destroy(b);
202 570492 : }
203 :
204 : static int
205 6939 : column_update_value(sql_trans *tr, sql_column *c, oid rid, void *value)
206 : {
207 6939 : sqlstore *store = tr->store;
208 6939 : assert(!is_oid_nil(rid));
209 :
210 6939 : return store->storage_api.update_col(tr, c, &rid, value, false);
211 : }
212 :
213 : static int
214 1957775 : table_insert(sql_trans *tr, sql_table *t, ...)
215 : {
216 1957775 : sqlstore *store = tr->store;
217 1957775 : va_list va;
218 1957775 : node *n = ol_first_node(t->columns);
219 1957775 : void *val = NULL;
220 1957775 : int cnt = 0;
221 1957775 : int ok = LOG_OK;
222 1957775 : BUN offset = 0;
223 :
224 1957775 : va_start(va, t);
225 3915550 : ok = t->bootstrap?
226 1957775 : store->storage_api.claim_tab(tr, t, 1, &offset, NULL):
227 125730 : store->storage_api.key_claim_tab(tr, t, 1, &offset, NULL);
228 1957775 : if (ok != LOG_OK) {
229 4 : va_end(va);
230 4 : return ok;
231 : }
232 17224365 : for (; n; n = n->next) {
233 15266594 : sql_column *c = n->data;
234 15266594 : val = va_arg(va, void *);
235 15266595 : if (!val)
236 : break;
237 15266595 : ok = store->storage_api.append_col(tr, c, offset, NULL, val, 1, false, c->type.type->localtype);
238 15266594 : if (ok != LOG_OK) {
239 0 : va_end(va);
240 0 : return ok;
241 : }
242 15266594 : cnt++;
243 : }
244 1957771 : va_end(va);
245 1957771 : if (n) {
246 : // This part of the code should never get reached
247 0 : TRC_ERROR(SQL_STORE, "Called table_insert(%s) with wrong number of args (%d,%d)\n", t->base.name, ol_length(t->columns), cnt);
248 0 : assert(0);
249 : return LOG_ERR;
250 : }
251 : return LOG_OK;
252 : }
253 :
254 : static int
255 75367 : table_delete(sql_trans *tr, sql_table *t, oid rid)
256 : {
257 75367 : sqlstore *store = tr->store;
258 75367 : assert(!is_oid_nil(rid));
259 :
260 75367 : return store->storage_api.delete_tab(tr, t, &rid, false);
261 : }
262 :
263 : static res_table *
264 1375 : table_orderby(sql_trans *tr, sql_table *t, sql_column *jl, sql_column *jr, sql_column *jl2, sql_column *jr2, sql_column *o, ...)
265 : {
266 : /* jl/jr are columns on which we first join */
267 : /* if also jl2,jr2, we need to do another join, where both tables differ from 't' */
268 :
269 1375 : va_list va;
270 1375 : BAT *b = NULL, *r = NULL, *cl, *cr = NULL, *cr2 = NULL, *id = NULL, *grp = NULL;
271 : /* if pointers are equal, make it an inclusive select */
272 :
273 1375 : cl = delta_cands(tr, t);
274 1375 : if (cl == NULL)
275 : return NULL;
276 :
277 1375 : if (jl && jr) {
278 1000 : BAT *lcb, *rcb, *r = NULL, *l = NULL;
279 1000 : gdk_return ret;
280 :
281 1000 : cr = delta_cands(tr, jr->t);
282 1000 : lcb = full_column(tr, jl);
283 1000 : rcb = full_column(tr, jr);
284 1000 : if (!cr || !lcb || !rcb) {
285 0 : bat_destroy(cl);
286 0 : bat_destroy(cr);
287 0 : bat_destroy(lcb);
288 0 : bat_destroy(rcb);
289 0 : return NULL;
290 : }
291 :
292 1000 : ret = BATjoin(&l, &r, lcb, rcb, cl, cr, false, BATcount(lcb));
293 1000 : bat_destroy(cl);
294 1000 : bat_destroy(cr);
295 1000 : bat_destroy(lcb);
296 1000 : bat_destroy(rcb);
297 1000 : if (ret != GDK_SUCCEED)
298 : return NULL;
299 1000 : cl = l;
300 1000 : cr = r;
301 : }
302 : /* we assume 1->n joins, therefore first join between jl2/jr2 */
303 1375 : if (jl2 && jr2) {
304 375 : assert(jr->t == jl2->t);
305 375 : BAT *lcb, *rcb, *r = NULL, *l = NULL;
306 375 : gdk_return ret;
307 :
308 375 : cr2 = delta_cands(tr, jr2->t);
309 375 : lcb = full_column(tr, jl2);
310 375 : rcb = full_column(tr, jr2);
311 375 : if (!cr2 || !lcb || !rcb) {
312 0 : bat_destroy(cl);
313 0 : bat_destroy(cr);
314 0 : bat_destroy(cr2);
315 0 : bat_destroy(lcb);
316 0 : bat_destroy(rcb);
317 0 : return NULL;
318 : }
319 :
320 375 : l = BATproject(cr, lcb); /* project because cr is join result */
321 375 : bat_destroy(lcb);
322 375 : if (l == NULL) {
323 0 : bat_destroy(cl);
324 0 : bat_destroy(cr);
325 0 : bat_destroy(cr2);
326 0 : bat_destroy(rcb);
327 0 : return NULL;
328 : }
329 375 : lcb = l;
330 375 : ret = BATjoin(&l, &r, lcb, rcb, NULL, cr2, false, BATcount(lcb));
331 375 : bat_destroy(cr2);
332 375 : bat_destroy(lcb);
333 375 : bat_destroy(rcb);
334 375 : if (ret != GDK_SUCCEED) {
335 0 : bat_destroy(cl);
336 0 : bat_destroy(cr);
337 0 : return NULL;
338 : }
339 375 : lcb = BATproject(l, cl);
340 375 : rcb = BATproject(l, cr);
341 375 : bat_destroy(l);
342 375 : bat_destroy(cl);
343 375 : bat_destroy(cr);
344 375 : if (!lcb || !rcb) {
345 0 : bat_destroy(lcb);
346 0 : bat_destroy(rcb);
347 0 : bat_destroy(r);
348 0 : return NULL;
349 : }
350 375 : cl = lcb;
351 375 : cr = rcb;
352 375 : cr2 = r;
353 : }
354 :
355 1375 : va_start(va, o);
356 3875 : do {
357 3875 : BAT *nid = NULL, *ngrp = NULL;
358 3875 : sql_column *next = va_arg(va, sql_column *);
359 :
360 3875 : b = full_column(tr, o);
361 3875 : if (b)
362 4875 : r = BATproject( (o->t==t) ? cl : (cr2 && o->t==jr2->t) ? cr2 : cr, b);
363 3875 : bat_destroy(b);
364 3875 : if (!b || !r) {
365 0 : bat_destroy(cl);
366 0 : bat_destroy(cr);
367 0 : bat_destroy(cr2);
368 0 : va_end(va);
369 0 : return NULL;
370 : }
371 : /* (sub)order b */
372 5250 : if (BATsort(NULL, &nid, next?&ngrp:NULL, r, id, grp, false, false, false) != GDK_SUCCEED) {
373 0 : bat_destroy(r);
374 0 : bat_destroy(id);
375 0 : bat_destroy(grp);
376 0 : bat_destroy(cl);
377 0 : bat_destroy(cr);
378 0 : bat_destroy(cr2);
379 0 : va_end(va);
380 0 : return NULL;
381 : }
382 3875 : bat_destroy(r);
383 3875 : bat_destroy(id);
384 3875 : bat_destroy(grp);
385 3875 : id = nid;
386 3875 : grp = ngrp;
387 3875 : o = next;
388 3875 : } while (o);
389 1375 : bat_destroy(grp);
390 1375 : va_end(va);
391 :
392 1375 : r = BATproject(id, cl);
393 1375 : bat_destroy(id);
394 1375 : bat_destroy(cl);
395 1375 : bat_destroy(cr);
396 1375 : bat_destroy(cr2);
397 1375 : if (r == NULL)
398 : return NULL;
399 1375 : cl = r;
400 : /* project all in the new order */
401 1375 : res_table *rt = res_table_create(tr, 1/*result_id*/, 1/*query_id*/, ol_length(t->columns), Q_TABLE, NULL);
402 1375 : if (!rt) {
403 0 : bat_destroy(cl);
404 0 : return NULL;
405 : }
406 1375 : rt->nr_rows = BATcount(cl);
407 10250 : for (node *n = ol_first_node(t->columns); n; n = n->next) {
408 8875 : BAT *rc = NULL;
409 :
410 8875 : o = n->data;
411 8875 : b = full_column(tr, o);
412 8875 : if (b == NULL || (rc = BATproject(cl, b)) == NULL) {
413 0 : bat_destroy(cl);
414 0 : bat_destroy(b);
415 0 : res_table_destroy(rt);
416 0 : return NULL;
417 : }
418 8875 : bat_destroy(b);
419 8875 : if (!res_col_create(tr, rt, t->base.name, o->base.name, o->type.type->base.name, o->type.type->digits, o->type.type->scale, true, rc->ttype, rc, true)) {
420 0 : bat_destroy(cl);
421 0 : res_table_destroy(rt);
422 0 : return NULL;
423 : }
424 : }
425 1375 : bat_destroy(cl);
426 1375 : return rt;
427 : }
428 :
429 : static void *
430 1435109 : table_fetch_value(res_table *rt, sql_column *c)
431 : {
432 : /* this function is only ever called during startup, and therefore
433 : * there are no other threads that may be modifying the BAT under
434 : * our hands, so returning a pointer into the heap is fine */
435 1435109 : BAT *b = (BAT*)rt->cols[c->colnr].p;
436 1435109 : BATiter bi = bat_iterator_nolock(b);
437 1435109 : assert(b->ttype && b->ttype != TYPE_msk);
438 1435109 : if (bi.vh)
439 525299 : return BUNtvar(bi, rt->cur_row);
440 909810 : return BUNtloc(bi, rt->cur_row);
441 : //return (void*)BUNtail(bi, rt->cur_row);
442 : }
443 :
444 : static void
445 1375 : table_result_destroy(res_table *rt)
446 : {
447 1375 : if (rt)
448 1375 : res_table_destroy(rt);
449 1375 : }
450 :
451 : /* returns table rids, for the given select ranges */
452 : static rids *
453 118618 : rids_select( sql_trans *tr, sql_column *key, const void *key_value_low, const void *key_value_high, ...)
454 : {
455 118618 : va_list va;
456 118618 : BAT *b = NULL, *r = NULL, *s = NULL;
457 118618 : rids *rs = MNEW(rids);
458 118618 : const void *kvl = key_value_low, *kvh = key_value_high;
459 : /* if pointers are equal, make it an inclusive select */
460 118618 : bool hi = key_value_low == key_value_high;
461 :
462 118618 : if(!rs)
463 : return NULL;
464 118618 : s = delta_cands(tr, key->t);
465 118618 : if (s == NULL) {
466 0 : GDKfree(rs);
467 0 : return NULL;
468 : }
469 118618 : b = full_column(tr, key);
470 118618 : if (b == NULL) {
471 0 : bat_destroy(s);
472 0 : GDKfree(rs);
473 0 : return NULL;
474 : }
475 118618 : if (!kvl)
476 243 : kvl = ATOMnilptr(b->ttype);
477 118618 : if (!kvh && kvl != ATOMnilptr(b->ttype))
478 0 : kvh = ATOMnilptr(b->ttype);
479 118618 : if (key_value_low) {
480 118375 : r = BATselect(b, s, kvl, kvh, true, hi, false, false);
481 118375 : bat_destroy(s);
482 118375 : s = r;
483 : }
484 118618 : bat_destroy(b);
485 118618 : if (s == NULL) {
486 0 : GDKfree(rs);
487 0 : return NULL;
488 : }
489 118618 : if (key_value_low || key_value_high) {
490 118375 : va_start(va, key_value_high);
491 121604 : while ((key = va_arg(va, sql_column *)) != NULL) {
492 3229 : kvl = va_arg(va, void *);
493 3229 : kvh = va_arg(va, void *);
494 :
495 3229 : b = full_column(tr, key);
496 3229 : if (b == NULL) {
497 0 : bat_destroy(s);
498 0 : GDKfree(rs);
499 0 : va_end(va);
500 0 : return NULL;
501 : }
502 3229 : if (!kvl)
503 0 : kvl = ATOMnilptr(b->ttype);
504 3229 : if (!kvh && kvl != ATOMnilptr(b->ttype))
505 2349 : kvh = ATOMnilptr(b->ttype);
506 2349 : assert(kvh);
507 3229 : r = BATselect(b, s, kvl, kvh, true, hi, false, false);
508 3229 : bat_destroy(s);
509 3229 : s = r;
510 3229 : bat_destroy(b);
511 3229 : if (s == NULL) {
512 0 : GDKfree(rs);
513 0 : va_end(va);
514 0 : return NULL;
515 : }
516 : }
517 118375 : va_end(va);
518 : }
519 118618 : *rs = (rids) {
520 : .data = s,
521 : };
522 118618 : return rs;
523 : }
524 :
525 : /* order rids by orderby_column values */
526 : static rids *
527 105 : rids_orderby(sql_trans *tr, rids *r, sql_column *orderby_col)
528 : {
529 105 : BAT *b, *s, *o;
530 :
531 105 : b = full_column(tr, orderby_col);
532 105 : if (!b)
533 : return NULL;
534 105 : s = BATproject(r->data, b);
535 105 : bat_destroy(b);
536 105 : if (s == NULL)
537 : return NULL;
538 105 : if (BATsort(NULL, &o, NULL, s, NULL, NULL, false, false, false) != GDK_SUCCEED) {
539 0 : bat_destroy(s);
540 0 : return NULL;
541 : }
542 105 : bat_destroy(s);
543 105 : s = BATproject(o, r->data);
544 105 : bat_destroy(o);
545 105 : if (s == NULL)
546 : return NULL;
547 105 : bat_destroy(r->data);
548 105 : r->data = s;
549 105 : return r;
550 : }
551 :
552 :
553 : /* return table rids from result of rids_select, return (oid_nil) when done */
554 : static oid
555 135679 : rids_next(rids *r)
556 : {
557 135679 : if (r->cur < BATcount((BAT *) r->data)) {
558 37968 : BAT *t = r->data;
559 :
560 37968 : if (t && (t->ttype == TYPE_msk || mask_cand(t))) {
561 0 : r->data = BATunmask(t);
562 0 : if (!r->data) {
563 0 : r->data = t;
564 0 : return oid_nil;
565 : }
566 0 : bat_destroy(t);
567 : }
568 37968 : return BUNtoid((BAT *) r->data, r->cur++);
569 : }
570 97711 : return oid_nil;
571 : }
572 :
573 : /* clean up the resources taken by the result of rids_select */
574 : static void
575 118618 : rids_destroy(rids *r)
576 : {
577 118618 : bat_destroy(r->data);
578 118618 : _DELETE(r);
579 118618 : }
580 :
581 : static int
582 21252 : rids_empty(rids *r )
583 : {
584 21252 : BAT *b = r->data;
585 21252 : return BATcount(b) <= 0;
586 : }
587 :
588 : static rids *
589 17 : rids_join(sql_trans *tr, rids *l, sql_column *lc, rids *r, sql_column *rc)
590 : {
591 17 : BAT *lcb, *rcb, *s = NULL;
592 17 : gdk_return ret;
593 :
594 17 : lcb = full_column(tr, lc);
595 17 : rcb = full_column(tr, rc);
596 17 : if (!lcb || !rcb) {
597 0 : bat_destroy(l->data);
598 0 : l->data = NULL;
599 0 : bat_destroy(lcb);
600 0 : bat_destroy(rcb);
601 0 : return NULL;
602 : }
603 17 : ret = BATjoin(&s, NULL, lcb, rcb, l->data, r->data, false, BATcount(lcb));
604 17 : bat_destroy(l->data);
605 17 : if (ret != GDK_SUCCEED) {
606 0 : l->data = NULL;
607 : } else {
608 17 : l->data = s;
609 : }
610 17 : bat_destroy(lcb);
611 17 : bat_destroy(rcb);
612 17 : return l->data ? l : NULL;
613 : }
614 :
615 : static rids *
616 805 : rids_semijoin(sql_trans *tr, rids *l, sql_column *lc, rids *r, sql_column *rc)
617 : {
618 805 : BAT *lcb, *rcb, *s = NULL;
619 805 : gdk_return ret;
620 :
621 805 : lcb = full_column(tr, lc);
622 805 : rcb = full_column(tr, rc);
623 805 : if (!lcb || !rcb) {
624 0 : bat_destroy(l->data);
625 0 : l->data = NULL;
626 0 : bat_destroy(lcb);
627 0 : bat_destroy(rcb);
628 0 : return NULL;
629 : }
630 805 : ret = BATsemijoin(&s, NULL, lcb, rcb, l->data, r->data, false, false, BATcount(lcb));
631 805 : bat_destroy(l->data);
632 805 : if (ret != GDK_SUCCEED) {
633 0 : l->data = NULL;
634 : } else {
635 805 : l->data = s;
636 : }
637 805 : bat_destroy(lcb);
638 805 : bat_destroy(rcb);
639 805 : return l->data ? l : NULL;
640 : }
641 :
642 : static subrids *
643 519 : subrids_create(sql_trans *tr, rids *t1, sql_column *rc, sql_column *lc, sql_column *obc)
644 : {
645 : /* join t1.rc with lc order by obc */
646 519 : subrids *r;
647 519 : BAT *lcb, *rcb, *s, *obb, *o, *g, *ids, *rids = NULL;
648 519 : gdk_return ret;
649 :
650 519 : lcb = full_column(tr, lc);
651 519 : rcb = full_column(tr, rc);
652 519 : s = delta_cands(tr, lc->t);
653 519 : if (lcb == NULL || rcb == NULL || s == NULL) {
654 0 : bat_destroy(lcb);
655 0 : bat_destroy(rcb);
656 0 : bat_destroy(s);
657 0 : return NULL;
658 : }
659 :
660 519 : ret = BATjoin(&rids, NULL, lcb, rcb, s, t1->data, false, BATcount(lcb));
661 519 : bat_destroy(s);
662 519 : bat_destroy(rcb);
663 519 : if (ret != GDK_SUCCEED) {
664 0 : bat_destroy(lcb);
665 0 : return NULL;
666 : }
667 :
668 519 : s = BATproject(rids, lcb);
669 519 : bat_destroy(lcb);
670 519 : if (s == NULL) {
671 0 : bat_destroy(rids);
672 0 : return NULL;
673 : }
674 519 : lcb = s;
675 :
676 519 : if ((obb = full_column(tr, obc)) == NULL) {
677 0 : bat_destroy(lcb);
678 0 : bat_destroy(rids);
679 0 : return NULL;
680 : }
681 519 : s = BATproject(rids, obb);
682 519 : bat_destroy(obb);
683 519 : if (s == NULL) {
684 0 : bat_destroy(lcb);
685 0 : bat_destroy(rids);
686 0 : return NULL;
687 : }
688 519 : obb = s;
689 :
690 : /* need id, obc */
691 519 : ids = o = g = NULL;
692 519 : ret = BATsort(&ids, &o, &g, lcb, NULL, NULL, false, false, false);
693 519 : bat_destroy(lcb);
694 519 : if (ret != GDK_SUCCEED) {
695 0 : bat_destroy(obb);
696 0 : bat_destroy(rids);
697 0 : return NULL;
698 : }
699 :
700 519 : s = NULL;
701 519 : ret = BATsort(NULL, &s, NULL, obb, o, g, false, false, false);
702 519 : bat_destroy(obb);
703 519 : bat_destroy(o);
704 519 : bat_destroy(g);
705 519 : if (ret != GDK_SUCCEED) {
706 0 : bat_destroy(ids);
707 0 : bat_destroy(rids);
708 0 : return NULL;
709 : }
710 :
711 519 : o = BATproject(s, rids);
712 519 : bat_destroy(rids);
713 519 : bat_destroy(s);
714 519 : if (o == NULL) {
715 0 : bat_destroy(ids);
716 0 : return NULL;
717 : }
718 519 : rids = o;
719 :
720 519 : assert(ids->ttype == TYPE_int && ATOMtype(rids->ttype) == TYPE_oid);
721 519 : r = MNEW(subrids);
722 519 : if (r == NULL) {
723 0 : bat_destroy(ids);
724 0 : bat_destroy(rids);
725 0 : return NULL;
726 : }
727 519 : *r = (subrids) {
728 : .ids = ids,
729 : .rids = rids,
730 : };
731 519 : return r;
732 : }
733 :
734 : static oid
735 250225 : subrids_next(subrids *r)
736 : {
737 250225 : if (r->pos < BATcount((BAT *) r->ids)) {
738 249706 : BATiter ii = bat_iterator((BAT *) r->ids);
739 249706 : sqlid id = *(sqlid*)BUNtloc(ii, r->pos);
740 249706 : bat_iterator_end(&ii);
741 249706 : if (id == r->id)
742 186979 : return BUNtoid((BAT *) r->rids, r->pos++);
743 : }
744 63246 : return oid_nil;
745 : }
746 :
747 : static sqlid
748 63765 : subrids_nextid(subrids *r)
749 : {
750 63765 : if (r->pos < BATcount((BAT *) r->ids)) {
751 63246 : BATiter ii = bat_iterator((BAT *) r->ids);
752 63246 : r->id = *(sqlid*)BUNtloc(ii, r->pos);
753 63246 : bat_iterator_end(&ii);
754 63246 : return r->id;
755 : }
756 : return -1;
757 : }
758 :
759 : static void
760 519 : subrids_destroy(subrids *r )
761 : {
762 519 : bat_destroy(r->ids);
763 519 : bat_destroy(r->rids);
764 519 : _DELETE(r);
765 519 : }
766 :
767 : /* get the non - join results */
768 : static rids *
769 519 : rids_diff(sql_trans *tr, rids *l, sql_column *lc, subrids *r, sql_column *rc )
770 : {
771 519 : BAT *lcb = full_column(tr, lc), *s, *rids, *diff;
772 519 : BAT *rcb = full_column(tr, rc);
773 519 : gdk_return ret;
774 :
775 519 : if (lcb == NULL || rcb == NULL) {
776 0 : bat_destroy(lcb);
777 0 : bat_destroy(rcb);
778 0 : return NULL;
779 : }
780 519 : s = BATproject(r->rids, rcb);
781 519 : bat_destroy(rcb);
782 519 : if (s == NULL) {
783 0 : bat_destroy(lcb);
784 0 : return NULL;
785 : }
786 519 : rcb = s;
787 :
788 519 : s = BATproject(l->data, lcb);
789 519 : if (s == NULL) {
790 0 : bat_destroy(lcb);
791 0 : bat_destroy(rcb);
792 0 : return NULL;
793 : }
794 :
795 519 : diff = BATdiff(s, rcb, NULL, NULL, false, false, BUN_NONE);
796 519 : bat_destroy(rcb);
797 519 : if (diff == NULL) {
798 0 : bat_destroy(lcb);
799 0 : bat_destroy(s);
800 0 : return NULL;
801 : }
802 :
803 519 : ret = BATjoin(&rids, NULL, lcb, s, NULL, diff, false, BATcount(s));
804 519 : bat_destroy(diff);
805 519 : bat_destroy(lcb);
806 519 : bat_destroy(s);
807 519 : if (ret != GDK_SUCCEED)
808 : return NULL;
809 :
810 519 : bat_destroy(l->data);
811 519 : l->data = rids;
812 519 : return l;
813 : }
814 :
815 : void
816 352 : bat_table_init( table_functions *tf )
817 : {
818 352 : tf->column_find_row = column_find_row;
819 352 : tf->column_find_value = column_find_value;
820 352 : tf->column_find_sqlid = column_find_sqlid;
821 352 : tf->column_find_bte = column_find_bte;
822 352 : tf->column_find_sht = column_find_sht;
823 352 : tf->column_find_int = column_find_int;
824 352 : tf->column_find_lng = column_find_lng;
825 352 : tf->column_find_string_start = column_find_string_start; /* this function returns a pointer to the heap, use it with care! */
826 352 : tf->column_find_string_end = column_find_string_end; /* don't forget to call this function to unfix the bat descriptor! */
827 352 : tf->column_update_value = column_update_value;
828 352 : tf->table_insert = table_insert;
829 352 : tf->table_delete = table_delete;
830 352 : tf->table_orderby = table_orderby;
831 352 : tf->table_fetch_value = table_fetch_value;
832 352 : tf->table_result_destroy = table_result_destroy;
833 :
834 352 : tf->rids_select = rids_select;
835 352 : tf->rids_orderby = rids_orderby;
836 352 : tf->rids_join = rids_join;
837 352 : tf->rids_semijoin = rids_semijoin;
838 352 : tf->rids_next = rids_next;
839 352 : tf->rids_destroy = rids_destroy;
840 352 : tf->rids_empty = rids_empty;
841 :
842 352 : tf->subrids_create = subrids_create;
843 352 : tf->subrids_next = subrids_next;
844 352 : tf->subrids_nextid = subrids_nextid;
845 352 : tf->subrids_destroy = subrids_destroy;
846 352 : tf->rids_diff = rids_diff;
847 352 : }
|