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 "gdk.h"
15 : #include "gdk_subquery.h"
16 : #include "gdk_private.h"
17 : #include "gdk_calc_private.h"
18 :
19 : #define SQLall_grp_imp(TYPE) \
20 : do { \
21 : const TYPE *restrict vals = (const TYPE *) li.base; \
22 : TYPE *restrict rp = (TYPE *) Tloc(res, 0); \
23 : for (BUN n = 0; n < ci.ncand; n++) { \
24 : i = canditer_next(&ci) - l->hseqbase; \
25 : if (gids == NULL || \
26 : (gids[i] >= min && gids[i] <= max)) { \
27 : if (gids) \
28 : gid = gids[i] - min; \
29 : else \
30 : gid = (oid) i; \
31 : if (oids[gid] != (BUN_NONE - 1)) { \
32 : if (oids[gid] == BUN_NONE) { \
33 : if (!is_##TYPE##_nil(vals[i])) \
34 : oids[gid] = i; \
35 : } else { \
36 : if (vals[oids[gid]] != vals[i] && !is_##TYPE##_nil(vals[i])) \
37 : oids[gid] = BUN_NONE - 1; \
38 : } \
39 : } \
40 : } \
41 : } \
42 : for (i = 0; i < ngrp; i++) { /* convert the found oids in values */ \
43 : BUN noid = oids[i]; \
44 : if (noid > (BUN_NONE - 2)) { \
45 : rp[i] = TYPE##_nil; \
46 : hasnil = 1; \
47 : } else { \
48 : rp[i] = vals[noid]; \
49 : } \
50 : } \
51 : } while (0)
52 :
53 : BAT *
54 21 : BATall_grp(BAT *l, BAT *g, BAT *e, BAT *s)
55 : {
56 21 : BAT *res = NULL;
57 21 : const oid *restrict gids;
58 21 : oid gid, min, max, *restrict oids = NULL; /* The oids variable controls if we have found a nil in the group so far */
59 21 : BUN i, ngrp;
60 21 : bit hasnil = 0;
61 21 : struct canditer ci;
62 21 : const char *err;
63 21 : lng t0 = 0;
64 :
65 21 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
66 :
67 21 : if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
68 0 : GDKerror("%s\n", err);
69 0 : return NULL;
70 : }
71 21 : if (g == NULL) {
72 0 : GDKerror("l and g must be aligned\n");
73 0 : return NULL;
74 : }
75 :
76 21 : if (BATcount(l) == 0 || ngrp == 0) {
77 6 : const void *nilp = ATOMnilptr(l->ttype);
78 6 : if ((res = BATconstant(ngrp == 0 ? 0 : min, l->ttype, nilp, ngrp, TRANSIENT)) == NULL)
79 0 : goto alloc_fail;
80 : } else {
81 15 : BATiter li;
82 :
83 15 : if ((res = COLnew(min, l->ttype, ngrp, TRANSIENT)) == NULL)
84 0 : goto alloc_fail;
85 15 : if ((oids = GDKmalloc(ngrp * sizeof(oid))) == NULL)
86 0 : goto alloc_fail;
87 :
88 59 : for (i = 0; i < ngrp; i++)
89 44 : oids[i] = BUN_NONE;
90 :
91 15 : if (!g || BATtdense(g))
92 : gids = NULL;
93 : else
94 10 : gids = (const oid *) Tloc(g, 0);
95 :
96 15 : li = bat_iterator(l);
97 30 : switch (ATOMbasetype(l->ttype)) {
98 4 : case TYPE_bte:
99 32 : SQLall_grp_imp(bte);
100 : break;
101 0 : case TYPE_sht:
102 0 : SQLall_grp_imp(sht);
103 : break;
104 8 : case TYPE_int:
105 66 : SQLall_grp_imp(int);
106 : break;
107 0 : case TYPE_lng:
108 0 : SQLall_grp_imp(lng);
109 : break;
110 : #ifdef HAVE_HGE
111 2 : case TYPE_hge:
112 22 : SQLall_grp_imp(hge);
113 : break;
114 : #endif
115 0 : case TYPE_flt:
116 0 : SQLall_grp_imp(flt);
117 : break;
118 0 : case TYPE_dbl:
119 0 : SQLall_grp_imp(dbl);
120 : break;
121 1 : default: {
122 1 : int (*ocmp) (const void *, const void *) = ATOMcompare(l->ttype);
123 1 : const void *restrict nilp = ATOMnilptr(l->ttype);
124 :
125 3 : for (BUN n = 0; n < ci.ncand; n++) {
126 2 : i = canditer_next(&ci) - l->hseqbase;
127 2 : if (gids == NULL ||
128 2 : (gids[i] >= min && gids[i] <= max)) {
129 2 : if (gids)
130 2 : gid = gids[i] - min;
131 : else
132 : gid = (oid) i;
133 2 : if (oids[gid] != (BUN_NONE - 1)) {
134 2 : if (oids[gid] == BUN_NONE) {
135 1 : if (ocmp(BUNtail(li, i), nilp) != 0)
136 1 : oids[gid] = i;
137 : } else {
138 1 : const void *pi = BUNtail(li, oids[gid]);
139 1 : const void *pp = BUNtail(li, i);
140 1 : if (ocmp(pi, pp) != 0 && ocmp(pp, nilp) != 0)
141 1 : oids[gid] = BUN_NONE - 1;
142 : }
143 : }
144 : }
145 : }
146 :
147 1 : if (ATOMvarsized(l->ttype)) {
148 2 : for (i = 0; i < ngrp; i++) { /* convert the found oids in values */
149 1 : BUN noid = oids[i];
150 1 : const void *next;
151 1 : if (noid > (BUN_NONE - 2)) {
152 : next = nilp;
153 : hasnil = 1;
154 : } else {
155 0 : next = BUNtvar(li, noid);
156 : }
157 1 : if (tfastins_nocheckVAR(res, i, next) != GDK_SUCCEED) {
158 0 : bat_iterator_end(&li);
159 0 : goto alloc_fail;
160 : }
161 : }
162 : } else {
163 0 : uint8_t *restrict rcast = (uint8_t *) Tloc(res, 0);
164 0 : uint16_t width = res->twidth;
165 0 : for (i = 0; i < ngrp; i++) { /* convert the found oids in values */
166 0 : BUN noid = oids[i];
167 0 : const void *next;
168 0 : if (noid > (BUN_NONE - 2)) {
169 : next = nilp;
170 : hasnil = 1;
171 : } else {
172 0 : next = BUNtloc(li, noid);
173 : }
174 0 : memcpy(rcast, next, width);
175 0 : rcast += width;
176 : }
177 : }
178 : }
179 : }
180 15 : bat_iterator_end(&li);
181 15 : BATsetcount(res, ngrp);
182 15 : res->tnil = hasnil != 0;
183 15 : res->tnonil = hasnil == 0;
184 15 : res->tkey = BATcount(res) <= 1;
185 15 : res->tsorted = BATcount(res) <= 1;
186 15 : res->trevsorted = BATcount(res) <= 1;
187 : }
188 :
189 36 : GDKfree(oids);
190 :
191 21 : TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",g=" ALGOBATFMT
192 : ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
193 : " -> " ALGOOPTBATFMT
194 : " (%s -- " LLFMT " usec)\n",
195 : ALGOBATPAR(l), ALGOBATPAR(g),
196 : ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
197 : ALGOOPTBATPAR(res),
198 : __func__, GDKusec() - t0);
199 : return res;
200 0 : alloc_fail:
201 0 : BBPreclaim(res);
202 0 : GDKfree(oids);
203 0 : return NULL;
204 : }
205 :
206 : #define SQLnil_grp_imp(TYPE) \
207 : do { \
208 : const TYPE *restrict vals = (const TYPE *) li.base; \
209 : for (BUN n = 0; n < ci.ncand; n++) { \
210 : i = canditer_next(&ci) - l->hseqbase; \
211 : if (gids == NULL || \
212 : (gids[i] >= min && gids[i] <= max)) { \
213 : if (gids) \
214 : gid = gids[i] - min; \
215 : else \
216 : gid = (oid) i; \
217 : if (ret[gid] != TRUE && is_##TYPE##_nil(vals[i])) \
218 : ret[gid] = TRUE; \
219 : } \
220 : } \
221 : } while (0)
222 :
223 : BAT *
224 37 : BATnil_grp(BAT *l, BAT *g, BAT *e, BAT *s)
225 : {
226 37 : BAT *res = NULL;
227 37 : const oid *restrict gids;
228 37 : oid gid, min, max;
229 37 : BUN i, ngrp;
230 37 : struct canditer ci;
231 37 : const char *err;
232 37 : lng t0 = 0;
233 :
234 37 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
235 :
236 37 : if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
237 0 : GDKerror("%s\n", err);
238 0 : return NULL;
239 : }
240 37 : if (g == NULL) {
241 0 : GDKerror("l and g must be aligned\n");
242 0 : return NULL;
243 : }
244 :
245 51 : if (BATcount(l) == 0 || ngrp == 0) {
246 14 : bit F = FALSE;
247 14 : if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &F, ngrp, TRANSIENT)) == NULL)
248 0 : goto alloc_fail;
249 :
250 : } else {
251 23 : bit *restrict ret;
252 23 : BATiter li;
253 :
254 23 : if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL)
255 0 : goto alloc_fail;
256 23 : ret = (bit *) Tloc(res, 0);
257 23 : memset(ret, FALSE, ngrp * sizeof(bit));
258 :
259 23 : if (!g || BATtdense(g))
260 : gids = NULL;
261 : else
262 14 : gids = (const oid *) Tloc(g, 0);
263 :
264 23 : li = bat_iterator(l);
265 46 : switch (ATOMbasetype(l->ttype)) {
266 8 : case TYPE_bte:
267 54 : SQLnil_grp_imp(bte);
268 : break;
269 0 : case TYPE_sht:
270 0 : SQLnil_grp_imp(sht);
271 : break;
272 12 : case TYPE_int:
273 55 : SQLnil_grp_imp(int);
274 : break;
275 0 : case TYPE_lng:
276 0 : SQLnil_grp_imp(lng);
277 : break;
278 : #ifdef HAVE_HGE
279 2 : case TYPE_hge:
280 12 : SQLnil_grp_imp(hge);
281 : break;
282 : #endif
283 0 : case TYPE_flt:
284 0 : SQLnil_grp_imp(flt);
285 : break;
286 0 : case TYPE_dbl:
287 0 : SQLnil_grp_imp(dbl);
288 : break;
289 1 : default: {
290 1 : int (*ocmp) (const void *, const void *) = ATOMcompare(l->ttype);
291 1 : const void *restrict nilp = ATOMnilptr(l->ttype);
292 :
293 3 : for (BUN n = 0; n < ci.ncand; n++) {
294 2 : i = canditer_next(&ci) - l->hseqbase;
295 2 : if (gids == NULL ||
296 2 : (gids[i] >= min && gids[i] <= max)) {
297 2 : if (gids)
298 2 : gid = gids[i] - min;
299 : else
300 : gid = (oid) i;
301 2 : const void *restrict lv = BUNtail(li, i);
302 2 : if (ret[gid] != TRUE && ocmp(lv, nilp) == 0)
303 0 : ret[gid] = TRUE;
304 : }
305 : }
306 : }
307 : }
308 23 : bat_iterator_end(&li);
309 23 : BATsetcount(res, ngrp);
310 23 : res->tkey = BATcount(res) <= 1;
311 23 : res->tsorted = BATcount(res) <= 1;
312 23 : res->trevsorted = BATcount(res) <= 1;
313 23 : res->tnil = false;
314 23 : res->tnonil = true;
315 : }
316 :
317 37 : TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",g=" ALGOBATFMT
318 : ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
319 : " -> " ALGOOPTBATFMT
320 : " (%s -- " LLFMT " usec)\n",
321 : ALGOBATPAR(l), ALGOBATPAR(g),
322 : ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
323 : ALGOOPTBATPAR(res),
324 : __func__, GDKusec() - t0);
325 : return res;
326 : alloc_fail:
327 0 : BBPreclaim(res);
328 : return NULL;
329 : }
330 :
331 : #define SQLanyequal_or_not_grp_imp(TYPE, TEST) \
332 : do { \
333 : const TYPE *vals1 = (const TYPE *) li.base; \
334 : const TYPE *vals2 = (const TYPE *) ri.base; \
335 : for (BUN n = 0; n < ci.ncand; n++) { \
336 : i = canditer_next(&ci) - l->hseqbase; \
337 : if (gids == NULL || \
338 : (gids[i] >= min && gids[i] <= max)) { \
339 : if (gids) \
340 : gid = gids[i] - min; \
341 : else \
342 : gid = (oid) i; \
343 : if (ret[gid] != TEST) { \
344 : if (is_##TYPE##_nil(vals1[i]) || is_##TYPE##_nil(vals2[i])) { \
345 : ret[gid] = bit_nil; \
346 : hasnil = 1; \
347 : } else if (vals1[i] == vals2[i]) { \
348 : ret[gid] = TEST; \
349 : } \
350 : } \
351 : } \
352 : } \
353 : } while (0)
354 :
355 : BAT *
356 0 : BATanyequal_grp(BAT *l, BAT *r, BAT *g, BAT *e, BAT *s)
357 : {
358 0 : BAT *res = NULL;
359 0 : const oid *restrict gids;
360 0 : oid gid, min, max;
361 0 : BUN i, ngrp;
362 0 : bit hasnil = 0;
363 0 : struct canditer ci;
364 0 : const char *err;
365 0 : lng t0 = 0;
366 :
367 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
368 :
369 0 : if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
370 0 : GDKerror("%s\n", err);
371 0 : return NULL;
372 : }
373 0 : if (g == NULL) {
374 0 : GDKerror("l, r and g must be aligned\n");
375 0 : return NULL;
376 : }
377 :
378 0 : if (BATcount(l) == 0 || ngrp == 0) {
379 0 : bit F = FALSE;
380 0 : if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &F, ngrp, TRANSIENT)) == NULL)
381 0 : goto alloc_fail;
382 : } else {
383 0 : bit *restrict ret;
384 0 : BATiter li, ri;
385 :
386 0 : if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL)
387 0 : goto alloc_fail;
388 0 : ret = (bit *) Tloc(res, 0);
389 0 : memset(ret, FALSE, ngrp * sizeof(bit));
390 :
391 0 : if (!g || BATtdense(g))
392 : gids = NULL;
393 : else
394 0 : gids = (const oid *) Tloc(g, 0);
395 :
396 0 : li = bat_iterator(l);
397 0 : ri = bat_iterator(r);
398 0 : switch (ATOMbasetype(l->ttype)) {
399 0 : case TYPE_bte:
400 0 : SQLanyequal_or_not_grp_imp(bte, TRUE);
401 : break;
402 0 : case TYPE_sht:
403 0 : SQLanyequal_or_not_grp_imp(sht, TRUE);
404 : break;
405 0 : case TYPE_int:
406 0 : SQLanyequal_or_not_grp_imp(int, TRUE);
407 : break;
408 0 : case TYPE_lng:
409 0 : SQLanyequal_or_not_grp_imp(lng, TRUE);
410 : break;
411 : #ifdef HAVE_HGE
412 0 : case TYPE_hge:
413 0 : SQLanyequal_or_not_grp_imp(hge, TRUE);
414 : break;
415 : #endif
416 0 : case TYPE_flt:
417 0 : SQLanyequal_or_not_grp_imp(flt, TRUE);
418 : break;
419 0 : case TYPE_dbl:
420 0 : SQLanyequal_or_not_grp_imp(dbl, TRUE);
421 : break;
422 0 : default: {
423 0 : int (*ocmp) (const void *, const void *) = ATOMcompare(l->ttype);
424 0 : const void *nilp = ATOMnilptr(l->ttype);
425 :
426 0 : for (BUN n = 0; n < ci.ncand; n++) {
427 0 : i = canditer_next(&ci) - l->hseqbase;
428 0 : if (gids == NULL ||
429 0 : (gids[i] >= min && gids[i] <= max)) {
430 0 : if (gids)
431 0 : gid = gids[i] - min;
432 : else
433 : gid = (oid) i;
434 0 : if (ret[gid] != TRUE) {
435 0 : const void *lv = BUNtail(li, i);
436 0 : const void *rv = BUNtail(ri, i);
437 0 : if (ocmp(lv, nilp) == 0 || ocmp(rv, nilp) == 0) {
438 0 : ret[gid] = bit_nil;
439 0 : hasnil = 1;
440 0 : } else if (ocmp(lv, rv) == 0)
441 0 : ret[gid] = TRUE;
442 : }
443 : }
444 : }
445 : }
446 : }
447 0 : bat_iterator_end(&li);
448 0 : bat_iterator_end(&ri);
449 0 : BATsetcount(res, ngrp);
450 0 : res->tkey = BATcount(res) <= 1;
451 0 : res->tsorted = BATcount(res) <= 1;
452 0 : res->trevsorted = BATcount(res) <= 1;
453 0 : (void)hasnil;
454 0 : res->tnil = false ;//hasnil != 0;
455 0 : res->tnonil = false ;//hasnil == 0;
456 : }
457 :
458 0 : TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",r=" ALGOBATFMT ",g=" ALGOBATFMT
459 : ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
460 : " -> " ALGOOPTBATFMT
461 : " (%s -- " LLFMT " usec)\n",
462 : ALGOBATPAR(l), ALGOBATPAR(r), ALGOBATPAR(g),
463 : ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
464 : ALGOOPTBATPAR(res),
465 : __func__, GDKusec() - t0);
466 : return res;
467 : alloc_fail:
468 0 : BBPreclaim(res);
469 : return NULL;
470 : }
471 :
472 : BAT *
473 0 : BATallnotequal_grp(BAT *l, BAT *r, BAT *g, BAT *e, BAT *s)
474 : {
475 0 : BAT *res = NULL;
476 0 : const oid *restrict gids;
477 0 : oid gid, min, max;
478 0 : BUN i, ngrp;
479 0 : bit hasnil = 0;
480 0 : struct canditer ci;
481 0 : const char *err;
482 0 : lng t0 = 0;
483 :
484 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
485 :
486 0 : if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
487 0 : GDKerror("%s\n", err);
488 0 : return NULL;
489 : }
490 0 : if (g == NULL) {
491 0 : GDKerror("l, r and g must be aligned\n");
492 0 : return NULL;
493 : }
494 :
495 0 : if (BATcount(l) == 0 || ngrp == 0) {
496 0 : bit T = TRUE;
497 0 : if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &T, ngrp, TRANSIENT)) == NULL)
498 0 : goto alloc_fail;
499 : } else {
500 0 : bit *restrict ret;
501 0 : BATiter li, ri;
502 :
503 0 : if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL)
504 0 : goto alloc_fail;
505 0 : ret = (bit *) Tloc(res, 0);
506 0 : memset(ret, TRUE, ngrp * sizeof(bit));
507 :
508 0 : if (!g || BATtdense(g))
509 : gids = NULL;
510 : else
511 0 : gids = (const oid *) Tloc(g, 0);
512 :
513 0 : li = bat_iterator(l);
514 0 : ri = bat_iterator(r);
515 0 : switch (ATOMbasetype(l->ttype)) {
516 0 : case TYPE_bte:
517 0 : SQLanyequal_or_not_grp_imp(bte, FALSE);
518 : break;
519 0 : case TYPE_sht:
520 0 : SQLanyequal_or_not_grp_imp(sht, FALSE);
521 : break;
522 0 : case TYPE_int:
523 0 : SQLanyequal_or_not_grp_imp(int, FALSE);
524 : break;
525 0 : case TYPE_lng:
526 0 : SQLanyequal_or_not_grp_imp(lng, FALSE);
527 : break;
528 : #ifdef HAVE_HGE
529 0 : case TYPE_hge:
530 0 : SQLanyequal_or_not_grp_imp(hge, FALSE);
531 : break;
532 : #endif
533 0 : case TYPE_flt:
534 0 : SQLanyequal_or_not_grp_imp(flt, FALSE);
535 : break;
536 0 : case TYPE_dbl:
537 0 : SQLanyequal_or_not_grp_imp(dbl, FALSE);
538 : break;
539 0 : default: {
540 0 : int (*ocmp) (const void *, const void *) = ATOMcompare(l->ttype);
541 0 : const void *nilp = ATOMnilptr(l->ttype);
542 :
543 0 : for (BUN n = 0; n < ci.ncand; n++) {
544 0 : i = canditer_next(&ci) - l->hseqbase;
545 0 : if (gids == NULL ||
546 0 : (gids[i] >= min && gids[i] <= max)) {
547 0 : if (gids)
548 0 : gid = gids[i] - min;
549 : else
550 : gid = (oid) i;
551 0 : if (ret[gid] != FALSE) {
552 0 : const void *lv = BUNtail(li, i);
553 0 : const void *rv = BUNtail(ri, i);
554 0 : if (ocmp(lv, nilp) == 0 || ocmp(rv, nilp) == 0) {
555 0 : ret[gid] = bit_nil;
556 0 : hasnil = 1;
557 0 : } else if (ocmp(lv, rv) == 0)
558 0 : ret[gid] = FALSE;
559 : }
560 : }
561 : }
562 : }
563 : }
564 0 : bat_iterator_end(&li);
565 0 : bat_iterator_end(&ri);
566 0 : BATsetcount(res, ngrp);
567 0 : res->tkey = BATcount(res) <= 1;
568 0 : res->tsorted = BATcount(res) <= 1;
569 0 : res->trevsorted = BATcount(res) <= 1;
570 0 : res->tnil = hasnil != 0;
571 0 : res->tnonil = hasnil == 0;
572 : }
573 :
574 0 : TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",r=" ALGOBATFMT ",g=" ALGOBATFMT
575 : ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
576 : " -> " ALGOOPTBATFMT
577 : " (%s -- " LLFMT " usec)\n",
578 : ALGOBATPAR(l), ALGOBATPAR(r), ALGOBATPAR(g),
579 : ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
580 : ALGOOPTBATPAR(res),
581 : __func__, GDKusec() - t0);
582 : return res;
583 : alloc_fail:
584 0 : BBPreclaim(res);
585 : return NULL;
586 : }
587 :
588 : #define SQLanyequal_or_not_grp2_imp(TYPE, VAL1, VAL2) \
589 : do { \
590 : const TYPE *vals1 = (const TYPE *) li.base; \
591 : const TYPE *vals2 = (const TYPE *) ri.base; \
592 : for (BUN n = 0; n < ci.ncand; n++) { \
593 : i = canditer_next(&ci) - l->hseqbase; \
594 : if (gids == NULL || \
595 : (gids[i] >= min && gids[i] <= max)) { \
596 : if (gids) \
597 : gid = gids[i] - min; \
598 : else \
599 : gid = (oid) i; \
600 : if (ret[gid] != VAL1) { \
601 : const oid id = *(oid*)BUNtail(ii, i); \
602 : if (is_oid_nil(id)) { \
603 : ret[gid] = VAL2; \
604 : } else if (is_##TYPE##_nil(vals1[i]) || is_##TYPE##_nil(vals2[i])) { \
605 : ret[gid] = bit_nil; \
606 : } else if (vals1[i] == vals2[i]) { \
607 : ret[gid] = VAL1; \
608 : } \
609 : } \
610 : } \
611 : } \
612 : } while (0)
613 :
614 : BAT *
615 0 : BATanyequal_grp2(BAT *l, BAT *r, BAT *rid, BAT *g, BAT *e, BAT *s)
616 : {
617 0 : BAT *res = NULL;
618 0 : const oid *restrict gids;
619 0 : oid gid, min, max;
620 0 : BUN i, ngrp;
621 0 : bit hasnil = 0;
622 0 : struct canditer ci;
623 0 : const char *err;
624 0 : lng t0 = 0;
625 :
626 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
627 :
628 0 : if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
629 0 : GDKerror("%s\n", err);
630 0 : return NULL;
631 : }
632 0 : if (g == NULL) {
633 0 : GDKerror("l, r, rid and g must be aligned\n");
634 0 : return NULL;
635 : }
636 :
637 0 : if (BATcount(l) == 0 || ngrp == 0) {
638 0 : bit F = FALSE;
639 0 : if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &F, ngrp, TRANSIENT)) == NULL)
640 0 : goto alloc_fail;
641 : } else {
642 0 : bit *restrict ret;
643 0 : BATiter ii, li, ri;
644 :
645 0 : if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL)
646 0 : goto alloc_fail;
647 0 : ret = (bit *) Tloc(res, 0);
648 0 : memset(ret, FALSE, ngrp * sizeof(bit));
649 :
650 0 : if (!g || BATtdense(g))
651 : gids = NULL;
652 : else
653 0 : gids = (const oid *) Tloc(g, 0);
654 :
655 0 : ii = bat_iterator(rid);
656 0 : li = bat_iterator(l);
657 0 : ri = bat_iterator(r);
658 0 : switch (ATOMbasetype(l->ttype)) {
659 0 : case TYPE_bte:
660 0 : SQLanyequal_or_not_grp2_imp(bte, TRUE, FALSE);
661 : break;
662 0 : case TYPE_sht:
663 0 : SQLanyequal_or_not_grp2_imp(sht, TRUE, FALSE);
664 : break;
665 0 : case TYPE_int:
666 0 : SQLanyequal_or_not_grp2_imp(int, TRUE, FALSE);
667 : break;
668 0 : case TYPE_lng:
669 0 : SQLanyequal_or_not_grp2_imp(lng, TRUE, FALSE);
670 : break;
671 : #ifdef HAVE_HGE
672 0 : case TYPE_hge:
673 0 : SQLanyequal_or_not_grp2_imp(hge, TRUE, FALSE);
674 : break;
675 : #endif
676 0 : case TYPE_flt:
677 0 : SQLanyequal_or_not_grp2_imp(flt, TRUE, FALSE);
678 : break;
679 0 : case TYPE_dbl:
680 0 : SQLanyequal_or_not_grp2_imp(dbl, TRUE, FALSE);
681 : break;
682 0 : default: {
683 0 : int (*ocmp) (const void *, const void *) = ATOMcompare(l->ttype);
684 0 : const void *nilp = ATOMnilptr(l->ttype);
685 :
686 0 : for (BUN n = 0; n < ci.ncand; n++) {
687 0 : i = canditer_next(&ci) - l->hseqbase;
688 0 : if (gids == NULL ||
689 0 : (gids[i] >= min && gids[i] <= max)) {
690 0 : if (gids)
691 0 : gid = gids[i] - min;
692 : else
693 : gid = (oid) i;
694 0 : if (ret[gid] != TRUE) {
695 0 : const oid id = *(oid*)BUNtail(ii, i);
696 0 : if (is_oid_nil(id)) {
697 0 : ret[gid] = FALSE;
698 : } else {
699 0 : const void *lv = BUNtail(li, i);
700 0 : const void *rv = BUNtail(ri, i);
701 0 : if (ocmp(lv, nilp) == 0 || ocmp(rv, nilp) == 0) {
702 0 : ret[gid] = bit_nil;
703 0 : } else if (ocmp(lv, rv) == 0)
704 0 : ret[gid] = TRUE;
705 : }
706 : }
707 : }
708 : }
709 : }
710 : }
711 0 : bat_iterator_end(&li);
712 0 : bat_iterator_end(&ri);
713 0 : bat_iterator_end(&ii);
714 0 : for (BUN i = 0 ; i < ngrp ; i++)
715 0 : hasnil |= ret[i] == bit_nil;
716 0 : BATsetcount(res, ngrp);
717 0 : res->tkey = BATcount(res) <= 1;
718 0 : res->tsorted = BATcount(res) <= 1;
719 0 : res->trevsorted = BATcount(res) <= 1;
720 0 : res->tnil = hasnil != 0;
721 0 : res->tnonil = hasnil == 0;
722 : }
723 :
724 0 : TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",r=" ALGOBATFMT ",rid=" ALGOBATFMT
725 : ",g=" ALGOBATFMT ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
726 : " -> " ALGOOPTBATFMT
727 : " (%s -- " LLFMT " usec)\n",
728 : ALGOBATPAR(l), ALGOBATPAR(r), ALGOBATPAR(rid),
729 : ALGOBATPAR(g), ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
730 : ALGOOPTBATPAR(res),
731 : __func__, GDKusec() - t0);
732 : return res;
733 : alloc_fail:
734 0 : BBPreclaim(res);
735 : return NULL;
736 : }
737 :
738 : BAT *
739 0 : BATallnotequal_grp2(BAT *l, BAT *r, BAT *rid, BAT *g, BAT *e, BAT *s)
740 : {
741 0 : BAT *res = NULL;
742 0 : const oid *restrict gids;
743 0 : oid gid, min, max;
744 0 : BUN i, ngrp;
745 0 : bit hasnil = 0;
746 0 : struct canditer ci;
747 0 : const char *err;
748 0 : lng t0 = 0;
749 :
750 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
751 :
752 0 : if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
753 0 : GDKerror("%s\n", err);
754 0 : return NULL;
755 : }
756 0 : if (g == NULL) {
757 0 : GDKerror("l, r, rid and g must be aligned\n");
758 0 : return NULL;
759 : }
760 :
761 0 : if (BATcount(l) == 0 || ngrp == 0) {
762 0 : bit T = TRUE;
763 0 : if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &T, ngrp, TRANSIENT)) == NULL)
764 0 : goto alloc_fail;
765 : } else {
766 0 : bit *restrict ret;
767 0 : BATiter ii, li, ri;
768 :
769 0 : if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL)
770 0 : goto alloc_fail;
771 0 : ret = (bit *) Tloc(res, 0);
772 0 : memset(ret, TRUE, ngrp * sizeof(bit));
773 :
774 0 : if (!g || BATtdense(g))
775 : gids = NULL;
776 : else
777 0 : gids = (const oid *) Tloc(g, 0);
778 :
779 0 : ii = bat_iterator(rid);
780 0 : li = bat_iterator(l);
781 0 : ri = bat_iterator(r);
782 0 : switch (ATOMbasetype(l->ttype)) {
783 0 : case TYPE_bte:
784 0 : SQLanyequal_or_not_grp2_imp(bte, FALSE, TRUE);
785 : break;
786 0 : case TYPE_sht:
787 0 : SQLanyequal_or_not_grp2_imp(sht, FALSE, TRUE);
788 : break;
789 0 : case TYPE_int:
790 0 : SQLanyequal_or_not_grp2_imp(int, FALSE, TRUE);
791 : break;
792 0 : case TYPE_lng:
793 0 : SQLanyequal_or_not_grp2_imp(lng, FALSE, TRUE);
794 : break;
795 : #ifdef HAVE_HGE
796 0 : case TYPE_hge:
797 0 : SQLanyequal_or_not_grp2_imp(hge, FALSE, TRUE);
798 : break;
799 : #endif
800 0 : case TYPE_flt:
801 0 : SQLanyequal_or_not_grp2_imp(flt, FALSE, TRUE);
802 : break;
803 0 : case TYPE_dbl:
804 0 : SQLanyequal_or_not_grp2_imp(dbl, FALSE, TRUE);
805 : break;
806 0 : default: {
807 0 : int (*ocmp) (const void *, const void *) = ATOMcompare(l->ttype);
808 0 : const void *nilp = ATOMnilptr(l->ttype);
809 :
810 0 : for (BUN n = 0; n < ci.ncand; n++) {
811 0 : i = canditer_next(&ci) - l->hseqbase;
812 0 : if (gids == NULL ||
813 0 : (gids[i] >= min && gids[i] <= max)) {
814 0 : if (gids)
815 0 : gid = gids[i] - min;
816 : else
817 : gid = (oid) i;
818 0 : if (ret[gid] != FALSE) {
819 0 : const oid id = *(oid*)BUNtail(ii, i);
820 0 : if (is_oid_nil(id)) {
821 0 : ret[gid] = TRUE;
822 : } else {
823 0 : const void *lv = BUNtail(li, i);
824 0 : const void *rv = BUNtail(ri, i);
825 0 : if (ocmp(lv, nilp) == 0 || ocmp(rv, nilp) == 0) {
826 0 : ret[gid] = bit_nil;
827 0 : } else if (ocmp(lv, rv) == 0)
828 0 : ret[gid] = FALSE;
829 : }
830 : }
831 : }
832 : }
833 : }
834 : }
835 0 : bat_iterator_end(&ii);
836 0 : bat_iterator_end(&li);
837 0 : bat_iterator_end(&ri);
838 0 : for (BUN i = 0 ; i < ngrp ; i++)
839 0 : hasnil |= ret[i] == bit_nil;
840 0 : BATsetcount(res, ngrp);
841 0 : res->tkey = BATcount(res) <= 1;
842 0 : res->tsorted = BATcount(res) <= 1;
843 0 : res->trevsorted = BATcount(res) <= 1;
844 0 : res->tnil = hasnil != 0;
845 0 : res->tnonil = hasnil == 0;
846 : }
847 :
848 0 : TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",r=" ALGOBATFMT ",rid=" ALGOBATFMT
849 : ",g=" ALGOBATFMT ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
850 : " -> " ALGOOPTBATFMT
851 : " (%s -- " LLFMT " usec)\n",
852 : ALGOBATPAR(l), ALGOBATPAR(r), ALGOBATPAR(rid),
853 : ALGOBATPAR(g), ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
854 : ALGOOPTBATPAR(res),
855 : __func__, GDKusec() - t0);
856 : return res;
857 : alloc_fail:
858 0 : BBPreclaim(res);
859 : return NULL;
860 : }
861 :
862 : BAT *
863 0 : BATsubexist(BAT *b, BAT *g, BAT *e, BAT *s)
864 : {
865 0 : BAT *res = NULL;
866 0 : const oid *restrict gids;
867 0 : oid min, max;
868 0 : BUN i, ngrp;
869 0 : struct canditer ci;
870 0 : const char *err;
871 0 : lng t0 = 0;
872 :
873 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
874 :
875 0 : if ((err = BATgroupaggrinit(b, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
876 0 : GDKerror("%s\n", err);
877 0 : return NULL;
878 : }
879 0 : if (g == NULL) {
880 0 : GDKerror("b and g must be aligned\n");
881 0 : return NULL;
882 : }
883 :
884 0 : if (BATcount(b) == 0 || ngrp == 0) {
885 0 : bit F = FALSE;
886 0 : if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &F, ngrp, TRANSIENT)) == NULL)
887 0 : goto alloc_fail;
888 : } else {
889 0 : bit *restrict exists;
890 :
891 0 : if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL)
892 0 : goto alloc_fail;
893 0 : exists = (bit *) Tloc(res, 0);
894 0 : memset(exists, FALSE, ngrp * sizeof(bit));
895 :
896 0 : if (!g || BATtdense(g))
897 : gids = NULL;
898 : else
899 0 : gids = (const oid *) Tloc(g, 0);
900 :
901 0 : if (gids) {
902 0 : for (BUN n = 0; n < ci.ncand; n++) {
903 0 : i = canditer_next(&ci) - b->hseqbase;
904 0 : if (gids[i] >= min && gids[i] <= max)
905 0 : exists[gids[i] - min] = TRUE;
906 : }
907 : } else {
908 0 : for (BUN n = 0; n < ci.ncand; n++) {
909 0 : i = canditer_next(&ci) - b->hseqbase;
910 0 : exists[i] = TRUE;
911 : }
912 : }
913 0 : BATsetcount(res, ngrp);
914 0 : res->tkey = BATcount(res) <= 1;
915 0 : res->tsorted = BATcount(res) <= 1;
916 0 : res->trevsorted = BATcount(res) <= 1;
917 0 : res->tnil = false;
918 0 : res->tnonil = true;
919 : }
920 :
921 0 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",g=" ALGOBATFMT
922 : ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
923 : " -> " ALGOOPTBATFMT
924 : " (%s -- " LLFMT " usec)\n",
925 : ALGOBATPAR(b), ALGOBATPAR(g),
926 : ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
927 : ALGOOPTBATPAR(res),
928 : __func__, GDKusec() - t0);
929 : return res;
930 : alloc_fail:
931 0 : BBPreclaim(res);
932 : return NULL;
933 : }
934 :
935 : BAT *
936 0 : BATsubnot_exist(BAT *b, BAT *g, BAT *e, BAT *s)
937 : {
938 0 : BAT *res = NULL;
939 0 : const oid *restrict gids;
940 0 : oid min, max;
941 0 : BUN i, ngrp;
942 0 : struct canditer ci;
943 0 : const char *err;
944 0 : lng t0 = 0;
945 :
946 0 : TRC_DEBUG_IF(ALGO) t0 = GDKusec();
947 :
948 0 : if ((err = BATgroupaggrinit(b, g, e, s, &min, &max, &ngrp, &ci)) != NULL) {
949 0 : GDKerror("%s\n", err);
950 0 : return NULL;
951 : }
952 0 : if (g == NULL) {
953 0 : GDKerror("b and g must be aligned\n");
954 0 : return NULL;
955 : }
956 :
957 0 : if (BATcount(b) == 0 || ngrp == 0) {
958 0 : bit T = TRUE;
959 0 : if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &T, ngrp, TRANSIENT)) == NULL)
960 0 : goto alloc_fail;
961 : } else {
962 0 : bit *restrict exists;
963 :
964 0 : if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL)
965 0 : goto alloc_fail;
966 0 : exists = (bit *) Tloc(res, 0);
967 0 : memset(exists, TRUE, ngrp * sizeof(bit));
968 :
969 0 : if (!g || BATtdense(g))
970 : gids = NULL;
971 : else
972 0 : gids = (const oid *) Tloc(g, 0);
973 :
974 0 : if (gids) {
975 0 : for (BUN n = 0; n < ci.ncand; n++) {
976 0 : i = canditer_next(&ci) - b->hseqbase;
977 0 : if (gids[i] >= min && gids[i] <= max)
978 0 : exists[gids[i] - min] = FALSE;
979 : }
980 : } else {
981 0 : for (BUN n = 0; n < ci.ncand; n++) {
982 0 : i = canditer_next(&ci) - b->hseqbase;
983 0 : exists[i] = FALSE;
984 : }
985 : }
986 0 : BATsetcount(res, ngrp);
987 0 : res->tkey = BATcount(res) <= 1;
988 0 : res->tsorted = BATcount(res) <= 1;
989 0 : res->trevsorted = BATcount(res) <= 1;
990 0 : res->tnil = false;
991 0 : res->tnonil = true;
992 : }
993 :
994 0 : TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",g=" ALGOBATFMT
995 : ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT
996 : " -> " ALGOOPTBATFMT
997 : " (%s -- " LLFMT " usec)\n",
998 : ALGOBATPAR(b), ALGOBATPAR(g),
999 : ALGOOPTBATPAR(e), ALGOOPTBATPAR(s),
1000 : ALGOOPTBATPAR(res),
1001 : __func__, GDKusec() - t0);
1002 : return res;
1003 : alloc_fail:
1004 0 : BBPreclaim(res);
1005 : return NULL;
1006 : }
|