LCOV - code coverage report
Current view: top level - gdk - gdk_project.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 345 630 54.8 %
Date: 2021-09-14 19:48:19 Functions: 21 22 95.5 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : #include "monetdb_config.h"
      10             : #include "gdk.h"
      11             : #include "gdk_private.h"
      12             : 
      13             : /*
      14             :  * BATproject returns a BAT aligned with the left input whose values
      15             :  * are the values from the right input that were referred to by the
      16             :  * OIDs in the left input.
      17             :  *
      18             :  * BATproject2 is similar, except instead of a single right input
      19             :  * there are two of which the second's hseqbase is equal to the first
      20             :  * hseqbase + its batCount.
      21             :  */
      22             : 
      23             : #define project1_loop(TYPE)                                             \
      24             : static gdk_return                                                       \
      25             : project1_##TYPE(BAT *restrict bn, BAT *restrict l, BAT *restrict r1,    \
      26             :                 BATiter *restrict r1i)                                  \
      27             : {                                                                       \
      28             :         BUN lo, hi;                                                     \
      29             :         const TYPE *restrict r1t;                                       \
      30             :         TYPE *restrict bt;                                              \
      31             :         oid r1seq, r1end;                                               \
      32             :                                                                         \
      33             :         MT_thread_setalgorithm(__func__);                               \
      34             :         r1t = (const TYPE *) r1i->base;                                      \
      35             :         bt = (TYPE *) Tloc(bn, 0);                                      \
      36             :         r1seq = r1->hseqbase;                                                \
      37             :         r1end = r1seq + BATcount(r1);                                   \
      38             :         if (BATtdense(l)) {                                             \
      39             :                 if (l->tseqbase < r1seq ||                                \
      40             :                    (l->tseqbase+BATcount(l)) >= r1end) {          \
      41             :                         GDKerror("does not match always\n");          \
      42             :                         return GDK_FAIL;                                \
      43             :                 }                                                       \
      44             :                 oid off = l->tseqbase - r1seq;                               \
      45             :                 r1t += off;                                             \
      46             :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++)                \
      47             :                         bt[lo] = r1t[lo];                               \
      48             :         } else {                                                        \
      49             :                 assert(l->ttype);                                    \
      50             :                 BATiter li = bat_iterator(l);                           \
      51             :                 const oid *restrict ot = (const oid *) li.base;         \
      52             :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {              \
      53             :                         oid o = ot[lo];                                 \
      54             :                         if (o < r1seq || o >= r1end) {                    \
      55             :                                 GDKerror("does not match always\n");  \
      56             :                                 bat_iterator_end(&li);                      \
      57             :                                 return GDK_FAIL;                        \
      58             :                         }                                               \
      59             :                         bt[lo] = r1t[o - r1seq];                        \
      60             :                 }                                                       \
      61             :                 bat_iterator_end(&li);                                      \
      62             :         }                                                               \
      63             :         BATsetcount(bn, lo);                                            \
      64             :         return GDK_SUCCEED;                                             \
      65             : }
      66             : 
      67             : /* project type switch */
      68    29171711 : project1_loop(bte)
      69    16927623 : project1_loop(sht)
      70   593032924 : project1_loop(int)
      71        6551 : project1_loop(flt)
      72      157982 : project1_loop(dbl)
      73   181451679 : project1_loop(lng)
      74             : #ifdef HAVE_HGE
      75    47212215 : project1_loop(hge)
      76             : #endif
      77         134 : project1_loop(uuid)
      78             : 
      79             : #define project_loop(TYPE)                                              \
      80             : static gdk_return                                                       \
      81             : project_##TYPE(BAT *restrict bn, BAT *restrict l,                       \
      82             :                struct canditer *restrict ci,                            \
      83             :                BAT *restrict r1, BAT *restrict r2,                      \
      84             :                BATiter *restrict r1i, BATiter *restrict r2i)            \
      85             : {                                                                       \
      86             :         BUN lo, hi;                                                     \
      87             :         const TYPE *restrict r1t;                                       \
      88             :         const TYPE *restrict r2t;                                       \
      89             :         TYPE *restrict bt;                                              \
      90             :         TYPE v;                                                         \
      91             :         oid r1seq, r1end;                                               \
      92             :         oid r2seq, r2end;                                               \
      93             :                                                                         \
      94             :         if (r2 == NULL &&                                               \
      95             :             (!ci || (ci->tpe == cand_dense && BATtdense(l))) &&              \
      96             :             l->tnonil && r1->ttype && !BATtdense(r1))                     \
      97             :                 return project1_##TYPE(bn, l, r1, r1i);                 \
      98             :         MT_thread_setalgorithm(__func__);                               \
      99             :         r1t = (const TYPE *) r1i->base;                                      \
     100             :         r2t = (const TYPE *) r2i->base;      /* may be NULL if r2 == NULL */ \
     101             :         bt = (TYPE *) Tloc(bn, 0);                                      \
     102             :         r1seq = r1->hseqbase;                                                \
     103             :         r1end = r1seq + BATcount(r1);                                   \
     104             :         if (r2) {                                                       \
     105             :                 r2seq = r2->hseqbase;                                        \
     106             :                 r2end = r2seq + BATcount(r2);                           \
     107             :         } else {                                                        \
     108             :                 r2seq = r2end = r1end;                                  \
     109             :         }                                                               \
     110             :         if (ci) {                                                       \
     111             :                 for (lo = 0, hi = ci->ncand; lo < hi; lo++) {             \
     112             :                         oid o = canditer_next(ci);                      \
     113             :                         if (o < r1seq || o >= r2end) {                    \
     114             :                                 GDKerror("does not match always\n");  \
     115             :                                 return GDK_FAIL;                        \
     116             :                         }                                               \
     117             :                         if (o < r1end)                                       \
     118             :                                 v = r1t[o - r1seq];                     \
     119             :                         else                                            \
     120             :                                 v = r2t[o - r2seq];                     \
     121             :                         bt[lo] = v;                                     \
     122             :                 }                                                       \
     123             :         } else if (BATtdense(l)) {                                      \
     124             :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {              \
     125             :                         oid o = l->tseqbase + lo;                    \
     126             :                         if (o < r1seq || o >= r2end) {                    \
     127             :                                 GDKerror("does not match always\n");  \
     128             :                                 return GDK_FAIL;                        \
     129             :                         }                                               \
     130             :                         if (o < r1end)                                       \
     131             :                                 v = r1t[o - r1seq];                     \
     132             :                         else                                            \
     133             :                                 v = r2t[o - r2seq];                     \
     134             :                         bt[lo] = v;                                     \
     135             :                 }                                                       \
     136             :         } else {                                                        \
     137             :                 BATiter li = bat_iterator(l);                           \
     138             :                 const oid *restrict ot = (const oid *) li.base;         \
     139             :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {              \
     140             :                         oid o = ot[lo];                                 \
     141             :                         if (is_oid_nil(o)) {                            \
     142             :                                 bt[lo] = v = TYPE##_nil;                \
     143             :                                 bn->tnil = true;                     \
     144             :                         } else if (o < r1seq || o >= r2end) {             \
     145             :                                 GDKerror("does not match always\n");  \
     146             :                                 bat_iterator_end(&li);                      \
     147             :                                 return GDK_FAIL;                        \
     148             :                         } else if (o < r1end) {                              \
     149             :                                 v = r1t[o - r1seq];                     \
     150             :                                 bt[lo] = v;                             \
     151             :                         } else {                                        \
     152             :                                 v = r2t[o - r2seq];                     \
     153             :                                 bt[lo] = v;                             \
     154             :                         }                                               \
     155             :                 }                                                       \
     156             :                 bat_iterator_end(&li);                                      \
     157             :         }                                                               \
     158             :         BATsetcount(bn, lo);                                            \
     159             :         return GDK_SUCCEED;                                             \
     160             : }
     161             : 
     162             : 
     163             : /* project type switch */
     164      574299 : project_loop(bte)
     165     1210680 : project_loop(sht)
     166     3601776 : project_loop(int)
     167          96 : project_loop(flt)
     168        1805 : project_loop(dbl)
     169       13946 : project_loop(lng)
     170             : #ifdef HAVE_HGE
     171     1224694 : project_loop(hge)
     172             : #endif
     173          20 : project_loop(uuid)
     174             : 
     175             : static gdk_return
     176       23809 : project_oid(BAT *restrict bn, BAT *restrict l, struct canditer *restrict lci,
     177             :             BAT *restrict r1, BAT *restrict r2,
     178             :             BATiter *restrict r1i, BATiter *restrict r2i)
     179             : {
     180             :         BUN lo, hi;
     181             :         oid *restrict bt;
     182             :         oid r1seq, r1end;
     183             :         oid r2seq, r2end;
     184             :         const oid *restrict r1t = NULL;
     185             :         const oid *restrict r2t = NULL;
     186       23809 :         struct canditer r1ci = {0}, r2ci = {0};
     187             : 
     188       23809 :         if ((!lci || (lci->tpe == cand_dense && BATtdense(l))) && r1->ttype && !BATtdense(r1) && !r2 &&   l->tnonil) {
     189             :                 if (sizeof(oid) == sizeof(lng))
     190        8182 :                         return project1_lng(bn, l, r1, r1i);
     191             :                 else
     192             :                         return project1_int(bn, l, r1, r1i);
     193             :         }
     194       15627 :         MT_thread_setalgorithm(__func__);
     195       15647 :         if (complex_cand(r1))
     196          30 :                 canditer_init(&r1ci, NULL, r1);
     197       15617 :         else if (!BATtdense(r1))
     198          10 :                 r1t = (const oid *) r1i->base;
     199       15647 :         r1seq = r1->hseqbase;
     200       15647 :         r1end = r1seq + r1i->count;
     201       15647 :         if (r2) {
     202           0 :                 if (complex_cand(r2))
     203           0 :                         canditer_init(&r2ci, NULL, r2);
     204           0 :                 else if (!BATtdense(r2))
     205           0 :                         r2t = (const oid *) r2i->base;
     206           0 :                 r2seq = r2->hseqbase;
     207           0 :                 r2end = r2seq + r2i->count;
     208             :         } else {
     209             :                 r2seq = r2end = r1end;
     210             :         }
     211       15647 :         bt = (oid *) Tloc(bn, 0);
     212       15647 :         if (lci) {
     213          53 :                 for (lo = 0, hi = lci->ncand; lo < hi; lo++) {
     214          42 :                         oid o = canditer_next(lci);
     215          12 :                         if (o < r1seq || o >= r2end) {
     216           0 :                                 goto nomatch;
     217             :                         }
     218          12 :                         if (o < r1end) {
     219          12 :                                 if (r1ci.s)
     220           0 :                                         bt[lo] = canditer_idx(&r1ci, o - r1seq);
     221          12 :                                 else if (r1t)
     222           9 :                                         bt[lo] = r1t[o - r1seq];
     223             :                                 else
     224           3 :                                         bt[lo] = o - r1seq + r1->tseqbase;
     225             :                         } else {
     226           0 :                                 if (r2ci.s)
     227           0 :                                         bt[lo] = canditer_idx(&r2ci, o - r2seq);
     228           0 :                                 else if (r2t)
     229           0 :                                         bt[lo] = r2t[o - r2seq];
     230             :                                 else
     231           0 :                                         bt[lo] = o - r2seq + r2->tseqbase;
     232             :                         }
     233             :                 }
     234       15606 :         } else if (BATtdense(l)) {
     235           0 :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {
     236           0 :                         oid o = l->tseqbase + lo;
     237           0 :                         if (o < r1seq || o >= r2end) {
     238           0 :                                 goto nomatch;
     239             :                         }
     240           0 :                         if (o < r1end) {
     241           0 :                                 if (r1ci.s)
     242           0 :                                         bt[lo] = canditer_idx(&r1ci, o - r1seq);
     243           0 :                                 else if (r1t)
     244           0 :                                         bt[lo] = r1t[o - r1seq];
     245             :                                 else
     246           0 :                                         bt[lo] = o - r1seq + r1->tseqbase;
     247             :                         } else {
     248           0 :                                 if (r2ci.s)
     249           0 :                                         bt[lo] = canditer_idx(&r2ci, o - r2seq);
     250           0 :                                 else if (r2t)
     251           0 :                                         bt[lo] = r2t[o - r2seq];
     252             :                                 else
     253           0 :                                         bt[lo] = o - r2seq + r2->tseqbase;
     254             :                         }
     255             :                 }
     256             :         } else {
     257       15606 :                 BATiter li = bat_iterator(l);
     258       15776 :                 const oid *ot = (const oid *) li.base;
     259   198526703 :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {
     260   198510755 :                         oid o = ot[lo];
     261   198510755 :                         if (is_oid_nil(o)) {
     262           1 :                                 bt[lo] = oid_nil;
     263           1 :                                 bn->tnonil = false;
     264           1 :                                 bn->tnil = true;
     265   198510754 :                         } else if (o < r1seq || o >= r2end) {
     266           0 :                                 bat_iterator_end(&li);
     267           0 :                                 goto nomatch;
     268   198510754 :                         } else if (o < r1end) {
     269   198510754 :                                 if (r1ci.s)
     270        8980 :                                         bt[lo] = canditer_idx(&r1ci, o - r1seq);
     271   198501774 :                                 else if (r1t)
     272           0 :                                         bt[lo] = r1t[o - r1seq];
     273             :                                 else
     274   198501774 :                                         bt[lo] = o - r1seq + r1->tseqbase;
     275             :                         } else {
     276           0 :                                 if (r2ci.s)
     277           0 :                                         bt[lo] = canditer_idx(&r2ci, o - r2seq);
     278           0 :                                 else if (r2t)
     279           0 :                                         bt[lo] = r2t[o - r2seq];
     280             :                                 else
     281           0 :                                         bt[lo] = o - r2seq + r2->tseqbase;
     282             :                         }
     283             :                 }
     284       15948 :                 bat_iterator_end(&li);
     285             :         }
     286       15973 :         BATsetcount(bn, lo);
     287       15984 :         return GDK_SUCCEED;
     288           0 :   nomatch:
     289           0 :         GDKerror("does not match always\n");
     290           0 :         return GDK_FAIL;
     291             : }
     292             : 
     293             : static gdk_return
     294        1783 : project_any(BAT *restrict bn, BAT *restrict l, struct canditer *restrict ci,
     295             :             BAT *restrict r1, BAT *restrict r2,
     296             :             BATiter *restrict r1i, BATiter *restrict r2i)
     297             : {
     298             :         BUN lo, hi;
     299        1783 :         const void *nil = ATOMnilptr(r1->ttype);
     300             :         const void *v;
     301             :         oid r1seq, r1end;
     302             :         oid r2seq, r2end;
     303             : 
     304        1783 :         MT_thread_setalgorithm(__func__);
     305        1784 :         r1seq = r1->hseqbase;
     306        1784 :         r1end = r1seq + BATcount(r1);
     307        1784 :         if (r2) {
     308           0 :                 r2seq = r2->hseqbase;
     309           0 :                 r2end = r2seq + BATcount(r2);
     310             :         } else {
     311             :                 r2seq = r2end = r1end;
     312             :         }
     313        1784 :         if (ci) {
     314           1 :                 for (lo = 0, hi = ci->ncand; lo < hi; lo++) {
     315           1 :                         oid o = canditer_next(ci);
     316           0 :                         if (o < r1seq || o >= r2end) {
     317           0 :                                 GDKerror("does not match always\n");
     318           0 :                                 return GDK_FAIL;
     319             :                         }
     320           0 :                         if (o < r1end)
     321           0 :                                 v = BUNtail(*r1i, o - r1seq);
     322             :                         else
     323           0 :                                 v = BUNtail(*r2i, o - r2seq);
     324           0 :                         if (tfastins_nocheck(bn, lo, v) != GDK_SUCCEED) {
     325             :                                 return GDK_FAIL;
     326             :                         }
     327             :                 }
     328        1783 :         } else if (BATtdense(l)) {
     329           0 :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {
     330           0 :                         oid o = l->tseqbase + lo;
     331           0 :                         if (o < r1seq || o >= r2end) {
     332           0 :                                 GDKerror("does not match always\n");
     333           0 :                                 return GDK_FAIL;
     334             :                         }
     335           0 :                         if (o < r1end)
     336           0 :                                 v = BUNtail(*r1i, o - r1seq);
     337             :                         else
     338           0 :                                 v = BUNtail(*r2i, o - r2seq);
     339           0 :                         if (tfastins_nocheck(bn, lo, v) != GDK_SUCCEED) {
     340             :                                 return GDK_FAIL;
     341             :                         }
     342             :                 }
     343             :         } else {
     344        1783 :                 BATiter li = bat_iterator(l);
     345        1785 :                 const oid *restrict ot = (const oid *) li.base;
     346             : 
     347      198144 :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {
     348      196358 :                         oid o = ot[lo];
     349      196358 :                         if (is_oid_nil(o)) {
     350             :                                 v = nil;
     351           0 :                                 bn->tnil = true;
     352      196358 :                         } else if (o < r1seq || o >= r2end) {
     353           0 :                                 GDKerror("does not match always\n");
     354           0 :                                 bat_iterator_end(&li);
     355           0 :                                 return GDK_FAIL;
     356      196358 :                         } else if (o < r1end) {
     357      196358 :                                 v = BUNtail(*r1i, o - r1seq);
     358             :                         } else {
     359           0 :                                 v = BUNtail(*r2i, o - r2seq);
     360             :                         }
     361      196358 :                         if (tfastins_nocheck(bn, lo, v) != GDK_SUCCEED) {
     362           0 :                                 bat_iterator_end(&li);
     363           0 :                                 return GDK_FAIL;
     364             :                         }
     365             :                 }
     366        1786 :                 bat_iterator_end(&li);
     367             :         }
     368        1786 :         BATsetcount(bn, lo);
     369        1787 :         bn->theap->dirty = true;
     370        1787 :         return GDK_SUCCEED;
     371             : }
     372             : 
     373             : static BAT *
     374           0 : project_str(BAT *restrict l, struct canditer *restrict ci, int tpe,
     375             :             BAT *restrict r1, BAT *restrict r2,
     376             :             BATiter *restrict r1i, BATiter *restrict r2i,
     377             :             lng t0)
     378             : {
     379             :         BAT *bn;
     380             :         BUN lo, hi;
     381             :         oid r1seq, r1end;
     382             :         oid r2seq, r2end;
     383             :         BUN h1off;
     384             :         BUN off;
     385             :         oid seq;
     386             :         var_t v;
     387             :         BATiter *ri;
     388             : 
     389           0 :         if ((bn = COLnew(l->hseqbase, tpe, ci ? ci->ncand : BATcount(l),
     390             :                          TRANSIENT)) == NULL)
     391             :                 return NULL;
     392             : 
     393           0 :         v = (var_t) r1i->vhfree;
     394           0 :         if (r1i->vh == r2i->vh) {
     395             :                 h1off = 0;
     396           0 :                 BBPshare(r1i->vh->parentid);
     397           0 :                 HEAPdecref(bn->tvheap, true);
     398           0 :                 HEAPincref(r1i->vh);
     399           0 :                 bn->tvheap = r1i->vh;
     400             :         } else {
     401           0 :                 v = (v + GDK_VARALIGN - 1) & ~(GDK_VARALIGN - 1);
     402             :                 h1off = (BUN) v;
     403           0 :                 v += ((var_t) r2i->vhfree + GDK_VARALIGN - 1) & ~(GDK_VARALIGN - 1);
     404           0 :                 if (HEAPextend(bn->tvheap, v, false) != GDK_SUCCEED) {
     405           0 :                         BBPreclaim(bn);
     406           0 :                         return NULL;
     407             :                 }
     408           0 :                 memcpy(bn->tvheap->base, r1i->vh->base, r1i->vhfree);
     409             : #ifndef NDEBUG
     410           0 :                 if (h1off > r1i->vhfree)
     411           0 :                         memset(bn->tvheap->base + r1i->vhfree, 0, h1off - r1i->vhfree);
     412             : #endif
     413           0 :                 memcpy(bn->tvheap->base + h1off, r2i->vh->base, r2i->vhfree);
     414           0 :                 bn->tvheap->free = h1off + r2i->vhfree;
     415             :         }
     416             : 
     417           0 :         if (v >= ((var_t) 1 << (8 << bn->tshift)) &&
     418           0 :             GDKupgradevarheap(bn, v, false, 0) != GDK_SUCCEED) {
     419           0 :                 BBPreclaim(bn);
     420           0 :                 return NULL;
     421             :         }
     422             : 
     423           0 :         r1seq = r1->hseqbase;
     424           0 :         r1end = r1seq + r1i->count;
     425           0 :         r2seq = r2->hseqbase;
     426           0 :         r2end = r2seq + r2i->count;
     427           0 :         if (ci) {
     428           0 :                 for (lo = 0, hi = ci->ncand; lo < hi; lo++) {
     429           0 :                         oid o = canditer_next(ci);
     430           0 :                         if (o < r1seq || o >= r2end) {
     431           0 :                                 GDKerror("does not match always\n");
     432           0 :                                 BBPreclaim(bn);
     433           0 :                                 return NULL;
     434             :                         }
     435           0 :                         if (o < r1end) {
     436             :                                 ri = r1i;
     437             :                                 off = 0;
     438             :                                 seq = r1seq;
     439             :                         } else {
     440             :                                 ri = r2i;
     441             :                                 off = h1off;
     442             :                                 seq = r2seq;
     443             :                         }
     444           0 :                         switch (ri->width) {
     445           0 :                         case 1:
     446           0 :                                 v = (var_t) ((uint8_t *) ri->base)[o - seq] + GDK_VAROFFSET;
     447           0 :                                 break;
     448           0 :                         case 2:
     449           0 :                                 v = (var_t) ((uint16_t *) ri->base)[o - seq] + GDK_VAROFFSET;
     450           0 :                                 break;
     451           0 :                         case 4:
     452           0 :                                 v = (var_t) ((uint32_t *) ri->base)[o - seq];
     453           0 :                                 break;
     454           0 :                         case 8:
     455           0 :                                 v = (var_t) ((uint64_t *) ri->base)[o - seq];
     456           0 :                                 break;
     457             :                         }
     458           0 :                         v += off;
     459           0 :                         switch (bn->twidth) {
     460           0 :                         case 1:
     461           0 :                                 ((uint8_t *) bn->theap->base)[lo] = (uint8_t) (v - GDK_VAROFFSET);
     462           0 :                                 break;
     463           0 :                         case 2:
     464           0 :                                 ((uint16_t *) bn->theap->base)[lo] = (uint16_t) (v - GDK_VAROFFSET);
     465           0 :                                 break;
     466           0 :                         case 4:
     467           0 :                                 ((uint32_t *) bn->theap->base)[lo] = (uint32_t) v;
     468           0 :                                 break;
     469           0 :                         case 8:
     470           0 :                                 ((uint64_t *) bn->theap->base)[lo] = (uint64_t) v;
     471           0 :                                 break;
     472             :                         }
     473           0 :                 }
     474           0 :         } else if (BATtdense(l)) {
     475           0 :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {
     476           0 :                         oid o = l->tseqbase + lo;
     477           0 :                         if (o < r1seq || o >= r2end) {
     478           0 :                                 GDKerror("does not match always\n");
     479           0 :                                 BBPreclaim(bn);
     480           0 :                                 return NULL;
     481             :                         }
     482           0 :                         if (o < r1end) {
     483             :                                 ri = r1i;
     484             :                                 off = 0;
     485             :                                 seq = r1seq;
     486             :                         } else {
     487             :                                 ri = r2i;
     488             :                                 off = h1off;
     489             :                                 seq = r2seq;
     490             :                         }
     491           0 :                         switch (ri->width) {
     492           0 :                         case 1:
     493           0 :                                 v = (var_t) ((uint8_t *) ri->base)[o - seq] + GDK_VAROFFSET;
     494           0 :                                 break;
     495           0 :                         case 2:
     496           0 :                                 v = (var_t) ((uint16_t *) ri->base)[o - seq] + GDK_VAROFFSET;
     497           0 :                                 break;
     498           0 :                         case 4:
     499           0 :                                 v = (var_t) ((uint32_t *) ri->base)[o - seq];
     500           0 :                                 break;
     501           0 :                         case 8:
     502           0 :                                 v = (var_t) ((uint64_t *) ri->base)[o - seq];
     503           0 :                                 break;
     504             :                         }
     505           0 :                         v += off;
     506           0 :                         switch (bn->twidth) {
     507           0 :                         case 1:
     508           0 :                                 ((uint8_t *) bn->theap->base)[lo] = (uint8_t) (v - GDK_VAROFFSET);
     509           0 :                                 break;
     510           0 :                         case 2:
     511           0 :                                 ((uint16_t *) bn->theap->base)[lo] = (uint16_t) (v - GDK_VAROFFSET);
     512           0 :                                 break;
     513           0 :                         case 4:
     514           0 :                                 ((uint32_t *) bn->theap->base)[lo] = (uint32_t) v;
     515           0 :                                 break;
     516           0 :                         case 8:
     517           0 :                                 ((uint64_t *) bn->theap->base)[lo] = (uint64_t) v;
     518           0 :                                 break;
     519             :                         }
     520           0 :                 }
     521             :         } else {
     522           0 :                 BATiter li = bat_iterator(l);
     523           0 :                 const oid *restrict ot = (const oid *) li.base;
     524           0 :                 for (lo = 0, hi = BATcount(l); lo < hi; lo++) {
     525           0 :                         oid o = ot[lo];
     526           0 :                         if (o < r1seq || o >= r2end) {
     527           0 :                                 GDKerror("does not match always\n");
     528           0 :                                 BBPreclaim(bn);
     529           0 :                                 bat_iterator_end(&li);
     530           0 :                                 return NULL;
     531             :                         }
     532           0 :                         if (o < r1end) {
     533             :                                 ri = r1i;
     534             :                                 off = 0;
     535             :                                 seq = r1seq;
     536             :                         } else {
     537             :                                 ri = r2i;
     538             :                                 off = h1off;
     539             :                                 seq = r2seq;
     540             :                         }
     541           0 :                         switch (ri->width) {
     542           0 :                         case 1:
     543           0 :                                 v = (var_t) ((uint8_t *) ri->base)[o - seq] + GDK_VAROFFSET;
     544           0 :                                 break;
     545           0 :                         case 2:
     546           0 :                                 v = (var_t) ((uint16_t *) ri->base)[o - seq] + GDK_VAROFFSET;
     547           0 :                                 break;
     548           0 :                         case 4:
     549           0 :                                 v = (var_t) ((uint32_t *) ri->base)[o - seq];
     550           0 :                                 break;
     551           0 :                         case 8:
     552           0 :                                 v = (var_t) ((uint64_t *) ri->base)[o - seq];
     553           0 :                                 break;
     554             :                         }
     555           0 :                         v += off;
     556           0 :                         switch (bn->twidth) {
     557           0 :                         case 1:
     558           0 :                                 ((uint8_t *) bn->theap->base)[lo] = (uint8_t) (v - GDK_VAROFFSET);
     559           0 :                                 break;
     560           0 :                         case 2:
     561           0 :                                 ((uint16_t *) bn->theap->base)[lo] = (uint16_t) (v - GDK_VAROFFSET);
     562           0 :                                 break;
     563           0 :                         case 4:
     564           0 :                                 ((uint32_t *) bn->theap->base)[lo] = (uint32_t) v;
     565           0 :                                 break;
     566           0 :                         case 8:
     567           0 :                                 ((uint64_t *) bn->theap->base)[lo] = (uint64_t) v;
     568           0 :                                 break;
     569             :                         }
     570           0 :                 }
     571           0 :                 bat_iterator_end(&li);
     572             :         }
     573           0 :         BATsetcount(bn, lo);
     574           0 :         bn->tsorted = bn->trevsorted = false;
     575           0 :         bn->tnil = false;
     576           0 :         bn->tnonil = r1->tnonil & r2->tnonil;
     577           0 :         bn->tkey = false;
     578           0 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT " r1=" ALGOBATFMT " r2=" ALGOBATFMT
     579             :                   " -> " ALGOBATFMT "%s " LLFMT "us\n",
     580             :                   ALGOBATPAR(l), ALGOBATPAR(r1), ALGOBATPAR(r2),
     581             :                   ALGOBATPAR(bn),
     582             :                   bn && bn->ttype == TYPE_str && bn->tvheap == r1i->vh ? " sharing string heap" : "",
     583             :                   GDKusec() - t0);
     584             :         return bn;
     585             : }
     586             : 
     587             : BAT *
     588     3813677 : BATproject2(BAT *restrict l, BAT *restrict r1, BAT *restrict r2)
     589             : {
     590             :         BAT *bn = NULL;
     591             :         BAT *or1 = r1, *or2 = r2, *ol = l;
     592             :         oid lo, hi;
     593             :         gdk_return res;
     594     3813677 :         int tpe = ATOMtype(r1->ttype), otpe = tpe;
     595             :         bool stringtrick = false;
     596     3813677 :         BUN lcount = BATcount(l);
     597             :         struct canditer ci, *lci = NULL;
     598             :         const char *msg = "";
     599             :         lng t0 = 0;
     600     3813677 :         BATiter r1i = bat_iterator(r1);
     601     3811479 :         BATiter r2i = bat_iterator(r2);
     602             : 
     603     3816116 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
     604             : 
     605     3816116 :         assert(ATOMtype(l->ttype) == TYPE_oid || l->ttype == TYPE_msk);
     606     3816116 :         assert(r2 == NULL || tpe == ATOMtype(r2->ttype));
     607     3816116 :         assert(r2 == NULL || r1->hseqbase + r1i.count == r2->hseqbase);
     608             : 
     609     3816116 :         if (r2 && r1i.count == 0) {
     610             :                 /* unlikely special case: r1 is empty, so we just have r2 */
     611             :                 r1 = r2;
     612             :                 r2 = NULL;
     613           0 :                 bat_iterator_end(&r1i);
     614           0 :                 r1i = r2i;
     615           0 :                 r2i = bat_iterator(r2);
     616             :         }
     617             : 
     618     3816116 :         if (BATtdense(l) && lcount > 0) {
     619             :                 lo = l->tseqbase;
     620      919069 :                 hi = l->tseqbase + lcount;
     621      919069 :                 if (lo >= r1->hseqbase && hi <= r1->hseqbase + r1i.count) {
     622      919069 :                         bn = BATslice(r1, lo - r1->hseqbase, hi - r1->hseqbase);
     623      916195 :                         BAThseqbase(bn, l->hseqbase);
     624             :                         msg = " (slice)";
     625      914282 :                         goto doreturn;
     626             :                 }
     627           0 :                 if (lo < r1->hseqbase || r2 == NULL || hi > r2->hseqbase + r2i.count) {
     628           0 :                         GDKerror("does not match always\n");
     629           0 :                         bat_iterator_end(&r1i);
     630           0 :                         bat_iterator_end(&r2i);
     631           0 :                         return NULL;
     632             :                 }
     633           0 :                 if (lo >= r2->hseqbase) {
     634           0 :                         bn = BATslice(r2, lo - r2->hseqbase, hi - r2->hseqbase);
     635           0 :                         BAThseqbase(bn, l->hseqbase);
     636             :                         msg = " (slice2)";
     637           0 :                         goto doreturn;
     638             :                 }
     639             :         }
     640     2897047 :         if (complex_cand(l)) {
     641             :                 /* l is candidate list with exceptions or is a bitmask */
     642       55744 :                 assert(l->ttype == TYPE_msk || !is_oid_nil(l->tseqbase));
     643       55744 :                 lcount = canditer_init(&ci, NULL, l);
     644       55535 :                 lci = &ci;
     645     2841303 :         } else if (l->ttype == TYPE_msk) {
     646           0 :                 l = BATunmask(l);
     647           0 :                 if (l == NULL)
     648           0 :                         goto doreturn;
     649             :         }
     650     2896838 :         if (lcount == 0 ||
     651      249407 :             (l->ttype == TYPE_void && is_oid_nil(l->tseqbase)) ||
     652      249407 :             (r1->ttype == TYPE_void && is_oid_nil(r1->tseqbase) &&
     653           0 :              (r2 == NULL ||
     654           0 :               (r2->ttype == TYPE_void && is_oid_nil(r2->tseqbase))))) {
     655             :                 /* trivial: all values are nil (includes no entries at all) */
     656     2647443 :                 const void *nil = r1->ttype == TYPE_msk ? &oid_nil : ATOMnilptr(r1->ttype);
     657             : 
     658     5289053 :                 bn = BATconstant(l->hseqbase, r1->ttype == TYPE_oid || r1->ttype == TYPE_msk ? TYPE_void : r1->ttype,
     659             :                                  nil, lcount, TRANSIENT);
     660     2635150 :                 if (bn != NULL &&
     661     2635150 :                     ATOMtype(bn->ttype) == TYPE_oid &&
     662      180852 :                     BATcount(bn) == 0) {
     663      181191 :                         BATtseqbase(bn, 0);
     664             :                 }
     665             :                 msg = " (constant)";
     666     2635649 :                 goto doreturn;
     667             :         }
     668             : 
     669      249395 :         if (ATOMstorage(tpe) == TYPE_str) {
     670       46646 :                 if (l->tnonil &&
     671       46647 :                     r2 == NULL &&
     672       46647 :                     (r1i.count == 0 ||
     673       46591 :                      lcount > (r1i.count >> 3) ||
     674        5599 :                      r1->batRestricted == BAT_READ)) {
     675             :                         /* insert strings as ints, we need to copy the
     676             :                          * string heap whole sale; we can't do this if
     677             :                          * there are nils in the left column, and we
     678             :                          * won't do it if the left is much smaller than
     679             :                          * the right and the right is writable (meaning
     680             :                          * we have to actually copy the right string
     681             :                          * heap) */
     682       44937 :                         tpe = r1i.width == 1 ? TYPE_bte : (r1i.width == 2 ? TYPE_sht : (r1i.width == 4 ? TYPE_int : TYPE_lng));
     683             :                         stringtrick = true;
     684        1709 :                 } else if (l->tnonil &&
     685           0 :                            r2 != NULL &&
     686           0 :                            (r1i.vh == r2i.vh ||
     687           0 :                             (!GDK_ELIMDOUBLES(r1i.vh) /* && size tests */))) {
     688             :                         /* r1 and r2 may explicitly share their vheap,
     689             :                          * if they do, the result will also share the
     690             :                          * vheap; this also means that for this case we
     691             :                          * don't care about duplicate elimination: it
     692             :                          * will remain the same */
     693           0 :                         bn = project_str(l, lci, tpe, r1, r2, &r1i, &r2i, t0);
     694           0 :                         bat_iterator_end(&r1i);
     695           0 :                         bat_iterator_end(&r2i);
     696           0 :                         return bn;
     697             :                 }
     698      202749 :         } else if (tpe == TYPE_msk || mask_cand(r1)) {
     699           4 :                 r1 = BATunmask(r1);
     700           4 :                 if (r1 == NULL)
     701           0 :                         goto doreturn;
     702           4 :                 if (r2) {
     703           0 :                         r2 = BATunmask(r2);
     704           0 :                         if (r2 == NULL)
     705           0 :                                 goto doreturn;
     706             :                 }
     707             :                 tpe = TYPE_oid;
     708           4 :                 bat_iterator_end(&r1i);
     709           4 :                 bat_iterator_end(&r2i);
     710           4 :                 r1i = bat_iterator(r1);
     711           4 :                 r2i = bat_iterator(r2);
     712             :         }
     713      483179 :         bn = COLnew_intern(l->hseqbase, ATOMtype(r1->ttype), lcount, TRANSIENT, stringtrick ? r1i.width : 0);
     714      248333 :         if (bn == NULL) {
     715           0 :                 goto doreturn;
     716             :         }
     717      248333 :         bn->tnil = false;
     718      248333 :         if (r2) {
     719         592 :                 bn->tnonil = l->tnonil & r1->tnonil & r2->tnonil;
     720         592 :                 bn->tsorted = l->batCount <= 1;
     721         592 :                 bn->trevsorted = l->batCount <= 1;
     722         592 :                 bn->tkey = l->batCount <= 1;
     723             :         } else {
     724      247741 :                 bn->tnonil = l->tnonil & r1->tnonil;
     725      495482 :                 bn->tsorted = l->batCount <= 1
     726      247190 :                         || (l->tsorted & r1->tsorted)
     727      203276 :                         || (l->trevsorted & r1->trevsorted)
     728      449148 :                         || r1->batCount <= 1;
     729      247741 :                 bn->trevsorted = l->batCount <= 1
     730      247940 :                         || (l->tsorted & r1->trevsorted)
     731      236860 :                         || (l->trevsorted & r1->tsorted)
     732      482543 :                         || r1->batCount <= 1;
     733      471782 :                 bn->tkey = l->batCount <= 1 || (l->tkey & r1->tkey);
     734             :         }
     735             : 
     736      248333 :         if (!stringtrick && tpe != TYPE_oid)
     737      180616 :                 tpe = ATOMbasetype(tpe);
     738      248333 :         switch (tpe) {
     739       25427 :         case TYPE_bte:
     740       25427 :                 res = project_bte(bn, l, lci, r1, r2, &r1i, &r2i);
     741       25513 :                 break;
     742       31014 :         case TYPE_sht:
     743       31014 :                 res = project_sht(bn, l, lci, r1, r2, &r1i, &r2i);
     744       31078 :                 break;
     745      147033 :         case TYPE_int:
     746      147033 :                 res = project_int(bn, l, lci, r1, r2, &r1i, &r2i);
     747      147956 :                 break;
     748          97 :         case TYPE_flt:
     749          97 :                 res = project_flt(bn, l, lci, r1, r2, &r1i, &r2i);
     750          97 :                 break;
     751        1745 :         case TYPE_dbl:
     752        1745 :                 res = project_dbl(bn, l, lci, r1, r2, &r1i, &r2i);
     753        1746 :                 break;
     754       13877 :         case TYPE_lng:
     755       13877 :                 res = project_lng(bn, l, lci, r1, r2, &r1i, &r2i);
     756       13952 :                 break;
     757             : #ifdef HAVE_HGE
     758        3440 :         case TYPE_hge:
     759        3440 :                 res = project_hge(bn, l, lci, r1, r2, &r1i, &r2i);
     760        3460 :                 break;
     761             : #endif
     762       23900 :         case TYPE_oid:
     763       23900 :                 res = project_oid(bn, l, lci, r1, r2, &r1i, &r2i);
     764       24019 :                 break;
     765          16 :         case TYPE_uuid:
     766          16 :                 res = project_uuid(bn, l, lci, r1, r2, &r1i, &r2i);
     767          16 :                 break;
     768        1784 :         default:
     769        1784 :                 res = project_any(bn, l, lci, r1, r2, &r1i, &r2i);
     770        1785 :                 break;
     771             :         }
     772             : 
     773      249622 :         if (res != GDK_SUCCEED)
     774         549 :                 goto bailout;
     775             : 
     776             :         /* handle string trick */
     777      249073 :         if (stringtrick) {
     778       44979 :                 assert(r1i.vh);
     779       44979 :                 if (r1->batRestricted == BAT_READ) {
     780             :                         /* really share string heap */
     781       39102 :                         assert(r1i.vh->parentid > 0);
     782       39102 :                         BBPshare(r1i.vh->parentid);
     783             :                         /* there is no file, so we don't need to remove it */
     784       39137 :                         HEAPdecref(bn->tvheap, false);
     785       39145 :                         bn->tvheap = r1i.vh;
     786       39145 :                         HEAPincref(r1i.vh);
     787             :                 } else {
     788             :                         /* make copy of string heap */
     789        5877 :                         bn->tvheap->parentid = bn->batCacheid;
     790        5877 :                         bn->tvheap->farmid = BBPselectfarm(bn->batRole, otpe, varheap);
     791        5880 :                         strconcat_len(bn->tvheap->filename,
     792             :                                       sizeof(bn->tvheap->filename),
     793        5880 :                                       BBP_physical(bn->batCacheid), ".theap",
     794             :                                       NULL);
     795        5879 :                         if (HEAPcopy(bn->tvheap, r1i.vh, 0) != GDK_SUCCEED)
     796           0 :                                 goto bailout;
     797             :                 }
     798       45014 :                 bn->ttype = r1->ttype;
     799       45014 :                 bn->tvarsized = true;
     800       45014 :                 bn->twidth = r1i.width;
     801       45014 :                 bn->tshift = r1i.shift;
     802             :         }
     803             : 
     804      249108 :         if (!BATtdense(r1) || (r2 && !BATtdense(r2)))
     805      233397 :                 BATtseqbase(bn, oid_nil);
     806             : 
     807       15711 :   doreturn:
     808     3798217 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT " r1=" ALGOBATFMT " r2=" ALGOOPTBATFMT
     809             :                   " -> " ALGOOPTBATFMT "%s%s " LLFMT "us\n",
     810             :                   ALGOBATPAR(l), ALGOBATPAR(or1), ALGOOPTBATPAR(or2),
     811             :                   ALGOOPTBATPAR(bn),
     812             :                   bn && bn->ttype == TYPE_str && bn->tvheap == r1i.vh ? " sharing string heap" : "",
     813             :                   msg, GDKusec() - t0);
     814     3798217 :         bat_iterator_end(&r1i);
     815     3831343 :         bat_iterator_end(&r2i);
     816     3814210 :         if (l != ol)
     817           0 :                 BBPreclaim(l);
     818     3819804 :         if (r1 != or1)
     819           4 :                 BBPreclaim(r1);
     820     3770690 :         if (r2 != or2)
     821           0 :                 BBPreclaim(r2);
     822             :         return bn;
     823             : 
     824         549 :   bailout:
     825         549 :         BBPreclaim(bn);
     826             :         bn = NULL;
     827           0 :         goto doreturn;
     828             : }
     829             : 
     830             : BAT *
     831      982955 : BATproject(BAT *restrict l, BAT *restrict r)
     832             : {
     833      982955 :         return BATproject2(l, r, NULL);
     834             : }
     835             : 
     836             : /* Calculate a chain of BATproject calls.
     837             :  * The argument is a NULL-terminated array of BAT pointers.
     838             :  * This function is equivalent (apart from reference counting) to a
     839             :  * sequence of calls
     840             :  * bn = BATproject(bats[0], bats[1]);
     841             :  * bn = BATproject(bn, bats[2]);
     842             :  * ...
     843             :  * bn = BATproject(bn, bats[n-1]);
     844             :  * return bn;
     845             :  * where none of the intermediates are actually produced (and bats[n]==NULL).
     846             :  * Note that all BATs except the last must have type oid/void or msk.
     847             :  *
     848             :  * We assume that all but the last BAT in the chain is temporary and
     849             :  * therefore there is no chance that another thread will modify it while
     850             :  * we're busy.  This is not necessarily the case for that last BAT, so
     851             :  * it uses a BAT iterator.
     852             :  */
     853             : BAT *
     854      727891 : BATprojectchain(BAT **bats)
     855             : {
     856             :         struct ba {
     857             :                 BAT *b;
     858             :                 oid hlo;
     859             :                 oid hhi;
     860             :                 BUN cnt;
     861             :                 oid *t;
     862             :                 struct canditer ci; /* used if .ci.s != NULL */
     863             :         } *ba;
     864             :         BAT **tobedeleted = NULL;
     865             :         int ndelete = 0;
     866             :         int n, i;
     867             :         BAT *b = NULL, *bn = NULL;
     868             :         BATiter bi;
     869             :         bool allnil = false;
     870             :         bool issorted = true;
     871             :         bool nonil = true;
     872             :         bool stringtrick = false;
     873             :         const void *nil;
     874             :         int tpe;
     875             :         lng t0 = 0;
     876             : 
     877      727891 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
     878             :         /* count number of participating BATs and allocate some
     879             :          * temporary work space */
     880     7228687 :         for (n = 0; bats[n]; n++) {
     881             :                 b = bats[n];
     882     6501044 :                 ndelete += (b->ttype == TYPE_msk || mask_cand(b));
     883     6501044 :                 TRC_DEBUG(ALGO, "arg %d: " ALGOBATFMT "\n",
     884             :                           n + 1, ALGOBATPAR(b));
     885             :         }
     886      727643 :         if (n == 0) {
     887           0 :                 GDKerror("must have BAT arguments\n");
     888           0 :                 return NULL;
     889             :         }
     890      727643 :         if (n == 1) {
     891           0 :                 bn = COLcopy(b, b->ttype, true, TRANSIENT);
     892           0 :                 TRC_DEBUG(ALGO, "single bat: copy -> " ALGOOPTBATFMT
     893             :                           " " LLFMT " usec\n",
     894             :                           ALGOOPTBATPAR(bn), GDKusec() - t0);
     895           0 :                 return bn;
     896             :         }
     897             : 
     898      732877 :         if (ndelete > 0 &&
     899        5226 :             (tobedeleted = GDKmalloc(sizeof(BAT *) * ndelete)) == NULL)
     900             :                 return NULL;
     901      727651 :         ba = GDKmalloc(sizeof(*ba) * n);
     902      724752 :         if (ba == NULL) {
     903           0 :                 GDKfree(tobedeleted);
     904           0 :                 return NULL;
     905             :         }
     906             : 
     907             :         ndelete = 0;
     908     7188376 :         for (n = 0, i = 0; bats[n]; n++) {
     909             :                 b = bats[n];
     910     6461585 :                 if (b->ttype == TYPE_msk || mask_cand(b)) {
     911         832 :                         if ((b = BATunmask(b)) == NULL) {
     912           0 :                                 goto bunins_failed;
     913             :                         }
     914        5205 :                         tobedeleted[ndelete++] = b;
     915             :                 }
     916     6465958 :                 if (bats[n+1] && BATtdense(b) && b->hseqbase == b->tseqbase && b->tseqbase == bats[n+1]->hseqbase && BATcount(b) == BATcount(bats[n+1]))
     917     5049700 :                         continue; /* skip dense bat */
     918     1416258 :                 ba[i] = (struct ba) {
     919             :                         .b = b,
     920     1416258 :                         .hlo = b->hseqbase,
     921     1416258 :                         .hhi = b->hseqbase + b->batCount,
     922             :                         .cnt = b->batCount,
     923     1416258 :                         .t = (oid *) Tloc(b, 0),
     924             :                 };
     925     1416258 :                 allnil |= b->ttype == TYPE_void && is_oid_nil(b->tseqbase);
     926     1416258 :                 issorted &= b->tsorted;
     927     1416258 :                 if (bats[n + 1])
     928      688923 :                         nonil &= b->tnonil;
     929     1416258 :                 if (b->tnonil && b->tkey && b->tsorted &&
     930      758540 :                     ATOMtype(b->ttype) == TYPE_oid) {
     931      663611 :                         canditer_init(&ba[i].ci, NULL, b);
     932             :                 }
     933     1413924 :                 i++;
     934             :         }
     935             :         n = i;
     936      726791 :         if (i<=2) {
     937      681904 :                 if (i == 1) {
     938       90270 :                         bn = ba[0].b;
     939       90270 :                         BBPfix(bn->batCacheid);
     940             :                 } else {
     941      591634 :                         bn = BATproject(ba[0].b, ba[1].b);
     942             :                 }
     943      681066 :                 while (ndelete-- > 0)
     944         200 :                         BBPunfix(tobedeleted[ndelete]->batCacheid);
     945      680866 :                 GDKfree(tobedeleted);
     946      675496 :                 GDKfree(ba);
     947      684328 :                 return bn;
     948             :         }
     949             :         /* b is last BAT in bats array */
     950       44887 :         tpe = ATOMtype(b->ttype);
     951       44887 :         nil = ATOMnilptr(tpe);
     952       44887 :         if (allnil || ba[0].cnt == 0) {
     953       29566 :                 bn = BATconstant(ba[0].hlo, tpe == TYPE_oid ? TYPE_void : tpe,
     954             :                                  nil, ba[0].cnt, TRANSIENT);
     955       26542 :                 while (ndelete-- > 0)
     956        3703 :                         BBPreclaim(tobedeleted[ndelete]);
     957       22839 :                 GDKfree(tobedeleted);
     958       22755 :                 GDKfree(ba);
     959       22954 :                 TRC_DEBUG(ALGO, "with %d bats: nil/empty -> " ALGOOPTBATFMT
     960             :                           " " LLFMT " usec\n",
     961             :                           n, ALGOOPTBATPAR(bn), GDKusec() - t0);
     962       22954 :                 return bn;
     963             :         }
     964             : 
     965       22122 :         bi = bat_iterator(b);
     966       21994 :         if (nonil && ATOMstorage(tpe) == TYPE_str && b->batRestricted == BAT_READ) {
     967             :                 stringtrick = true;
     968        6477 :                 bn = COLnew_intern(ba[0].hlo, tpe, ba[0].cnt, TRANSIENT, bi.width);
     969        6463 :                 if (bn && bn->tvheap) {
     970             :                         /* no need to remove any files since they were
     971             :                          * never created for this bat */
     972        6475 :                         HEAPdecref(bn->tvheap, false);
     973        6475 :                         bn->tvheap = NULL;
     974             :                 }
     975        6463 :                 tpe = bi.width == 1 ? TYPE_bte : (bi.width == 2 ? TYPE_sht : (bi.width == 4 ? TYPE_int : TYPE_lng));
     976             :         } else {
     977       15517 :                 bn = COLnew(ba[0].hlo, tpe, ba[0].cnt, TRANSIENT);
     978             :         }
     979       21940 :         if (bn == NULL) {
     980           0 :                 bat_iterator_end(&bi);
     981           0 :                 goto bunins_failed;
     982             :         }
     983             : 
     984       21940 :         assert(ba[n - 1].b == b);
     985       21940 :         ba[n - 1].t = bi.base;
     986       21940 :         if (ATOMtype(b->ttype) == TYPE_oid) {
     987             :                 /* oid all the way */
     988         880 :                 oid *d = (oid *) Tloc(bn, 0);
     989         880 :                 assert(!stringtrick);
     990    23380770 :                 for (BUN p = 0; p < ba[0].cnt; p++) {
     991    23379887 :                         oid o = ba[0].ci.s ? canditer_next(&ba[0].ci) : ba[0].t[p];
     992    73029393 :                         for (int i = 1; i < n; i++) {
     993    49649503 :                                 if (is_oid_nil(o)) {
     994           0 :                                         bn->tnil = true;
     995           0 :                                         break;
     996             :                                 }
     997    49649503 :                                 if (o < ba[i].hlo || o >= ba[i].hhi) {
     998           0 :                                         GDKerror("does not match always\n");
     999           0 :                                         bat_iterator_end(&bi);
    1000           0 :                                         goto bunins_failed;
    1001             :                                 }
    1002    49649503 :                                 o -= ba[i].hlo;
    1003    49649503 :                                 o = ba[i].ci.s ?
    1004    25458306 :                                     (ba[i].ci.tpe == cand_dense) ?
    1005    25458306 :                                         canditer_idx_dense(&ba[i].ci, o) :
    1006    66806526 :                                         canditer_idx(&ba[i].ci, o) : ba[i].t[o];
    1007             :                         }
    1008    23379890 :                         *d++ = o;
    1009             :                 }
    1010       21060 :         } else if (!ATOMvarsized(tpe)) {
    1011             :                 const void *v;
    1012       20547 :                 char *d = Tloc(bn, 0);
    1013             : 
    1014       20547 :                 bn->tnil = false;
    1015       20547 :                 n--;    /* stop one before the end, also ba[n] is last */
    1016   101807275 :                 for (BUN p = 0; p < ba[0].cnt; p++) {
    1017   101786570 :                         oid o = ba[0].ci.s ? canditer_next(&ba[0].ci) : ba[0].t[p];
    1018             : 
    1019   250360525 :                         for (int i = 1; i < n; i++) {
    1020   149064314 :                                 if (is_oid_nil(o)) {
    1021           0 :                                         bn->tnil = true;
    1022           0 :                                         break;
    1023             :                                 }
    1024   149064314 :                                 if (o < ba[i].hlo || o >= ba[i].hhi) {
    1025           0 :                                         GDKerror("does not match always\n");
    1026           0 :                                         bat_iterator_end(&bi);
    1027           0 :                                         goto bunins_failed;
    1028             :                                 }
    1029   149064314 :                                 o -= ba[i].hlo;
    1030   149064314 :                                 o = ba[i].ci.s ?
    1031    75965865 :                                     (ba[i].ci.tpe == cand_dense) ?
    1032    75965865 :                                         canditer_idx_dense(&ba[i].ci, o) :
    1033   211782579 :                                         canditer_idx(&ba[i].ci, o) : ba[i].t[o];
    1034             :                         }
    1035   101296211 :                         if (is_oid_nil(o)) {
    1036           0 :                                 assert(!stringtrick);
    1037           0 :                                 bn->tnil = true;
    1038             :                                 v = nil;
    1039   101296211 :                         } else if (o < ba[n].hlo || o >= ba[n].hhi) {
    1040           0 :                                 GDKerror("does not match always\n");
    1041           0 :                                 bat_iterator_end(&bi);
    1042           0 :                                 goto bunins_failed;
    1043             :                         } else {
    1044   101296211 :                                 o -= ba[n].hlo;
    1045   101296211 :                                 v = (const char *) bi.base + (o << bi.shift);
    1046             :                         }
    1047   101296211 :                         if (ATOMputFIX(tpe, d, v) != GDK_SUCCEED) {
    1048           0 :                                 bat_iterator_end(&bi);
    1049           0 :                                 goto bunins_failed;
    1050             :                         }
    1051   101786728 :                         d += bi.width;
    1052             :                 }
    1053       20705 :                 if (stringtrick) {
    1054        6476 :                         bn->tnil = false;
    1055        6476 :                         bn->tnonil = b->tnonil;
    1056        6476 :                         bn->tkey = false;
    1057        6476 :                         BBPshare(bi.vh->parentid);
    1058        6485 :                         assert(bn->tvheap == NULL);
    1059        6485 :                         bn->tvheap = bi.vh;
    1060        6485 :                         HEAPincref(bi.vh);
    1061        6491 :                         assert(bn->ttype == b->ttype);
    1062        6491 :                         assert(bn->tvarsized);
    1063        6491 :                         assert(bn->twidth == bi.width);
    1064        6491 :                         assert(bn->tshift == bi.shift);
    1065             :                 }
    1066             :                 n++;            /* undo for debug print */
    1067             :         } else {
    1068             :                 const void *v;
    1069             : 
    1070         513 :                 assert(!stringtrick);
    1071         513 :                 bn->tnil = false;
    1072         513 :                 n--;    /* stop one before the end, also ba[n] is last */
    1073       47234 :                 for (BUN p = 0; p < ba[0].cnt; p++) {
    1074       46720 :                         oid o = ba[0].ci.s ? canditer_next(&ba[0].ci) : ba[0].t[p];
    1075      118509 :                         for (int i = 1; i < n; i++) {
    1076       71853 :                                 if (is_oid_nil(o)) {
    1077           0 :                                         bn->tnil = true;
    1078           0 :                                         break;
    1079             :                                 }
    1080       71853 :                                 if (o < ba[i].hlo || o >= ba[i].hhi) {
    1081           0 :                                         GDKerror("does not match always\n");
    1082           0 :                                         bat_iterator_end(&bi);
    1083           0 :                                         goto bunins_failed;
    1084             :                                 }
    1085       71853 :                                 o -= ba[i].hlo;
    1086       71853 :                                 o = ba[i].ci.s ?
    1087       40420 :                                     (ba[i].ci.tpe == cand_dense) ?
    1088       40420 :                                         canditer_idx_dense(&ba[i].ci, o) :
    1089      111794 :                                         canditer_idx(&ba[i].ci, o) : ba[i].t[o];
    1090             :                         }
    1091       46656 :                         if (is_oid_nil(o)) {
    1092           0 :                                 bn->tnil = true;
    1093             :                                 v = nil;
    1094       46656 :                         } else if (o < ba[n].hlo || o >= ba[n].hhi) {
    1095           0 :                                 GDKerror("does not match always\n");
    1096           0 :                                 bat_iterator_end(&bi);
    1097           0 :                                 goto bunins_failed;
    1098             :                         } else {
    1099       46656 :                                 o -= ba[n].hlo;
    1100       46656 :                                 v = BUNtail(bi, o);
    1101             :                         }
    1102       46656 :                         if (bunfastapp(bn, v) != GDK_SUCCEED) {
    1103           0 :                                 bat_iterator_end(&bi);
    1104           0 :                                 goto bunins_failed;
    1105             :                         }
    1106             :                 }
    1107             :                 n++;            /* undo for debug print */
    1108             :         }
    1109       22117 :         bat_iterator_end(&bi);
    1110       22141 :         BATsetcount(bn, ba[0].cnt);
    1111       22101 :         bn->tsorted = (ba[0].cnt <= 1) | issorted;
    1112       22101 :         bn->trevsorted = ba[0].cnt <= 1;
    1113       22101 :         bn->tnonil = nonil & b->tnonil;
    1114       22101 :         bn->tseqbase = oid_nil;
    1115             :         /* note, b may point to one of the bats in tobedeleted, so
    1116             :          * reclaim after the last use of b */
    1117       23377 :         while (ndelete-- > 0)
    1118        1315 :                 BBPreclaim(tobedeleted[ndelete]);
    1119       22062 :         GDKfree(tobedeleted);
    1120       21998 :         GDKfree(ba);
    1121       22164 :         TRC_DEBUG(ALGO, "with %d bats: " ALGOOPTBATFMT " " LLFMT " usec\n",
    1122             :                   n, ALGOOPTBATPAR(bn), GDKusec() - t0);
    1123             :         return bn;
    1124             : 
    1125           0 :   bunins_failed:
    1126           0 :         while (ndelete-- > 0)
    1127           0 :                 BBPreclaim(tobedeleted[ndelete]);
    1128           0 :         GDKfree(tobedeleted);
    1129           0 :         GDKfree(ba);
    1130           0 :         BBPreclaim(bn);
    1131           0 :         TRC_DEBUG(ALGO, "failed " LLFMT "usec\n", GDKusec() - t0);
    1132             :         return NULL;
    1133             : }

Generated by: LCOV version 1.14