LCOV - code coverage report
Current view: top level - gdk - gdk_join.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1984 2999 66.2 %
Date: 2024-10-07 21:21:43 Functions: 27 30 90.0 %

          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_private.h"
      16             : #include "gdk_calc_private.h"
      17             : 
      18             : /*
      19             :  * All join variants produce some sort of join on two input BATs,
      20             :  * optionally subject to up to two candidate lists.  Only values in
      21             :  * the input BATs that are mentioned in the associated candidate list
      22             :  * (if provided) are eligible.  They all return two output BATs in the
      23             :  * first two arguments.  The join operations differ in the way in
      24             :  * which tuples from the two inputs are matched.
      25             :  *
      26             :  * The outputs consist of two aligned BATs (i.e. same length and same
      27             :  * hseqbase (0@0)) that contain the OIDs of the input BATs that match.
      28             :  * The candidate lists, if given, contain the OIDs of the associated
      29             :  * input BAT which must be considered for matching.  The input BATs
      30             :  * must have the same type.
      31             :  *
      32             :  * All functions also have a parameter nil_matches which indicates
      33             :  * whether NIL must be considered an ordinary value that can match, or
      34             :  * whether NIL must be considered to never match.
      35             :  *
      36             :  * The join functions that are provided here are:
      37             :  * BATjoin
      38             :  *      normal equi-join
      39             :  * BATleftjoin
      40             :  *      normal equi-join, but the left output is sorted
      41             :  * BATouterjoin
      42             :  *      equi-join, but the left output is sorted, and if there is no
      43             :  *      match for a value in the left input, there is still an output
      44             :  *      with NIL in the right output
      45             :  * BATsemijoin
      46             :  *      equi-join, but the left output is sorted, and if there are
      47             :  *      multiple matches, only one is returned (i.e., the left output
      48             :  *      is also key, making it a candidate list)
      49             :  * BATmarkjoin
      50             :  *      equi-join, but the left output is sorted, if there is no
      51             :  *      match for a value in the left input, there is still an output
      52             :  *      with NIL in the right output, and there is a third output column
      53             :  *      containing a flag that indicates the "certainty" of the match: 1
      54             :  *      there is a match, 0, there is no match and there are no NIL
      55             :  *      values, NIL, there is no match but there are NIL values
      56             :  * BATthetajoin
      57             :  *      theta-join: an extra operator must be provided encoded as an
      58             :  *      integer (macros JOIN_EQ, JOIN_NE, JOIN_LT, JOIN_LE, JOIN_GT,
      59             :  *      JOIN_GE); values match if the left input has the given
      60             :  *      relationship with the right input; order of the outputs is not
      61             :  *      guaranteed
      62             :  * BATbandjoin
      63             :  *      band-join: two extra input values (c1, c2) must be provided as
      64             :  *      well as Booleans (li, hi) that indicate whether the value
      65             :  *      ranges are inclusive or not; values in the left and right
      66             :  *      inputs match if right - c1 <[=] left <[=] right + c2; if c1 or
      67             :  *      c2 is NIL, there are no matches
      68             :  * BATrangejoin
      69             :  *      range-join: the right input consists of two aligned BATs,
      70             :  *      values match if the left value is between two corresponding
      71             :  *      right values; two extra Boolean parameters, li and hi,
      72             :  *      indicate whether equal values match
      73             :  *
      74             :  * In addition to these functions, there are two more functions that
      75             :  * are closely related:
      76             :  * BATintersect
      77             :  *      intersection: return a candidate list with OIDs of tuples in
      78             :  *      the left input whose value occurs in the right input
      79             :  * BATdiff
      80             :  *      difference: return a candidate list with OIDs of tuples in the
      81             :  *      left input whose value does not occur in the right input
      82             :  */
      83             : 
      84             : /* Perform a bunch of sanity checks on the inputs to a join. */
      85             : static gdk_return
      86      532041 : joinparamcheck(BAT *l, BAT *r1, BAT *r2, BAT *sl, BAT *sr, const char *func)
      87             : {
      88     1385349 :         if (ATOMtype(l->ttype) != ATOMtype(r1->ttype) ||
      89         294 :             (r2 && ATOMtype(l->ttype) != ATOMtype(r2->ttype))) {
      90           0 :                 GDKerror("%s: inputs not compatible.\n", func);
      91           0 :                 return GDK_FAIL;
      92             :         }
      93         147 :         if (r2 &&
      94         147 :             (BATcount(r1) != BATcount(r2) || r1->hseqbase != r2->hseqbase)) {
      95           0 :                 GDKerror("%s: right inputs not aligned.\n", func);
      96           0 :                 return GDK_FAIL;
      97             :         }
      98      532041 :         if ((sl && !BATiscand(sl)) || (sr && !BATiscand(sr))) {
      99           0 :                 GDKerror("%s: argument not a candidate list.\n", func);
     100           0 :                 return GDK_FAIL;
     101             :         }
     102             :         return GDK_SUCCEED;
     103             : }
     104             : 
     105             : #define INCRSIZELOG     (8 + (SIZEOF_OID / 2))
     106             : #define INCRSIZE        (1 << INCRSIZELOG)
     107             : 
     108             : /* Create the result bats for a join, returns the absolute maximum
     109             :  * number of outputs that could possibly be generated. */
     110             : static BUN
     111       82428 : joininitresults(BAT **r1p, BAT **r2p, BAT **r3p, BUN lcnt, BUN rcnt,
     112             :                 bool lkey, bool rkey, bool semi, bool nil_on_miss,
     113             :                 bool only_misses, bool min_one, BUN estimate)
     114             : {
     115       82428 :         BAT *r1 = NULL, *r2 = NULL, *r3 = NULL;
     116       82428 :         BUN maxsize, size;
     117             : 
     118             :         /* if nil_on_miss is set, we really need a right output */
     119       82428 :         assert(!nil_on_miss || r2p != NULL || r3p != NULL);
     120             : 
     121       82428 :         lkey |= lcnt <= 1;
     122       82428 :         rkey |= rcnt <= 1;
     123             : 
     124       82428 :         *r1p = NULL;
     125       82428 :         if (r2p)
     126       30002 :                 *r2p = NULL;
     127       82428 :         if (r3p)
     128         330 :                 *r3p = NULL;
     129       82428 :         if (lcnt == 0) {
     130             :                 /* there is nothing to match */
     131             :                 maxsize = 0;
     132       67561 :         } else if (!only_misses && !nil_on_miss && rcnt == 0) {
     133             :                 /* if right is empty, we have no hits, so if we don't
     134             :                  * want misses, the result is empty */
     135             :                 maxsize = 0;
     136       67616 :         } else if (rkey | semi | only_misses) {
     137             :                 /* each entry left matches at most one on right, in
     138             :                  * case nil_on_miss is also set, each entry matches
     139             :                  * exactly one (see below) */
     140             :                 maxsize = lcnt;
     141       46080 :         } else if (lkey) {
     142             :                 /* each entry on right is matched at most once */
     143       10938 :                 if (nil_on_miss) {
     144             :                         /* one entry left could match all right, and
     145             :                          * all other entries left match nil */
     146           1 :                         maxsize = lcnt + rcnt - 1;
     147             :                 } else {
     148             :                         maxsize = rcnt;
     149             :                 }
     150       35142 :         } else if (rcnt == 0) {
     151             :                 /* nil_on_miss must be true due to previous checks, so
     152             :                  * all values on left miss */
     153             :                 maxsize = lcnt;
     154       35179 :         } else if (BUN_MAX / lcnt >= rcnt) {
     155             :                 /* in the worst case we have a full cross product */
     156       35210 :                 maxsize = lcnt * rcnt;
     157             :         } else {
     158             :                 /* a BAT cannot grow larger than BUN_MAX */
     159             :                 maxsize = BUN_MAX;
     160             :         }
     161       82428 :         size = estimate == BUN_NONE ? lcnt < rcnt ? lcnt : rcnt : estimate;
     162       82428 :         if (size < INCRSIZE)
     163             :                 size = INCRSIZE;
     164       82428 :         if (size > maxsize)
     165             :                 size = maxsize;
     166       82428 :         if ((rkey | semi | only_misses) & nil_on_miss) {
     167             :                 /* see comment above: each entry left matches exactly
     168             :                  * once */
     169         101 :                 size = maxsize;
     170             :         }
     171       82428 :         if (min_one && size < lcnt)
     172           0 :                 size = lcnt;
     173             : 
     174       82428 :         if (maxsize == 0) {
     175       14750 :                 r1 = BATdense(0, 0, 0);
     176       14644 :                 if (r1 == NULL) {
     177             :                         return BUN_NONE;
     178             :                 }
     179       14644 :                 if (r2p) {
     180         647 :                         r2 = BATdense(0, 0, 0);
     181         652 :                         if (r2 == NULL) {
     182           0 :                                 BBPreclaim(r1);
     183           0 :                                 return BUN_NONE;
     184             :                         }
     185         652 :                         *r2p = r2;
     186             :                 }
     187       14649 :                 if (r3p) {
     188           0 :                         r3 = COLnew(0, TYPE_bit, 0, TRANSIENT);
     189           0 :                         if (r3 == NULL) {
     190           0 :                                 BBPreclaim(r1);
     191           0 :                                 BBPreclaim(r2);
     192           0 :                                 if (r2p)
     193           0 :                                         *r2p = NULL;
     194           0 :                                 return BUN_NONE;
     195             :                         }
     196           0 :                         *r3p = r3;
     197             :                 }
     198       14649 :                 *r1p = r1;
     199       14649 :                 return 0;
     200             :         }
     201             : 
     202       67678 :         r1 = COLnew(0, TYPE_oid, size, TRANSIENT);
     203       67026 :         if (r1 == NULL) {
     204             :                 return BUN_NONE;
     205             :         }
     206       67026 :         r1->tnil = false;
     207       67026 :         r1->tnonil = true;
     208       67026 :         r1->tkey = true;
     209       67026 :         r1->tsorted = true;
     210       67026 :         r1->trevsorted = true;
     211       67026 :         r1->tseqbase = 0;
     212       67026 :         r1->theap->dirty = true;
     213       67026 :         *r1p = r1;
     214       67026 :         if (r2p) {
     215       29003 :                 r2 = COLnew(0, TYPE_oid, size, TRANSIENT);
     216       29111 :                 if (r2 == NULL) {
     217           0 :                         BBPreclaim(r1);
     218           0 :                         return BUN_NONE;
     219             :                 }
     220       29111 :                 r2->tnil = false;
     221       29111 :                 r2->tnonil = true;
     222       29111 :                 r2->tkey = true;
     223       29111 :                 r2->tsorted = true;
     224       29111 :                 r2->trevsorted = true;
     225       29111 :                 r2->tseqbase = 0;
     226       29111 :                 r2->theap->dirty = true;
     227       29111 :                 *r2p = r2;
     228             :         }
     229       67134 :         if (r3p) {
     230         100 :                 BAT *r3 = COLnew(0, TYPE_bit, size, TRANSIENT);
     231         101 :                 if (r3 == NULL) {
     232           0 :                         BBPreclaim(r1);
     233           0 :                         BBPreclaim(r2);
     234           0 :                         return BUN_NONE;
     235             :                 }
     236         101 :                 r3->tnil = false;
     237         101 :                 r3->tnonil = true;
     238         101 :                 r3->tkey = false;
     239         101 :                 r3->tsorted = false;
     240         101 :                 r3->trevsorted = false;
     241         101 :                 r3->tseqbase = oid_nil;
     242         101 :                 r3->theap->dirty = true;
     243         101 :                 *r3p = r3;
     244             :         }
     245             :         return maxsize;
     246             : }
     247             : 
     248             : #define VALUE(s, x)     (s##vars ?                                      \
     249             :                          s##vars + VarHeapVal(s##vals, (x), s##i.width) : \
     250             :                          s##vals ? (const char *) s##vals + ((x) * s##i.width) : \
     251             :                          (s##val = BUNtoid(s, (x)), (const char *) &s##val))
     252             : #define FVALUE(s, x)    ((const char *) s##vals + ((x) * s##i.width))
     253             : 
     254             : #define APPEND(b, o)            (((oid *) b->theap->base)[b->batCount++] = (o))
     255             : 
     256             : static inline gdk_return
     257   161930446 : maybeextend(BAT *restrict r1, BAT *restrict r2, BAT *restrict r3,
     258             :             BUN cnt, BUN lcur, BUN lcnt, BUN maxsize)
     259             : {
     260   161930446 :         if (BATcount(r1) + cnt > BATcapacity(r1)) {
     261             :                 /* make some extra space by extrapolating how much more
     262             :                  * we need (fraction of l we've seen so far is used to
     263             :                  * estimate a new size but with a shallow slope so that
     264             :                  * a skewed join doesn't overwhelm, whilst making sure
     265             :                  * there is somewhat significant progress) */
     266        2176 :                 BUN newcap = (BUN) (lcnt / (lcnt / 4.0 + lcur * .75) * (BATcount(r1) + cnt));
     267        2176 :                 newcap = (newcap + INCRSIZE - 1) & ~(((BUN) 1 << INCRSIZELOG) - 1);
     268        2176 :                 if (newcap < cnt + BATcount(r1))
     269           0 :                         newcap = cnt + BATcount(r1) + INCRSIZE;
     270             :                 /* if close to maxsize, then just use maxsize */
     271        2176 :                 if (newcap + INCRSIZE > maxsize)
     272         168 :                         newcap = maxsize;
     273             :                 /* make sure heap.free is set properly before
     274             :                  * extending */
     275        2176 :                 BATsetcount(r1, BATcount(r1));
     276        2176 :                 if (BATextend(r1, newcap) != GDK_SUCCEED)
     277             :                         return GDK_FAIL;
     278        2176 :                 if (r2) {
     279        1309 :                         BATsetcount(r2, BATcount(r2));
     280        1309 :                         if (BATextend(r2, newcap) != GDK_SUCCEED)
     281             :                                 return GDK_FAIL;
     282        1309 :                         assert(BATcapacity(r1) == BATcapacity(r2));
     283             :                 }
     284        2176 :                 if (r3) {
     285           0 :                         BATsetcount(r3, BATcount(r3));
     286           0 :                         if (BATextend(r3, newcap) != GDK_SUCCEED)
     287             :                                 return GDK_FAIL;
     288           0 :                         assert(BATcapacity(r1) == BATcapacity(r3));
     289             :                 }
     290             :         }
     291             :         return GDK_SUCCEED;
     292             : }
     293             : 
     294             : /* Return BATs through r1p, r2p, and r3p for the case that there is no
     295             :  * match between l and r, taking all flags into consideration.
     296             :  *
     297             :  * This means, if nil_on_miss is set or only_misses is set, *r1p is a
     298             :  * copy of the left candidate list or a dense list of all "head"
     299             :  * values of l, and *r2p (if r2p is not NULL) is all nil.  If neither
     300             :  * of those flags is set, the result is two empty BATs. */
     301             : static gdk_return
     302      380783 : nomatch(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r,
     303             :         struct canditer *restrict lci, bit defmark,
     304             :         bool nil_on_miss, bool only_misses, const char *func, lng t0)
     305             : {
     306      380783 :         BAT *r1, *r2 = NULL, *r3 = NULL;
     307             : 
     308      380783 :         MT_thread_setalgorithm(__func__);
     309      381098 :         if (lci->ncand == 0 || !(nil_on_miss | only_misses)) {
     310             :                 /* return empty BATs */
     311      362536 :                 if ((r1 = BATdense(0, 0, 0)) == NULL)
     312             :                         return GDK_FAIL;
     313      362530 :                 if (r2p) {
     314      269038 :                         if ((r2 = BATdense(0, 0, 0)) == NULL) {
     315           0 :                                 BBPreclaim(r1);
     316           0 :                                 return GDK_FAIL;
     317             :                         }
     318      269196 :                         *r2p = r2;
     319             :                 }
     320      362688 :                 if (r3p) {
     321        3933 :                         if ((r3 = COLnew(0, TYPE_bit, 0, TRANSIENT)) == NULL) {
     322           0 :                                 BBPreclaim(r1);
     323           0 :                                 BBPreclaim(r2);
     324           0 :                                 return GDK_FAIL;
     325             :                         }
     326        3951 :                         *r3p = r3;
     327             :                 }
     328             :         } else {
     329       18562 :                 r1 = canditer_slice(lci, 0, lci->ncand);
     330       18566 :                 if (r2p) {
     331           5 :                         if ((r2 = BATconstant(0, TYPE_void, &oid_nil, lci->ncand, TRANSIENT)) == NULL) {
     332           0 :                                 BBPreclaim(r1);
     333           0 :                                 return GDK_FAIL;
     334             :                         }
     335           5 :                         *r2p = r2;
     336             :                 }
     337       18566 :                 if (r3p) {
     338          47 :                         if ((r3 = BATconstant(0, TYPE_bit, &defmark, lci->ncand, TRANSIENT)) == NULL) {
     339           0 :                                 BBPreclaim(r1);
     340           0 :                                 BBPreclaim(r2);
     341           0 :                                 return GDK_FAIL;
     342             :                         }
     343          47 :                         *r3p = r3;
     344             :                 }
     345             :         }
     346      381272 :         *r1p = r1;
     347      381272 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT
     348             :                   ",nil_on_miss=%s,only_misses=%s"
     349             :                   " - > " ALGOBATFMT "," ALGOOPTBATFMT "," ALGOOPTBATFMT
     350             :                   " (%s -- " LLFMT "usec)\n",
     351             :                   ALGOBATPAR(l), ALGOBATPAR(r), ALGOOPTBATPAR(lci->s),
     352             :                   nil_on_miss ? "true" : "false",
     353             :                   only_misses ? "true" : "false",
     354             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2), ALGOOPTBATPAR(r3),
     355             :                   func, GDKusec() - t0);
     356             :         return GDK_SUCCEED;
     357             : }
     358             : 
     359             : /* Implementation of join where there is a single value (possibly
     360             :  * repeated multiple times) on the left.  This means we can use a
     361             :  * point select to find matches in the right column. */
     362             : static gdk_return
     363       49804 : selectjoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r,
     364             :            struct canditer *lci, struct canditer *rci,
     365             :            bool nil_matches, bool nil_on_miss, bool semi, bool max_one, bool min_one,
     366             :            lng t0, bool swapped, const char *reason)
     367             : {
     368       49804 :         BATiter li = bat_iterator(l);
     369       49826 :         const void *v;
     370       49826 :         BAT *bn = NULL;
     371       49826 :         BAT *r1 = NULL;
     372       49826 :         BAT *r2 = NULL;
     373       49826 :         BUN bncount;
     374             : 
     375       49826 :         assert(lci->ncand > 0);
     376       49826 :         assert(lci->ncand == 1 || (li.sorted && li.revsorted));
     377             : 
     378       49826 :         size_t counter = 0;
     379       49826 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     380             : 
     381       49822 :         MT_thread_setalgorithm(__func__);
     382       49825 :         oid o = canditer_next(lci);
     383       49801 :         v = BUNtail(li, o - l->hseqbase);
     384             : 
     385       97406 :         if (!nil_matches &&
     386       47606 :             (*ATOMcompare(li.type))(v, ATOMnilptr(li.type)) == 0) {
     387             :                 /* NIL doesn't match anything */
     388         144 :                 bat_iterator_end(&li);
     389         144 :                 gdk_return rc = nomatch(r1p, r2p, r3p, l, r, lci, bit_nil, nil_on_miss,
     390             :                                         false, reason, t0);
     391         144 :                 return rc;
     392             :         }
     393             : 
     394       49656 :         bn = BATselect(r, rci->s, v, NULL, true, true, false, false);
     395       49551 :         bat_iterator_end(&li);
     396       49646 :         if (bn == NULL) {
     397             :                 return GDK_FAIL;
     398             :         }
     399       49646 :         bncount = BATcount(bn);
     400       49646 :         if (bncount == 0) {
     401       12277 :                 BBPreclaim(bn);
     402       12229 :                 if (min_one) {
     403           0 :                         GDKerror("not enough matches");
     404           0 :                         return GDK_FAIL;
     405             :                 }
     406       12229 :                 if (!nil_on_miss) {
     407       12071 :                         assert(r3p == NULL);
     408       12071 :                         return nomatch(r1p, r2p, r3p, l, r, lci, 0, nil_on_miss,
     409             :                                        false, reason, t0);
     410             :                 }
     411             :                 /* special case: return nil on RHS */
     412             :                 bncount = 1;
     413             :                 bn = NULL;
     414             :         }
     415       37369 :         if (bncount > 1) {
     416        1836 :                 if (semi)
     417         693 :                         bncount = 1;
     418        1836 :                 if (max_one) {
     419          12 :                         GDKerror("more than one match");
     420          12 :                         goto bailout;
     421             :                 }
     422             :         }
     423       37515 :         r1 = COLnew(0, TYPE_oid, lci->ncand * bncount, TRANSIENT);
     424       37516 :         if (r1 == NULL)
     425           0 :                 goto bailout;
     426       37516 :         r1->tsorted = true;
     427       37516 :         r1->trevsorted = lci->ncand == 1;
     428       37516 :         r1->tseqbase = bncount == 1 && lci->tpe == cand_dense ? o : oid_nil;
     429       37516 :         r1->tkey = bncount == 1;
     430       37516 :         r1->tnil = false;
     431       37516 :         r1->tnonil = true;
     432       37516 :         if (bn == NULL) {
     433             :                 /* left outer join, no match, we're returning nil in r2 */
     434         158 :                 oid *o1p = (oid *) Tloc(r1, 0);
     435         158 :                 BUN p, q = bncount;
     436             : 
     437         158 :                 if (r2p) {
     438           2 :                         r2 = BATconstant(0, TYPE_void, &oid_nil, lci->ncand * bncount, TRANSIENT);
     439           2 :                         if (r2 == NULL)
     440           0 :                                 goto bailout;
     441           2 :                         *r2p = r2;
     442             :                 }
     443         318 :                 do {
     444         318 :                         GDK_CHECK_TIMEOUT(qry_ctx, counter,
     445             :                                           GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     446         636 :                         for (p = 0; p < q; p++) {
     447         318 :                                 *o1p++ = o;
     448             :                         }
     449         318 :                         o = canditer_next(lci);
     450         318 :                 } while (!is_oid_nil(o));
     451             :         } else {
     452       37358 :                 oid *o1p = (oid *) Tloc(r1, 0);
     453       37358 :                 oid *o2p;
     454       37358 :                 BUN p, q = bncount;
     455             : 
     456       37358 :                 if (r2p) {
     457       32441 :                         r2 = COLnew(0, TYPE_oid, lci->ncand * bncount, TRANSIENT);
     458       32456 :                         if (r2 == NULL)
     459           0 :                                 goto bailout;
     460       32456 :                         r2->tsorted = lci->ncand == 1 || bncount == 1;
     461       32456 :                         r2->trevsorted = bncount == 1;
     462       32456 :                         r2->tseqbase = lci->ncand == 1 && BATtdense(bn) ? bn->tseqbase : oid_nil;
     463       32456 :                         r2->tkey = lci->ncand == 1;
     464       32456 :                         r2->tnil = false;
     465       32456 :                         r2->tnonil = true;
     466       32456 :                         *r2p = r2;
     467       32456 :                         o2p = (oid *) Tloc(r2, 0);
     468             :                 } else {
     469             :                         o2p = NULL;
     470             :                 }
     471             : 
     472       37373 :                 if (BATtdense(bn)) {
     473             :                         oid bno = bn->tseqbase;
     474             : 
     475     1306311 :                         do {
     476     1306311 :                                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
     477             :                                                   GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     478     2666084 :                                 for (p = 0; p < q; p++) {
     479     1359773 :                                         *o1p++ = o;
     480             :                                 }
     481     1306311 :                                 if (o2p) {
     482      436086 :                                         for (p = 0; p < q; p++) {
     483      244732 :                                                 *o2p++ = bno + p;
     484             :                                         }
     485             :                                 }
     486     1306311 :                                 o = canditer_next(lci);
     487     1306313 :                         } while (!is_oid_nil(o));
     488             :                 } else {
     489         294 :                         const oid *bnp = (const oid *) Tloc(bn, 0);
     490             : 
     491      122471 :                         do {
     492      122471 :                                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
     493             :                                                   GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     494     4659190 :                                 for (p = 0; p < q; p++) {
     495     4536719 :                                         *o1p++ = o;
     496             :                                 }
     497      122471 :                                 if (o2p) {
     498     4762099 :                                         for (p = 0; p < q; p++) {
     499     4629118 :                                                 *o2p++ = bnp[p];
     500             :                                         }
     501             :                                 }
     502      122471 :                                 o = canditer_next(lci);
     503      122467 :                         } while (!is_oid_nil(o));
     504             :                 }
     505       37371 :                 if (r2)
     506       32450 :                         BATsetcount(r2, lci->ncand * bncount);
     507             :         }
     508       37529 :         BATsetcount(r1, lci->ncand * bncount);
     509       37541 :         *r1p = r1;
     510       37541 :         BAT *r3 = NULL;
     511       37541 :         if (r3p) {
     512         182 :                 bit mark;
     513         182 :                 if (bn) {
     514             :                         /* there is a match */
     515          25 :                         mark = 1;
     516         157 :                 } else if (r->tnonil) {
     517             :                         /* no match, no NIL in r */
     518         153 :                         mark = 0;
     519             :                 } else {
     520             :                         /* no match, search for NIL in r */
     521           4 :                         BAT *n = BATselect(r, rci->s, ATOMnilptr(r->ttype), NULL, true, true, false, false);
     522           4 :                         if (n == NULL)
     523           0 :                                 goto bailout;
     524           4 :                         mark = BATcount(n) == 0 ? 0 : bit_nil;
     525           4 :                         BBPreclaim(n);
     526             :                 }
     527         182 :                 r3 = BATconstant(0, TYPE_bit, &mark, lci->ncand, TRANSIENT);
     528         182 :                 if (r3 == NULL)
     529           0 :                         goto bailout;
     530         182 :                 *r3p = r3;
     531             :         }
     532       37541 :         BBPreclaim(bn);
     533       37524 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
     534             :                   "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
     535             :                   "sr=" ALGOOPTBATFMT ",nil_matches=%s;%s %s "
     536             :                   "-> " ALGOBATFMT "," ALGOOPTBATFMT "," ALGOOPTBATFMT
     537             :                   " (" LLFMT "usec)\n",
     538             :                   ALGOBATPAR(l), ALGOBATPAR(r),
     539             :                   ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
     540             :                   nil_matches ? "true" : "false",
     541             :                   swapped ? " swapped" : "", reason,
     542             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2), ALGOOPTBATPAR(r3),
     543             :                   GDKusec() - t0);
     544             : 
     545             :         return GDK_SUCCEED;
     546             : 
     547          12 :   bailout:
     548          12 :         BBPreclaim(bn);
     549          12 :         BBPreclaim(r1);
     550          12 :         BBPreclaim(r2);
     551          12 :         if (r2p)
     552          11 :                 *r2p = NULL;
     553             :         return GDK_FAIL;
     554             : }
     555             : 
     556             : #if SIZEOF_OID == SIZEOF_INT
     557             : #define binsearch_oid(indir, offset, vals, lo, hi, v, ordering, last) binsearch_int(indir, offset, (const int *) vals, lo, hi, (int) (v), ordering, last)
     558             : #endif
     559             : #if SIZEOF_OID == SIZEOF_LNG
     560             : #define binsearch_oid(indir, offset, vals, lo, hi, v, ordering, last) binsearch_lng(indir, offset, (const lng *) vals, lo, hi, (lng) (v), ordering, last)
     561             : #endif
     562             : 
     563             : /* Implementation of join where the right-hand side is dense, and if
     564             :  * there is a right candidate list, it too is dense.  This means there
     565             :  * are no NIL values in r.  In case nil_on_miss is not set, we use a
     566             :  * range select (BATselect) to find the matching values in the left
     567             :  * column and then calculate the corresponding matches from the right.
     568             :  * If nil_on_miss is set, we need to do some more work. The latter is
     569             :  * also the only case in which r3p van be set. */
     570             : static gdk_return
     571       25190 : mergejoin_void(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r,
     572             :                struct canditer *restrict lci, struct canditer *restrict rci,
     573             :                bool nil_on_miss, bool only_misses, lng t0, bool swapped,
     574             :                const char *reason)
     575             : {
     576       25190 :         oid lo, hi;
     577       25190 :         BUN i;
     578       25190 :         oid o, *o1p = NULL, *o2p = NULL;
     579       25190 :         bit *m3p = NULL;
     580       25190 :         BAT *r1 = NULL, *r2 = NULL, *r3 = NULL;
     581       25190 :         bool ltsorted = false, ltrevsorted = false, ltkey = false;
     582             : 
     583             :         /* r is dense, and if there is a candidate list, it too is
     584             :          * dense.  This means we don't have to do any searches, we
     585             :          * only need to compare ranges to know whether a value from l
     586             :          * has a match in r */
     587       36339 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
     588       25190 :         assert(r->tsorted || r->trevsorted);
     589       25190 :         assert(BATcount(l) > 0);
     590       25190 :         assert(rci->tpe == cand_dense);
     591       25190 :         assert(BATcount(r) > 0);
     592             : 
     593       25190 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
     594             : 
     595       25196 :         MT_thread_setalgorithm(__func__);
     596             :         /* figure out range [lo..hi) of values in r that we need to match */
     597       25210 :         lo = r->tseqbase;
     598       25210 :         hi = lo + BATcount(r);
     599             :         /* restrict [lo..hi) range further using candidate list */
     600       25210 :         if (rci->seq > r->hseqbase)
     601           0 :                 lo += rci->seq - r->hseqbase;
     602       25210 :         if (rci->seq + rci->ncand < r->hseqbase + BATcount(r))
     603           0 :                 hi -= r->hseqbase + BATcount(r) - rci->seq - rci->ncand;
     604             : 
     605             :         /* at this point, the matchable values in r are [lo..hi) */
     606       25210 :         if (!nil_on_miss) {
     607       25210 :                 assert(r3p == NULL);
     608       25210 :                 r1 = BATselect(l, lci->s, &lo, &hi, true, false, only_misses, false);
     609       25155 :                 if (r1 == NULL)
     610             :                         return GDK_FAIL;
     611       25155 :                 if (only_misses && !l->tnonil) {
     612             :                         /* also look for NILs */
     613           0 :                         r2 = BATselect(l, lci->s, &oid_nil, NULL, true, false, false, false);
     614           0 :                         if (r2 == NULL) {
     615           0 :                                 BBPreclaim(r1);
     616           0 :                                 return GDK_FAIL;
     617             :                         }
     618           0 :                         if (BATcount(r2) > 0) {
     619           0 :                                 BAT *mg = BATmergecand(r1, r2);
     620           0 :                                 BBPunfix(r1->batCacheid);
     621           0 :                                 BBPunfix(r2->batCacheid);
     622           0 :                                 r1 = mg;
     623           0 :                                 if (r1 == NULL)
     624             :                                         return GDK_FAIL;
     625             :                         } else {
     626           0 :                                 BBPunfix(r2->batCacheid);
     627             :                         }
     628             :                         r2 = NULL;
     629             :                 }
     630       25155 :                 *r1p = r1;
     631       25155 :                 if (r2p == NULL)
     632       24027 :                         goto doreturn2;
     633        1128 :                 if (BATcount(r1) == 0) {
     634          44 :                         r2 = BATdense(0, 0, 0);
     635          44 :                         if (r2 == NULL) {
     636           0 :                                 BBPreclaim(r1);
     637           0 :                                 return GDK_FAIL;
     638             :                         }
     639        1084 :                 } else if (BATtdense(r1) && BATtdense(l)) {
     640          56 :                         r2 = BATdense(0, l->tseqbase + r1->tseqbase - l->hseqbase + r->hseqbase - r->tseqbase, BATcount(r1));
     641          56 :                         if (r2 == NULL) {
     642           0 :                                 BBPreclaim(r1);
     643           0 :                                 return GDK_FAIL;
     644             :                         }
     645             :                 } else {
     646        1028 :                         r2 = COLnew(0, TYPE_oid, BATcount(r1), TRANSIENT);
     647        1039 :                         if (r2 == NULL) {
     648           0 :                                 BBPreclaim(r1);
     649           0 :                                 return GDK_FAIL;
     650             :                         }
     651        1039 :                         BATiter li = bat_iterator(l);
     652        1028 :                         const oid *lp = (const oid *) li.base;
     653        1028 :                         const oid *o1p = (const oid *) Tloc(r1, 0);
     654        1028 :                         oid *o2p = (oid *) Tloc(r2, 0);
     655        1028 :                         hi = BATcount(r1);
     656        1028 :                         if (complex_cand(l)) {
     657             :                                 /* this is actually generic code */
     658           0 :                                 for (o = 0; o < hi; o++)
     659           0 :                                         o2p[o] = BUNtoid(l, BUNtoid(r1, o) - l->hseqbase) - r->tseqbase + r->hseqbase;
     660        1028 :                         } else if (BATtdense(r1)) {
     661         468 :                                 lo = r1->tseqbase - l->hseqbase;
     662         468 :                                 if (r->tseqbase == r->hseqbase) {
     663         459 :                                         memcpy(o2p, lp + lo, hi * SIZEOF_OID);
     664             :                                 } else {
     665           9 :                                         hi += lo;
     666     5085015 :                                         for (o = 0; lo < hi; o++, lo++) {
     667     5085006 :                                                 o2p[o] = lp[lo] - r->tseqbase + r->hseqbase;
     668             :                                         }
     669             :                                 }
     670         560 :                         } else if (BATtdense(l)) {
     671           0 :                                 for (o = 0; o < hi; o++) {
     672           0 :                                         o2p[o] = o1p[o] - l->hseqbase + li.tseq - r->tseqbase + r->hseqbase;
     673             :                                 }
     674             :                         } else {
     675    33466517 :                                 for (o = 0; o < hi; o++) {
     676    33465957 :                                         o2p[o] = lp[o1p[o] - l->hseqbase] - r->tseqbase + r->hseqbase;
     677             :                                 }
     678             :                         }
     679        1028 :                         r2->tkey = li.key;
     680        1028 :                         r2->tsorted = li.sorted;
     681        1028 :                         r2->trevsorted = li.revsorted;
     682        1028 :                         bat_iterator_end(&li);
     683        1039 :                         r2->tnil = false;
     684        1039 :                         r2->tnonil = true;
     685        1039 :                         BATsetcount(r2, BATcount(r1));
     686             :                 }
     687        1138 :                 *r2p = r2;
     688        1138 :                 goto doreturn2;
     689             :         }
     690             :         /* nil_on_miss is set, this means we must have a second or third
     691             :          * output */
     692           0 :         assert(r2p || r3p);
     693           0 :         if (BATtdense(l)) {
     694             :                 /* if l is dense, we can further restrict the [lo..hi)
     695             :                  * range to values in l that match with values in r */
     696           0 :                 o = lo;
     697           0 :                 i = lci->seq - l->hseqbase;
     698           0 :                 if (l->tseqbase + i > lo)
     699           0 :                         lo = l->tseqbase + i;
     700           0 :                 i = canditer_last(lci) + 1 - l->hseqbase;
     701           0 :                 if (l->tseqbase + i < hi)
     702           0 :                         hi = l->tseqbase + i;
     703           0 :                 if (lci->tpe == cand_dense) {
     704             :                         /* l is dense, and so is the left candidate
     705             :                          * list (if it exists); this means we don't
     706             :                          * have to actually look at any values in l:
     707             :                          * we can just do some arithmetic; it also
     708             :                          * means that r1 will be dense, and if
     709             :                          * nil_on_miss is not set, or if all values in
     710             :                          * l match, r2 will too */
     711           0 :                         if (hi <= lo) {
     712           0 :                                 return nomatch(r1p, r2p, r3p, l, r, lci, 0,
     713             :                                                nil_on_miss, only_misses,
     714             :                                                __func__, t0);
     715             :                         }
     716             : 
     717             :                         /* at this point, the matched values in l and
     718             :                          * r (taking candidate lists into account) are
     719             :                          * [lo..hi) which we can translate back to the
     720             :                          * respective OID values that we can store in
     721             :                          * r1 and r2; note that r1 will be dense since
     722             :                          * all values in l will match something (even
     723             :                          * if nil since nil_on_miss is set) */
     724           0 :                         *r1p = r1 = BATdense(0, lci->seq, lci->ncand);
     725           0 :                         if (r1 == NULL)
     726             :                                 return GDK_FAIL;
     727           0 :                         if (r2p) {
     728           0 :                                 if (hi - lo < lci->ncand) {
     729             :                                         /* we need to fill in nils in r2 for
     730             :                                          * missing values */
     731           0 :                                         *r2p = r2 = COLnew(0, TYPE_oid, lci->ncand, TRANSIENT);
     732           0 :                                         if (r2 == NULL) {
     733           0 :                                                 BBPreclaim(*r1p);
     734           0 :                                                 return GDK_FAIL;
     735             :                                         }
     736           0 :                                         o2p = (oid *) Tloc(r2, 0);
     737           0 :                                         i = l->tseqbase + lci->seq - l->hseqbase;
     738           0 :                                         lo -= i;
     739           0 :                                         hi -= i;
     740           0 :                                         i += r->hseqbase - r->tseqbase;
     741           0 :                                         for (o = 0; o < lo; o++)
     742           0 :                                                 *o2p++ = oid_nil;
     743           0 :                                         for (o = lo; o < hi; o++)
     744           0 :                                                 *o2p++ = o + i;
     745           0 :                                         for (o = hi; o < lci->ncand; o++)
     746           0 :                                                 *o2p++ = oid_nil;
     747           0 :                                         r2->tnonil = false;
     748           0 :                                         r2->tnil = true;
     749             :                                         /* sorted of no nils at end */
     750           0 :                                         r2->tsorted = hi == lci->ncand;
     751             :                                         /* reverse sorted if single non-nil at start */
     752           0 :                                         r2->trevsorted = lo == 0 && hi == 1;
     753           0 :                                         r2->tseqbase = oid_nil;
     754             :                                         /* (hi - lo) different OIDs in r2,
     755             :                                          * plus one for nil */
     756           0 :                                         r2->tkey = hi - lo + 1 == lci->ncand;
     757           0 :                                         BATsetcount(r2, lci->ncand);
     758             :                                 } else {
     759             :                                         /* no missing values */
     760           0 :                                         *r2p = r2 = BATdense(0, r->hseqbase + lo - r->tseqbase, lci->ncand);
     761           0 :                                         if (r2 == NULL) {
     762           0 :                                                 BBPreclaim(*r1p);
     763           0 :                                                 return GDK_FAIL;
     764             :                                         }
     765             :                                 }
     766             :                         }
     767           0 :                         if (r3p) {
     768           0 :                                 if (hi - lo < lci->ncand) {
     769           0 :                                         *r3p = r3 = COLnew(0, TYPE_bit, lci->ncand, TRANSIENT);
     770           0 :                                         if (r3 == NULL) {
     771           0 :                                                 BBPreclaim(*r1p);
     772           0 :                                                 BBPreclaim(r2);
     773           0 :                                                 return GDK_FAIL;
     774             :                                         }
     775           0 :                                         m3p = (bit *) Tloc(r3, 0);
     776           0 :                                         for (o = 0; o < lo; o++)
     777           0 :                                                 *m3p++ = 0;
     778           0 :                                         for (o = lo; o < hi; o++)
     779           0 :                                                 *m3p++ = 1;
     780           0 :                                         for (o = hi; o < lci->ncand; o++)
     781           0 :                                                 *m3p++ = 0;
     782           0 :                                         r3->tnonil = true;
     783           0 :                                         r3->tnil = false;
     784           0 :                                         r3->tsorted = hi == lci->ncand;
     785           0 :                                         r3->trevsorted = lo == 0;
     786           0 :                                         r3->tkey = false;
     787           0 :                                         BATsetcount(r3, lci->ncand);
     788             :                                 }
     789             :                         }
     790           0 :                         goto doreturn;
     791             :                 }
     792             :                 /* l is dense, but the candidate list exists and is
     793             :                  * not dense; we can, by manipulating the range
     794             :                  * [lo..hi), just look at the candidate list values */
     795             : 
     796             :                 /* translate lo and hi to l's OID values that now need
     797             :                  * to match */
     798           0 :                 lo = lo - l->tseqbase + l->hseqbase;
     799           0 :                 hi = hi - l->tseqbase + l->hseqbase;
     800             : 
     801           0 :                 *r1p = r1 = COLnew(0, TYPE_oid, lci->ncand, TRANSIENT);
     802           0 :                 if (r2p)
     803           0 :                         *r2p = r2 = COLnew(0, TYPE_oid, lci->ncand, TRANSIENT);
     804           0 :                 if (r3p)
     805           0 :                         *r3p = r3 = COLnew(0, TYPE_bit, lci->ncand, TRANSIENT);
     806           0 :                 if (r1 == NULL || (r2p != NULL && r2 == NULL) || (r3p != NULL && r3 == NULL)) {
     807           0 :                         BBPreclaim(r1);
     808           0 :                         BBPreclaim(r2);
     809           0 :                         BBPreclaim(r3);
     810           0 :                         return GDK_FAIL;
     811             :                 }
     812           0 :                 o1p = (oid *) Tloc(r1, 0);
     813           0 :                 if (r2) {
     814           0 :                         o2p = (oid *) Tloc(r2, 0);
     815           0 :                         r2->tnil = false;
     816           0 :                         r2->tnonil = true;
     817           0 :                         r2->tkey = true;
     818           0 :                         r2->tsorted = true;
     819             :                 }
     820           0 :                 if (r3) {
     821           0 :                         m3p = (bit *) Tloc(r3, 0);
     822           0 :                         r3->tnil = false;
     823           0 :                         r3->tnonil = true;
     824           0 :                         r3->tkey = false;
     825           0 :                         r3->tsorted = false;
     826             :                 }
     827           0 :                 o = canditer_next(lci);
     828           0 :                 for (i = 0; i < lci->ncand && o < lo; i++) {
     829           0 :                         *o1p++ = o;
     830           0 :                         if (r2)
     831           0 :                                 *o2p++ = oid_nil;
     832           0 :                         if (r3)
     833           0 :                                 *m3p++ = 0;
     834           0 :                         o = canditer_next(lci);
     835             :                 }
     836           0 :                 if (i > 0 && r2) {
     837           0 :                         r2->tnil = true;
     838           0 :                         r2->tnonil = false;
     839           0 :                         r2->tkey = i == 1;
     840             :                 }
     841           0 :                 for (; i < lci->ncand && o < hi; i++) {
     842           0 :                         *o1p++ = o;
     843           0 :                         if (r2)
     844           0 :                                 *o2p++ = o - l->hseqbase + l->tseqbase - r->tseqbase + r->hseqbase;
     845           0 :                         if (r3)
     846           0 :                                 *m3p++ = 1;
     847           0 :                         o = canditer_next(lci);
     848             :                 }
     849           0 :                 if (i < lci->ncand) {
     850           0 :                         if (r2) {
     851           0 :                                 r2->tkey = !r2->tnil && lci->ncand - i == 1;
     852           0 :                                 r2->tnil = true;
     853           0 :                                 r2->tnonil = false;
     854           0 :                                 r2->tsorted = false;
     855             :                         }
     856           0 :                         for (; i < lci->ncand; i++) {
     857           0 :                                 *o1p++ = o;
     858           0 :                                 if (r2)
     859           0 :                                         *o2p++ = oid_nil;
     860           0 :                                 if (r1)
     861           0 :                                         *m3p++ = 0;
     862           0 :                                 o = canditer_next(lci);
     863             :                         }
     864             :                 }
     865           0 :                 BATsetcount(r1, lci->ncand);
     866           0 :                 r1->tseqbase = BATcount(r1) == 1 ? *(oid*)Tloc(r1, 0) : oid_nil;
     867           0 :                 r1->tsorted = true;
     868           0 :                 r1->trevsorted = BATcount(r1) <= 1;
     869           0 :                 r1->tnil = false;
     870           0 :                 r1->tnonil = true;
     871           0 :                 r1->tkey = true;
     872           0 :                 if (r2) {
     873           0 :                         BATsetcount(r2, BATcount(r1));
     874           0 :                         r2->tseqbase = r2->tnil || BATcount(r2) > 1 ? oid_nil : BATcount(r2) == 1 ? *(oid*)Tloc(r2, 0) : 0;
     875           0 :                         r2->trevsorted = BATcount(r2) <= 1;
     876             :                 }
     877           0 :                 if (r3) {
     878           0 :                         BATsetcount(r3, BATcount(r1));
     879             :                 }
     880           0 :                 goto doreturn;
     881             :         }
     882             :         /* l is not dense, so we need to look at the values and check
     883             :          * whether they are in the range [lo..hi) */
     884             : 
     885             :         /* do indirection through the candidate list to look at the
     886             :          * value */
     887             : 
     888           0 :         *r1p = r1 = COLnew(0, TYPE_oid, lci->ncand, TRANSIENT);
     889           0 :         if (r2p)
     890           0 :                 *r2p = r2 = COLnew(0, TYPE_oid, lci->ncand, TRANSIENT);
     891           0 :         if (r3p)
     892           0 :                 *r3p = r3 = COLnew(0, TYPE_bit, lci->ncand, TRANSIENT);
     893           0 :         if (r1 == NULL || (r2p != NULL && r2 == NULL) || (r3p != NULL && r3 == NULL)) {
     894           0 :                 BBPreclaim(r1);
     895           0 :                 BBPreclaim(r2);
     896           0 :                 BBPreclaim(r3);
     897           0 :                 return GDK_FAIL;
     898             :         }
     899           0 :         o1p = (oid *) Tloc(r1, 0);
     900           0 :         if (r2) {
     901           0 :                 o2p = (oid *) Tloc(r2, 0);
     902           0 :                 r2->tnil = false;
     903           0 :                 r2->tnonil = true;
     904             :         }
     905           0 :         if (r3) {
     906           0 :                 m3p = (bit *) Tloc(r3, 0);
     907           0 :                 r3->tnil = false;
     908           0 :                 r3->tnonil = true;
     909             :         }
     910           0 :         if (complex_cand(l)) {
     911           0 :                 ltsorted = l->tsorted;
     912           0 :                 ltrevsorted = l->trevsorted;
     913           0 :                 ltkey = l->tkey;
     914           0 :                 TIMEOUT_LOOP(lci->ncand, qry_ctx) {
     915           0 :                         oid c = canditer_next(lci);
     916             : 
     917           0 :                         o = BUNtoid(l, c - l->hseqbase);
     918           0 :                         *o1p++ = c;
     919           0 :                         if (r2) {
     920           0 :                                 if (o >= lo && o < hi) {
     921           0 :                                         *o2p++ = o - r->tseqbase + r->hseqbase;
     922             :                                 } else {
     923           0 :                                         *o2p++ = oid_nil;
     924           0 :                                         r2->tnil = true;
     925           0 :                                         r2->tnonil = false;
     926             :                                 }
     927             :                         }
     928           0 :                         if (r3) {
     929           0 :                                 if (is_oid_nil(o)) {
     930           0 :                                         *m3p++ = bit_nil;
     931           0 :                                         r3->tnil = true;
     932           0 :                                         r3->tnonil = false;
     933             :                                 } else {
     934           0 :                                         *m3p++ = (o >= lo && o < hi);
     935             :                                 }
     936             :                         }
     937             :                 }
     938           0 :                 TIMEOUT_CHECK(qry_ctx,
     939             :                               GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     940             :         } else {
     941           0 :                 BATiter li = bat_iterator(l);
     942           0 :                 const oid *lvals = (const oid *) li.base;
     943           0 :                 ltsorted = li.sorted;
     944           0 :                 ltrevsorted = li.revsorted;
     945           0 :                 ltkey = li.key;
     946           0 :                 TIMEOUT_LOOP(lci->ncand, qry_ctx) {
     947           0 :                         oid c = canditer_next(lci);
     948             : 
     949           0 :                         o = lvals[c - l->hseqbase];
     950           0 :                         *o1p++ = c;
     951           0 :                         if (r2) {
     952           0 :                                 if (o >= lo && o < hi) {
     953           0 :                                         *o2p++ = o - r->tseqbase + r->hseqbase;
     954             :                                 } else {
     955           0 :                                         *o2p++ = oid_nil;
     956           0 :                                         r2->tnil = true;
     957           0 :                                         r2->tnonil = false;
     958             :                                 }
     959             :                         }
     960           0 :                         if (r3) {
     961           0 :                                 if (is_oid_nil(o)) {
     962           0 :                                         *m3p++ = bit_nil;
     963           0 :                                         r3->tnil = true;
     964           0 :                                         r3->tnonil = false;
     965             :                                 } else {
     966           0 :                                         *m3p++ = (o >= lo && o < hi);
     967             :                                 }
     968             :                         }
     969             :                 }
     970           0 :                 bat_iterator_end(&li);
     971           0 :                 TIMEOUT_CHECK(qry_ctx,
     972             :                               GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
     973             :         }
     974           0 :         r1->tsorted = true;
     975           0 :         r1->trevsorted = BATcount(r1) <= 1;
     976           0 :         r1->tkey = true;
     977           0 :         r1->tseqbase = oid_nil;
     978           0 :         r1->tnil = false;
     979           0 :         r1->tnonil = true;
     980           0 :         BATsetcount(r1, lci->ncand);
     981           0 :         if (r2) {
     982           0 :                 BATsetcount(r2, lci->ncand);
     983           0 :                 r2->tsorted = ltsorted || BATcount(r2) <= 1;
     984           0 :                 r2->trevsorted = ltrevsorted || BATcount(r2) <= 1;
     985           0 :                 r2->tkey = ltkey || BATcount(r2) <= 1;
     986           0 :                 r2->tseqbase = oid_nil;
     987             :         }
     988           0 :         if (r3) {
     989           0 :                 BATsetcount(r3, lci->ncand);
     990             :         }
     991             : 
     992           0 :   doreturn:
     993           0 :         if (r1->tkey)
     994           0 :                 virtualize(r1);
     995           0 :         if (r2 && r2->tkey && r2->tsorted)
     996           0 :                 virtualize(r2);
     997           0 :   doreturn2:
     998       25165 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
     999             :                   "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    1000             :                   "sr=" ALGOOPTBATFMT ","
    1001             :                   "nil_on_miss=%s,only_misses=%s;%s %s "
    1002             :                   "-> " ALGOBATFMT "," ALGOOPTBATFMT "," ALGOOPTBATFMT
    1003             :                   " (" LLFMT "usec)\n",
    1004             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    1005             :                   ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
    1006             :                   nil_on_miss ? "true" : "false",
    1007             :                   only_misses ? "true" : "false",
    1008             :                   swapped ? " swapped" : "", reason,
    1009             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2), ALGOOPTBATPAR(r3),
    1010             :                   GDKusec() - t0);
    1011             : 
    1012             :         return GDK_SUCCEED;
    1013             : 
    1014           0 :   bailout:
    1015           0 :         BBPreclaim(r1);
    1016           0 :         BBPreclaim(r2);
    1017             :         return GDK_FAIL;
    1018             : }
    1019             : 
    1020             : /* Implementation of mergejoin (see below) for the special case that
    1021             :  * the values are of type int, and some more conditions are met. */
    1022             : static gdk_return
    1023        7889 : mergejoin_int(BAT **r1p, BAT **r2p, BAT *l, BAT *r,
    1024             :               bool nil_matches, BUN estimate, lng t0, bool swapped,
    1025             :               const char *reason)
    1026             : {
    1027        7889 :         BAT *r1, *r2;
    1028        7889 :         BUN lstart, lend, lcnt;
    1029        7889 :         BUN rstart, rend;
    1030        7889 :         BUN lscan, rscan;       /* opportunistic scan window */
    1031        7889 :         BUN maxsize;
    1032        7889 :         const int *lvals, *rvals;
    1033        7889 :         int v;
    1034        7889 :         BUN nl, nr;
    1035        7889 :         oid lv;
    1036        7889 :         BUN i;
    1037        7889 :         BATiter li = bat_iterator(l);
    1038        7916 :         BATiter ri = bat_iterator(r);
    1039             : 
    1040       23748 :         assert(ATOMtype(li.type) == ATOMtype(ri.type));
    1041        7916 :         assert(ri.sorted || ri.revsorted);
    1042             : 
    1043        7916 :         MT_thread_setalgorithm(__func__);
    1044        7917 :         lstart = rstart = 0;
    1045        7917 :         lend = BATcount(l);
    1046        7917 :         lcnt = lend - lstart;
    1047        7917 :         rend = BATcount(r);
    1048        7917 :         lvals = (const int *) li.base;
    1049        7917 :         rvals = (const int *) ri.base;
    1050        7917 :         size_t counter = 0;
    1051        7917 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1052             : 
    1053             :         /* basic properties will be adjusted if necessary later on,
    1054             :          * they were initially set by joininitresults() */
    1055             : 
    1056        7914 :         if (lend == 0 || rend == 0) {
    1057             :                 /* there are no matches */
    1058           0 :                 bat_iterator_end(&li);
    1059           0 :                 bat_iterator_end(&ri);
    1060           0 :                 return nomatch(r1p, r2p, NULL, l, r,
    1061           0 :                                &(struct canditer) {.tpe = cand_dense, .ncand = lcnt,},
    1062             :                                0, false, false, __func__, t0);
    1063             :         }
    1064             : 
    1065        7860 :         if ((maxsize = joininitresults(r1p, r2p, NULL, BATcount(l), BATcount(r),
    1066        7914 :                                        li.key, ri.key, false, false,
    1067             :                                        false, false, estimate)) == BUN_NONE) {
    1068           0 :                 bat_iterator_end(&li);
    1069           0 :                 bat_iterator_end(&ri);
    1070           0 :                 return GDK_FAIL;
    1071             :         }
    1072        7860 :         r1 = *r1p;
    1073        7860 :         r2 = r2p ? *r2p : NULL;
    1074             : 
    1075             :         /* determine opportunistic scan window for l and r */
    1076       44885 :         for (nl = lend - lstart, lscan = 4; nl > 0; lscan++)
    1077       37025 :                 nl >>= 1;
    1078       59614 :         for (nr = rend - rstart, rscan = 4; nr > 0; rscan++)
    1079       51754 :                 nr >>= 1;
    1080             : 
    1081        7860 :         if (!nil_matches) {
    1082             :                 /* skip over nils at the start of the columns */
    1083        4848 :                 if (lscan < lend - lstart && is_int_nil(lvals[lstart + lscan])) {
    1084           0 :                         lstart = binsearch_int(NULL, 0, lvals, lstart + lscan,
    1085             :                                                lend - 1, int_nil, 1, 1);
    1086             :                 } else {
    1087        4848 :                         while (is_int_nil(lvals[lstart]))
    1088           0 :                                 lstart++;
    1089             :                 }
    1090        4848 :                 if (rscan < rend - rstart && is_int_nil(rvals[rstart + rscan])) {
    1091           0 :                         rstart = binsearch_int(NULL, 0, rvals, rstart + rscan,
    1092             :                                                rend - 1, int_nil, 1, 1);
    1093             :                 } else {
    1094        4848 :                         while (is_int_nil(rvals[rstart]))
    1095           0 :                                 rstart++;
    1096             :                 }
    1097             :         }
    1098             :         /* from here on we don't have to worry about nil values */
    1099             : 
    1100      382937 :         while (lstart < lend && rstart < rend) {
    1101      377241 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    1102             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    1103             : 
    1104      377241 :                 v = rvals[rstart];
    1105             : 
    1106      377241 :                 if (lscan < lend - lstart && lvals[lstart + lscan] < v) {
    1107        1646 :                         lstart = binsearch_int(NULL, 0, lvals, lstart + lscan,
    1108             :                                                lend - 1, v, 1, 0);
    1109             :                 } else {
    1110             :                         /* scan l for v */
    1111      381609 :                         while (lstart < lend && lvals[lstart] < v)
    1112        6014 :                                 lstart++;
    1113             :                 }
    1114      374996 :                 if (lstart >= lend) {
    1115             :                         /* nothing found */
    1116             :                         break;
    1117             :                 }
    1118             : 
    1119             :                 /* Here we determine the next value in l that we are
    1120             :                  * going to try to match in r.  We will also count the
    1121             :                  * number of occurrences in l of that value.
    1122             :                  * Afterwards, v points to the value and nl is the
    1123             :                  * number of times it occurs.  Also, lstart will
    1124             :                  * point to the next value to be considered (ready for
    1125             :                  * the next iteration).
    1126             :                  * If there are many equal values in l (more than
    1127             :                  * lscan), we will use binary search to find the end
    1128             :                  * of the sequence.  Obviously, we can do this only if
    1129             :                  * l is actually sorted (lscan > 0). */
    1130      374337 :                 nl = 1;         /* we'll match (at least) one in l */
    1131      374337 :                 nr = 0;         /* maybe we won't match anything in r */
    1132      374337 :                 v = lvals[lstart];
    1133      374337 :                 if (li.key) {
    1134             :                         /* if l is key, there is a single value */
    1135       54035 :                         lstart++;
    1136      320302 :                 } else if (lscan < lend - lstart &&
    1137      314905 :                            v == lvals[lstart + lscan]) {
    1138             :                         /* lots of equal values: use binary search to
    1139             :                          * find end */
    1140       25514 :                         nl = binsearch_int(NULL, 0, lvals, lstart + lscan,
    1141             :                                            lend - 1, v, 1, 1);
    1142       25535 :                         nl -= lstart;
    1143       25535 :                         lstart += nl;
    1144             :                 } else {
    1145             :                         /* just scan */
    1146     1405578 :                         while (++lstart < lend && v == lvals[lstart])
    1147     1110790 :                                 nl++;
    1148             :                 }
    1149             :                 /* lstart points one beyond the value we're
    1150             :                  * going to match: ready for the next iteration. */
    1151             : 
    1152             :                 /* First we find the first value in r that is at
    1153             :                  * least as large as v, then we find the first
    1154             :                  * value in r that is larger than v.  The difference
    1155             :                  * is the number of values equal to v and is stored in
    1156             :                  * nr.
    1157             :                  * We will use binary search on r to find both ends of
    1158             :                  * the sequence of values that are equal to v in case
    1159             :                  * the position is "too far" (more than rscan
    1160             :                  * away). */
    1161             : 
    1162             :                 /* first find the location of the first value in r
    1163             :                  * that is >= v, then find the location of the first
    1164             :                  * value in r that is > v; the difference is the
    1165             :                  * number of values equal to v */
    1166             : 
    1167             :                 /* look ahead a little (rscan) in r to see whether
    1168             :                  * we're better off doing a binary search */
    1169      374358 :                 if (rscan < rend - rstart && rvals[rstart + rscan] < v) {
    1170             :                         /* value too far away in r: use binary
    1171             :                          * search */
    1172       19104 :                         rstart = binsearch_int(NULL, 0, rvals, rstart + rscan,
    1173             :                                                rend - 1, v, 1, 0);
    1174             :                 } else {
    1175             :                         /* scan r for v */
    1176      381632 :                         while (rstart < rend && rvals[rstart] < v)
    1177       26378 :                                 rstart++;
    1178             :                 }
    1179      376239 :                 if (rstart == rend) {
    1180             :                         /* nothing found */
    1181             :                         break;
    1182             :                 }
    1183             : 
    1184             :                 /* now find the end of the sequence of equal values v */
    1185             : 
    1186             :                 /* if r is key, there is zero or one match, otherwise
    1187             :                  * look ahead a little (rscan) in r to see whether
    1188             :                  * we're better off doing a binary search */
    1189      374719 :                 if (ri.key) {
    1190      177567 :                         if (rstart < rend && v == rvals[rstart]) {
    1191      177251 :                                 nr = 1;
    1192      177251 :                                 rstart++;
    1193             :                         }
    1194      197152 :                 } else if (rscan < rend - rstart &&
    1195      196313 :                            v == rvals[rstart + rscan]) {
    1196             :                         /* range too large: use binary search */
    1197       69040 :                         nr = binsearch_int(NULL, 0, rvals, rstart + rscan,
    1198             :                                            rend - 1, v, 1, 1);
    1199       70060 :                         nr -= rstart;
    1200       70060 :                         rstart += nr;
    1201             :                 } else {
    1202             :                         /* scan r for end of range */
    1203     1042998 :                         while (rstart < rend && v == rvals[rstart]) {
    1204      914886 :                                 nr++;
    1205      914886 :                                 rstart++;
    1206             :                         }
    1207             :                 }
    1208             :                 /* rstart points to first value > v or end of
    1209             :                  * r, and nr is the number of values in r that
    1210             :                  * are equal to v */
    1211      375423 :                 if (nr == 0) {
    1212             :                         /* no entries in r found */
    1213         349 :                         continue;
    1214             :                 }
    1215             :                 /* make space: nl values in l match nr values in r, so
    1216             :                  * we need to add nl * nr values in the results */
    1217      375390 :                 if (maybeextend(r1, r2, NULL, nl * nr, lstart, lend, maxsize) != GDK_SUCCEED)
    1218           0 :                         goto bailout;
    1219             : 
    1220             :                 /* maintain properties */
    1221      374728 :                 if (nl > 1) {
    1222             :                         /* value occurs multiple times in l, so entry
    1223             :                          * in r will be repeated multiple times: hence
    1224             :                          * r2 is not key and not dense */
    1225      255239 :                         if (r2) {
    1226      220194 :                                 r2->tkey = false;
    1227      220194 :                                 r2->tseqbase = oid_nil;
    1228             :                         }
    1229             :                         /* multiple different values will be inserted
    1230             :                          * in r1 (always in order), so not reverse
    1231             :                          * ordered anymore */
    1232      255239 :                         r1->trevsorted = false;
    1233             :                 }
    1234      374728 :                 if (nr > 1) {
    1235             :                         /* value occurs multiple times in r, so entry
    1236             :                          * in l will be repeated multiple times: hence
    1237             :                          * r1 is not key and not dense */
    1238      158657 :                         r1->tkey = false;
    1239      158657 :                         r1->tseqbase = oid_nil;
    1240             :                         /* multiple different values will be inserted
    1241             :                          * in r2 (in order), so not reverse ordered
    1242             :                          * anymore */
    1243      158657 :                         if (r2) {
    1244      108236 :                                 r2->trevsorted = false;
    1245      108236 :                                 if (nl > 1) {
    1246             :                                         /* multiple values in l match
    1247             :                                          * multiple values in r, so an
    1248             :                                          * ordered sequence will be
    1249             :                                          * inserted multiple times in
    1250             :                                          * r2, so r2 is not ordered
    1251             :                                          * anymore */
    1252       83075 :                                         r2->tsorted = false;
    1253             :                                 }
    1254             :                         }
    1255             :                 }
    1256      374728 :                 if (BATcount(r1) > 0) {
    1257             :                         /* a new, higher value will be inserted into
    1258             :                          * r1, so r1 is not reverse ordered anymore */
    1259      369175 :                         r1->trevsorted = false;
    1260             :                         /* a new higher value will be added to r2 */
    1261      369175 :                         if (r2) {
    1262      303178 :                                 r2->trevsorted = false;
    1263             :                         }
    1264      369175 :                         if (BATtdense(r1) &&
    1265      205725 :                             ((oid *) r1->theap->base)[r1->batCount - 1] + 1 != l->hseqbase + lstart - nl) {
    1266          68 :                                 r1->tseqbase = oid_nil;
    1267             :                         }
    1268             :                 }
    1269             : 
    1270      374728 :                 if (r2 &&
    1271      307677 :                     BATcount(r2) > 0 &&
    1272      302085 :                     BATtdense(r2) &&
    1273       72645 :                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != r->hseqbase + rstart - nr) {
    1274         551 :                         r2->tseqbase = oid_nil;
    1275             :                 }
    1276             : 
    1277             :                 /* insert values */
    1278      374728 :                 lv = l->hseqbase + lstart - nl;
    1279    15819282 :                 for (i = 0; i < nl; i++) {
    1280             :                         BUN j;
    1281             : 
    1282   110863761 :                         for (j = 0; j < nr; j++) {
    1283    95419207 :                                 APPEND(r1, lv);
    1284             :                         }
    1285    15444554 :                         if (r2) {
    1286    15274230 :                                 oid rv = r->hseqbase + rstart - nr;
    1287             : 
    1288   103818262 :                                 for (j = 0; j < nr; j++) {
    1289    88544032 :                                         APPEND(r2, rv);
    1290    88544032 :                                         rv++;
    1291             :                                 }
    1292             :                         }
    1293    15444554 :                         lv++;
    1294             :                 }
    1295             :         }
    1296             :         /* also set other bits of heap to correct value to indicate size */
    1297        7875 :         BATsetcount(r1, BATcount(r1));
    1298        7850 :         if (r2) {
    1299        6018 :                 BATsetcount(r2, BATcount(r2));
    1300        6016 :                 assert(BATcount(r1) == BATcount(r2));
    1301             :         }
    1302        7848 :         if (BATcount(r1) > 0) {
    1303        6199 :                 if (BATtdense(r1))
    1304        4871 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    1305        6199 :                 if (r2 && BATtdense(r2))
    1306        3663 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    1307             :         } else {
    1308        1649 :                 r1->tseqbase = 0;
    1309        1649 :                 if (r2) {
    1310         836 :                         r2->tseqbase = 0;
    1311             :                 }
    1312             :         }
    1313        7848 :         bat_iterator_end(&li);
    1314        7911 :         bat_iterator_end(&ri);
    1315        7873 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT ","
    1316             :                   "nil_matches=%s;%s %s "
    1317             :                   "-> " ALGOBATFMT "," ALGOOPTBATFMT " (" LLFMT "usec)\n",
    1318             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    1319             :                   nil_matches ? "true" : "false",
    1320             :                   swapped ? " swapped" : "", reason,
    1321             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    1322             :                   GDKusec() - t0);
    1323             : 
    1324             :         return GDK_SUCCEED;
    1325             : 
    1326           0 :   bailout:
    1327           0 :         bat_iterator_end(&li);
    1328           0 :         bat_iterator_end(&ri);
    1329           0 :         BBPreclaim(r1);
    1330           0 :         BBPreclaim(r2);
    1331             :         return GDK_FAIL;
    1332             : }
    1333             : 
    1334             : /* Implementation of mergejoin (see below) for the special case that
    1335             :  * the values are of type lng, and some more conditions are met. */
    1336             : static gdk_return
    1337         219 : mergejoin_lng(BAT **r1p, BAT **r2p, BAT *l, BAT *r,
    1338             :               bool nil_matches, BUN estimate, lng t0, bool swapped,
    1339             :               const char *reason)
    1340             : {
    1341         219 :         BAT *r1, *r2;
    1342         219 :         BUN lstart, lend, lcnt;
    1343         219 :         BUN rstart, rend;
    1344         219 :         BUN lscan, rscan;       /* opportunistic scan window */
    1345         219 :         BUN maxsize;
    1346         219 :         const lng *lvals, *rvals;
    1347         219 :         lng v;
    1348         219 :         BUN nl, nr;
    1349         219 :         oid lv;
    1350         219 :         BUN i;
    1351         219 :         BATiter li = bat_iterator(l);
    1352         220 :         BATiter ri = bat_iterator(r);
    1353             : 
    1354         660 :         assert(ATOMtype(li.type) == ATOMtype(ri.type));
    1355         220 :         assert(ri.sorted || ri.revsorted);
    1356             : 
    1357         220 :         MT_thread_setalgorithm(__func__);
    1358         220 :         lstart = rstart = 0;
    1359         220 :         lend = BATcount(l);
    1360         220 :         lcnt = lend - lstart;
    1361         220 :         rend = BATcount(r);
    1362         220 :         lvals = (const lng *) li.base;
    1363         220 :         rvals = (const lng *) ri.base;
    1364         220 :         size_t counter = 0;
    1365         220 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1366             : 
    1367             :         /* basic properties will be adjusted if necessary later on,
    1368             :          * they were initially set by joininitresults() */
    1369             : 
    1370         220 :         if (lend == 0 || rend == 0) {
    1371             :                 /* there are no matches */
    1372           0 :                 bat_iterator_end(&li);
    1373           0 :                 bat_iterator_end(&ri);
    1374           0 :                 return nomatch(r1p, r2p, NULL, l, r,
    1375           0 :                                &(struct canditer) {.tpe = cand_dense, .ncand = lcnt,},
    1376             :                                0, false, false, __func__, t0);
    1377             :         }
    1378             : 
    1379         219 :         if ((maxsize = joininitresults(r1p, r2p, NULL, BATcount(l), BATcount(r),
    1380         220 :                                        li.key, ri.key, false, false,
    1381             :                                        false, false, estimate)) == BUN_NONE) {
    1382           0 :                 bat_iterator_end(&li);
    1383           0 :                 bat_iterator_end(&ri);
    1384           0 :                 return GDK_FAIL;
    1385             :         }
    1386         219 :         r1 = *r1p;
    1387         219 :         r2 = r2p ? *r2p : NULL;
    1388             : 
    1389             :         /* determine opportunistic scan window for l and r */
    1390        1644 :         for (nl = lend - lstart, lscan = 4; nl > 0; lscan++)
    1391        1425 :                 nl >>= 1;
    1392        1629 :         for (nr = rend - rstart, rscan = 4; nr > 0; rscan++)
    1393        1410 :                 nr >>= 1;
    1394             : 
    1395         219 :         if (!nil_matches) {
    1396             :                 /* skip over nils at the start of the columns */
    1397         141 :                 if (lscan < lend - lstart && is_lng_nil(lvals[lstart + lscan])) {
    1398           0 :                         lstart = binsearch_lng(NULL, 0, lvals, lstart + lscan,
    1399             :                                                lend - 1, lng_nil, 1, 1);
    1400             :                 } else {
    1401         141 :                         while (is_lng_nil(lvals[lstart]))
    1402           0 :                                 lstart++;
    1403             :                 }
    1404         141 :                 if (rscan < rend - rstart && is_lng_nil(rvals[rstart + rscan])) {
    1405           0 :                         rstart = binsearch_lng(NULL, 0, rvals, rstart + rscan,
    1406             :                                                rend - 1, lng_nil, 1, 1);
    1407             :                 } else {
    1408         141 :                         while (is_lng_nil(rvals[rstart]))
    1409           0 :                                 rstart++;
    1410             :                 }
    1411             :         }
    1412             :         /* from here on we don't have to worry about nil values */
    1413             : 
    1414      413920 :         while (lstart < lend && rstart < rend) {
    1415      413800 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    1416             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    1417      413799 :                 v = rvals[rstart];
    1418             : 
    1419      413799 :                 if (lscan < lend - lstart && lvals[lstart + lscan] < v) {
    1420         959 :                         lstart = binsearch_lng(NULL, 0, lvals, lstart + lscan,
    1421             :                                                lend - 1, v, 1, 0);
    1422             :                 } else {
    1423             :                         /* scan l for v */
    1424      490620 :                         while (lstart < lend && lvals[lstart] < v)
    1425       77780 :                                 lstart++;
    1426             :                 }
    1427      413818 :                 if (lstart >= lend) {
    1428             :                         /* nothing found */
    1429             :                         break;
    1430             :                 }
    1431             : 
    1432             :                 /* Here we determine the next value in l that we are
    1433             :                  * going to try to match in r.  We will also count the
    1434             :                  * number of occurrences in l of that value.
    1435             :                  * Afterwards, v points to the value and nl is the
    1436             :                  * number of times it occurs.  Also, lstart will
    1437             :                  * point to the next value to be considered (ready for
    1438             :                  * the next iteration).
    1439             :                  * If there are many equal values in l (more than
    1440             :                  * lscan), we will use binary search to find the end
    1441             :                  * of the sequence.  Obviously, we can do this only if
    1442             :                  * l is actually sorted (lscan > 0). */
    1443      413741 :                 nl = 1;         /* we'll match (at least) one in l */
    1444      413741 :                 nr = 0;         /* maybe we won't match anything in r */
    1445      413741 :                 v = lvals[lstart];
    1446      413741 :                 if (li.key) {
    1447             :                         /* if l is key, there is a single value */
    1448      369975 :                         lstart++;
    1449       43766 :                 } else if (lscan < lend - lstart &&
    1450       43662 :                            v == lvals[lstart + lscan]) {
    1451             :                         /* lots of equal values: use binary search to
    1452             :                          * find end */
    1453         391 :                         nl = binsearch_lng(NULL, 0, lvals, lstart + lscan,
    1454             :                                            lend - 1, v, 1, 1);
    1455         391 :                         nl -= lstart;
    1456         391 :                         lstart += nl;
    1457             :                 } else {
    1458             :                         /* just scan */
    1459       65990 :                         while (++lstart < lend && v == lvals[lstart])
    1460       22615 :                                 nl++;
    1461             :                 }
    1462             :                 /* lstart points one beyond the value we're
    1463             :                  * going to match: ready for the next iteration. */
    1464             : 
    1465             :                 /* First we find the first value in r that is at
    1466             :                  * least as large as v, then we find the first
    1467             :                  * value in r that is larger than v.  The difference
    1468             :                  * is the number of values equal to v and is stored in
    1469             :                  * nr.
    1470             :                  * We will use binary search on r to find both ends of
    1471             :                  * the sequence of values that are equal to v in case
    1472             :                  * the position is "too far" (more than rscan
    1473             :                  * away). */
    1474             : 
    1475             :                 /* first find the location of the first value in r
    1476             :                  * that is >= v, then find the location of the first
    1477             :                  * value in r that is > v; the difference is the
    1478             :                  * number of values equal to v */
    1479             : 
    1480             :                 /* look ahead a little (rscan) in r to see whether
    1481             :                  * we're better off doing a binary search */
    1482      413741 :                 if (rscan < rend - rstart && rvals[rstart + rscan] < v) {
    1483             :                         /* value too far away in r: use binary
    1484             :                          * search */
    1485        2244 :                         rstart = binsearch_lng(NULL, 0, rvals, rstart + rscan,
    1486             :                                                rend - 1, v, 1, 0);
    1487             :                 } else {
    1488             :                         /* scan r for v */
    1489     1486539 :                         while (rstart < rend && rvals[rstart] < v)
    1490     1075042 :                                 rstart++;
    1491             :                 }
    1492      413725 :                 if (rstart == rend) {
    1493             :                         /* nothing found */
    1494             :                         break;
    1495             :                 }
    1496             : 
    1497             :                 /* now find the end of the sequence of equal values v */
    1498             : 
    1499             :                 /* if r is key, there is zero or one match, otherwise
    1500             :                  * look ahead a little (rscan) in r to see whether
    1501             :                  * we're better off doing a binary search */
    1502      413703 :                 if (ri.key) {
    1503      376048 :                         if (rstart < rend && v == rvals[rstart]) {
    1504       82126 :                                 nr = 1;
    1505       82126 :                                 rstart++;
    1506             :                         }
    1507       37655 :                 } else if (rscan < rend - rstart &&
    1508       37617 :                            v == rvals[rstart + rscan]) {
    1509             :                         /* range too large: use binary search */
    1510           0 :                         nr = binsearch_lng(NULL, 0, rvals, rstart + rscan,
    1511             :                                            rend - 1, v, 1, 1);
    1512           0 :                         nr -= rstart;
    1513           0 :                         rstart += nr;
    1514             :                 } else {
    1515             :                         /* scan r for end of range */
    1516       90643 :                         while (rstart < rend && v == rvals[rstart]) {
    1517       52988 :                                 nr++;
    1518       52988 :                                 rstart++;
    1519             :                         }
    1520             :                 }
    1521             :                 /* rstart points to first value > v or end of
    1522             :                  * r, and nr is the number of values in r that
    1523             :                  * are equal to v */
    1524      119781 :                 if (nr == 0) {
    1525             :                         /* no entries in r found */
    1526      293589 :                         continue;
    1527             :                 }
    1528             :                 /* make space: nl values in l match nr values in r, so
    1529             :                  * we need to add nl * nr values in the results */
    1530      120114 :                 if (maybeextend(r1, r2, NULL, nl * nr, lstart, lend, maxsize) != GDK_SUCCEED)
    1531           0 :                         goto bailout;
    1532             : 
    1533             :                 /* maintain properties */
    1534      120112 :                 if (nl > 1) {
    1535             :                         /* value occurs multiple times in l, so entry
    1536             :                          * in r will be repeated multiple times: hence
    1537             :                          * r2 is not key and not dense */
    1538        6772 :                         if (r2) {
    1539        1773 :                                 r2->tkey = false;
    1540        1773 :                                 r2->tseqbase = oid_nil;
    1541             :                         }
    1542             :                         /* multiple different values will be inserted
    1543             :                          * in r1 (always in order), so not reverse
    1544             :                          * ordered anymore */
    1545        6772 :                         r1->trevsorted = false;
    1546             :                 }
    1547      120112 :                 if (nr > 1) {
    1548             :                         /* value occurs multiple times in r, so entry
    1549             :                          * in l will be repeated multiple times: hence
    1550             :                          * r1 is not key and not dense */
    1551        4467 :                         r1->tkey = false;
    1552        4467 :                         r1->tseqbase = oid_nil;
    1553             :                         /* multiple different values will be inserted
    1554             :                          * in r2 (in order), so not reverse ordered
    1555             :                          * anymore */
    1556        4467 :                         if (r2) {
    1557        4467 :                                 r2->trevsorted = false;
    1558        4467 :                                 if (nl > 1) {
    1559             :                                         /* multiple values in l match
    1560             :                                          * multiple values in r, so an
    1561             :                                          * ordered sequence will be
    1562             :                                          * inserted multiple times in
    1563             :                                          * r2, so r2 is not ordered
    1564             :                                          * anymore */
    1565          51 :                                         r2->tsorted = false;
    1566             :                                 }
    1567             :                         }
    1568             :                 }
    1569      120112 :                 if (BATcount(r1) > 0) {
    1570             :                         /* a new, higher value will be inserted into
    1571             :                          * r1, so r1 is not reverse ordered anymore */
    1572      119545 :                         r1->trevsorted = false;
    1573             :                         /* a new higher value will be added to r2 */
    1574      119545 :                         if (r2) {
    1575      112842 :                                 r2->trevsorted = false;
    1576             :                         }
    1577      119545 :                         if (BATtdense(r1) &&
    1578       52763 :                             ((oid *) r1->theap->base)[r1->batCount - 1] + 1 != l->hseqbase + lstart - nl) {
    1579          68 :                                 r1->tseqbase = oid_nil;
    1580             :                         }
    1581             :                 }
    1582             : 
    1583      120112 :                 if (r2 &&
    1584      113396 :                     BATcount(r2) > 0 &&
    1585      112877 :                     BATtdense(r2) &&
    1586       51605 :                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != r->hseqbase + rstart - nr) {
    1587          36 :                         r2->tseqbase = oid_nil;
    1588             :                 }
    1589             : 
    1590             :                 /* insert values */
    1591      120112 :                 lv = l->hseqbase + lstart - nl;
    1592      269505 :                 for (i = 0; i < nl; i++) {
    1593             :                         BUN j;
    1594             : 
    1595      313213 :                         for (j = 0; j < nr; j++) {
    1596      163820 :                                 APPEND(r1, lv);
    1597             :                         }
    1598      149393 :                         if (r2) {
    1599      131407 :                                 oid rv = r->hseqbase + rstart - nr;
    1600             : 
    1601      277187 :                                 for (j = 0; j < nr; j++) {
    1602      145780 :                                         APPEND(r2, rv);
    1603      145780 :                                         rv++;
    1604             :                                 }
    1605             :                         }
    1606      149393 :                         lv++;
    1607             :                 }
    1608             :         }
    1609             :         /* also set other bits of heap to correct value to indicate size */
    1610         219 :         BATsetcount(r1, BATcount(r1));
    1611         219 :         if (r2) {
    1612         193 :                 BATsetcount(r2, BATcount(r2));
    1613         193 :                 assert(BATcount(r1) == BATcount(r2));
    1614             :         }
    1615         219 :         if (BATcount(r1) > 0) {
    1616         194 :                 if (BATtdense(r1))
    1617         107 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    1618         194 :                 if (r2 && BATtdense(r2))
    1619         101 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    1620             :         } else {
    1621          25 :                 r1->tseqbase = 0;
    1622          25 :                 if (r2) {
    1623          11 :                         r2->tseqbase = 0;
    1624             :                 }
    1625             :         }
    1626         219 :         bat_iterator_end(&li);
    1627         219 :         bat_iterator_end(&ri);
    1628         219 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT ","
    1629             :                   "nil_matches=%s;%s %s "
    1630             :                   "-> " ALGOBATFMT "," ALGOOPTBATFMT " (" LLFMT "usec)\n",
    1631             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    1632             :                   nil_matches ? "true" : "false",
    1633             :                   swapped ? " swapped" : "", reason,
    1634             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    1635             :                   GDKusec() - t0);
    1636             : 
    1637             :         return GDK_SUCCEED;
    1638             : 
    1639           1 :   bailout:
    1640           1 :         bat_iterator_end(&li);
    1641           1 :         bat_iterator_end(&ri);
    1642           1 :         BBPreclaim(r1);
    1643           1 :         BBPreclaim(r2);
    1644             :         return GDK_FAIL;
    1645             : }
    1646             : 
    1647             : /* Implementation of mergejoin (see below) for the special case that
    1648             :  * the values are of type oid, and the right-hand side is a candidate
    1649             :  * list with exception, and some more conditions are met. */
    1650             : static gdk_return
    1651           0 : mergejoin_cand(BAT **r1p, BAT **r2p, BAT *l, BAT *r,
    1652             :                bool nil_matches, BUN estimate, lng t0, bool swapped,
    1653             :                const char *reason)
    1654             : {
    1655             : /* the comments in this function have not been checked after making a
    1656             :  * copy of mergejoin below and adapting it to a mask right-hand side */
    1657           0 :         BAT *r1, *r2;
    1658           0 :         BUN lstart, lend, lcnt;
    1659           0 :         struct canditer lci, rci;
    1660           0 :         BUN lscan;              /* opportunistic scan window */
    1661           0 :         BUN maxsize;
    1662           0 :         const oid *lvals;
    1663           0 :         oid v;
    1664           0 :         BUN nl, nr;
    1665           0 :         oid lv;
    1666           0 :         BUN i;
    1667           0 :         BATiter li = bat_iterator(l);
    1668           0 :         BATiter ri = bat_iterator(r);
    1669             : 
    1670           0 :         assert(ATOMtype(li.type) == ATOMtype(ri.type));
    1671             : 
    1672           0 :         MT_thread_setalgorithm(__func__);
    1673           0 :         lstart = 0;
    1674           0 :         lend = BATcount(l);
    1675           0 :         lcnt = lend - lstart;
    1676           0 :         if (li.type == TYPE_void) {
    1677           0 :                 assert(!is_oid_nil(l->tseqbase));
    1678           0 :                 canditer_init(&lci, NULL, l);
    1679           0 :                 lcnt = lci.ncand;
    1680           0 :                 lvals = NULL;
    1681             :         } else {
    1682           0 :                 lci = (struct canditer) {.tpe = cand_dense}; /* not used */
    1683           0 :                 lvals = (const oid *) li.base;
    1684           0 :                 assert(lvals != NULL);
    1685             :         }
    1686             : 
    1687           0 :         assert(complex_cand(r));
    1688           0 :         canditer_init(&rci, NULL, r);
    1689           0 :         size_t counter = 0;
    1690           0 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1691             : 
    1692             :         /* basic properties will be adjusted if necessary later on,
    1693             :          * they were initially set by joininitresults() */
    1694             : 
    1695           0 :         if (lend == 0 || rci.ncand == 0) {
    1696             :                 /* there are no matches */
    1697           0 :                 bat_iterator_end(&li);
    1698           0 :                 bat_iterator_end(&ri);
    1699           0 :                 return nomatch(r1p, r2p, NULL, l, r,
    1700           0 :                                &(struct canditer) {.tpe = cand_dense, .ncand = lcnt,},
    1701             :                                0, false, false, __func__, t0);
    1702             :         }
    1703             : 
    1704           0 :         if ((maxsize = joininitresults(r1p, r2p, NULL, BATcount(l), BATcount(r),
    1705           0 :                                        li.key, ri.key, false, false,
    1706             :                                        false, false, estimate)) == BUN_NONE) {
    1707           0 :                 bat_iterator_end(&li);
    1708           0 :                 bat_iterator_end(&ri);
    1709           0 :                 return GDK_FAIL;
    1710             :         }
    1711           0 :         r1 = *r1p;
    1712           0 :         r2 = r2p ? *r2p : NULL;
    1713             : 
    1714             :         /* determine opportunistic scan window for l and r */
    1715           0 :         for (nl = lend - lstart, lscan = 4; nl > 0; lscan++)
    1716           0 :                 nl >>= 1;
    1717             : 
    1718           0 :         if (!nil_matches) {
    1719             :                 /* skip over nils at the start of the columns */
    1720           0 :                 if (lscan < lend - lstart && lvals && is_oid_nil(lvals[lstart + lscan])) {
    1721           0 :                         lstart = binsearch_oid(NULL, 0, lvals, lstart + lscan,
    1722             :                                                lend - 1, oid_nil, 1, 1);
    1723           0 :                 } else if (lvals) {
    1724           0 :                         while (is_oid_nil(lvals[lstart]))
    1725           0 :                                 lstart++;
    1726             :                 } /* else l is candidate list: no nils */
    1727             :         }
    1728             :         /* from here on we don't have to worry about nil values */
    1729             : 
    1730           0 :         while (lstart < lend && rci.next < rci.ncand) {
    1731           0 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    1732             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    1733           0 :                 v = canditer_peek(&rci);
    1734             : 
    1735           0 :                 if (lvals) {
    1736           0 :                         if (lscan < lend - lstart &&
    1737           0 :                             lvals[lstart + lscan] < v) {
    1738           0 :                                 lstart = binsearch_oid(NULL, 0, lvals,
    1739             :                                                        lstart + lscan,
    1740             :                                                        lend - 1, v, 1, 0);
    1741             :                         } else {
    1742             :                                 /* scan l for v */
    1743           0 :                                 while (lstart < lend && lvals[lstart] < v)
    1744           0 :                                         lstart++;
    1745             :                         }
    1746             :                 } else {
    1747           0 :                         lstart = canditer_search(&lci, v, true);
    1748           0 :                         canditer_setidx(&lci, lstart);
    1749             :                 }
    1750           0 :                 if (lstart >= lend) {
    1751             :                         /* nothing found */
    1752             :                         break;
    1753             :                 }
    1754             : 
    1755             :                 /* Here we determine the next value in l that we are
    1756             :                  * going to try to match in r.  We will also count the
    1757             :                  * number of occurrences in l of that value.
    1758             :                  * Afterwards, v points to the value and nl is the
    1759             :                  * number of times it occurs.  Also, lstart will
    1760             :                  * point to the next value to be considered (ready for
    1761             :                  * the next iteration).
    1762             :                  * If there are many equal values in l (more than
    1763             :                  * lscan), we will use binary search to find the end
    1764             :                  * of the sequence.  Obviously, we can do this only if
    1765             :                  * l is actually sorted (lscan > 0). */
    1766           0 :                 nl = 1;         /* we'll match (at least) one in l */
    1767           0 :                 nr = 0;         /* maybe we won't match anything in r */
    1768           0 :                 v = lvals ? lvals[lstart] : canditer_next(&lci);
    1769           0 :                 if (li.key || lvals == NULL) {
    1770             :                         /* if l is key, there is a single value */
    1771           0 :                         lstart++;
    1772           0 :                 } else if (lscan < lend - lstart &&
    1773           0 :                            v == lvals[lstart + lscan]) {
    1774             :                         /* lots of equal values: use binary search to
    1775             :                          * find end */
    1776           0 :                         nl = binsearch_oid(NULL, 0, lvals, lstart + lscan,
    1777             :                                            lend - 1, v, 1, 1);
    1778           0 :                         nl -= lstart;
    1779           0 :                         lstart += nl;
    1780             :                 } else {
    1781             :                         /* just scan */
    1782           0 :                         while (++lstart < lend && v == lvals[lstart])
    1783           0 :                                 nl++;
    1784             :                 }
    1785             :                 /* lstart points one beyond the value we're
    1786             :                  * going to match: ready for the next iteration. */
    1787             : 
    1788             :                 /* First we find the first value in r that is at
    1789             :                  * least as large as v, then we find the first
    1790             :                  * value in r that is larger than v.  The difference
    1791             :                  * is the number of values equal to v and is stored in
    1792             :                  * nr.
    1793             :                  * We will use binary search on r to find both ends of
    1794             :                  * the sequence of values that are equal to v in case
    1795             :                  * the position is "too far" (more than rscan
    1796             :                  * away). */
    1797             : 
    1798             :                 /* first find the location of the first value in r
    1799             :                  * that is >= v, then find the location of the first
    1800             :                  * value in r that is > v; the difference is the
    1801             :                  * number of values equal to v */
    1802           0 :                 nr = canditer_search(&rci, v, true);
    1803           0 :                 canditer_setidx(&rci, nr);
    1804           0 :                 if (nr == rci.ncand) {
    1805             :                         /* nothing found */
    1806             :                         break;
    1807             :                 }
    1808             : 
    1809             :                 /* now find the end of the sequence of equal values v */
    1810             : 
    1811             :                 /* if r is key, there is zero or one match, otherwise
    1812             :                  * look ahead a little (rscan) in r to see whether
    1813             :                  * we're better off doing a binary search */
    1814           0 :                 if (canditer_peek(&rci) == v) {
    1815           0 :                         nr = 1;
    1816           0 :                         canditer_next(&rci);
    1817             :                 } else {
    1818             :                         /* rci points to first value > v or end of
    1819             :                          * r, and nr is the number of values in r that
    1820             :                          * are equal to v */
    1821             :                         /* no entries in r found */
    1822           0 :                         continue;
    1823             :                 }
    1824             :                 /* make space: nl values in l match nr values in r, so
    1825             :                  * we need to add nl * nr values in the results */
    1826           0 :                 if (maybeextend(r1, r2, NULL, nl * nr, lstart, lend, maxsize) != GDK_SUCCEED)
    1827           0 :                         goto bailout;
    1828             : 
    1829             :                 /* maintain properties */
    1830           0 :                 if (nl > 1) {
    1831             :                         /* value occurs multiple times in l, so entry
    1832             :                          * in r will be repeated multiple times: hence
    1833             :                          * r2 is not key and not dense */
    1834           0 :                         if (r2) {
    1835           0 :                                 r2->tkey = false;
    1836           0 :                                 r2->tseqbase = oid_nil;
    1837             :                         }
    1838             :                         /* multiple different values will be inserted
    1839             :                          * in r1 (always in order), so not reverse
    1840             :                          * ordered anymore */
    1841           0 :                         r1->trevsorted = false;
    1842             :                 }
    1843           0 :                 if (BATcount(r1) > 0) {
    1844             :                         /* a new, higher value will be inserted into
    1845             :                          * r1, so r1 is not reverse ordered anymore */
    1846           0 :                         r1->trevsorted = false;
    1847             :                         /* a new higher value will be added to r2 */
    1848           0 :                         if (r2) {
    1849           0 :                                 r2->trevsorted = false;
    1850             :                         }
    1851           0 :                         if (BATtdense(r1) &&
    1852           0 :                             ((oid *) r1->theap->base)[r1->batCount - 1] + 1 != l->hseqbase + lstart - nl) {
    1853           0 :                                 r1->tseqbase = oid_nil;
    1854             :                         }
    1855             :                 }
    1856             : 
    1857           0 :                 if (r2 &&
    1858           0 :                     BATcount(r2) > 0 &&
    1859           0 :                     BATtdense(r2) &&
    1860           0 :                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != r->hseqbase + rci.next - nr) {
    1861           0 :                         r2->tseqbase = oid_nil;
    1862             :                 }
    1863             : 
    1864             :                 /* insert values */
    1865           0 :                 lv = l->hseqbase + lstart - nl;
    1866           0 :                 for (i = 0; i < nl; i++) {
    1867             :                         BUN j;
    1868             : 
    1869           0 :                         for (j = 0; j < nr; j++) {
    1870           0 :                                 APPEND(r1, lv);
    1871             :                         }
    1872           0 :                         if (r2) {
    1873           0 :                                 oid rv = r->hseqbase + rci.next - nr;
    1874             : 
    1875           0 :                                 for (j = 0; j < nr; j++) {
    1876           0 :                                         APPEND(r2, rv);
    1877           0 :                                         rv++;
    1878             :                                 }
    1879             :                         }
    1880           0 :                         lv++;
    1881             :                 }
    1882             :         }
    1883             :         /* also set other bits of heap to correct value to indicate size */
    1884           0 :         BATsetcount(r1, BATcount(r1));
    1885           0 :         if (r2) {
    1886           0 :                 BATsetcount(r2, BATcount(r2));
    1887           0 :                 assert(BATcount(r1) == BATcount(r2));
    1888             :         }
    1889           0 :         if (BATcount(r1) > 0) {
    1890           0 :                 if (BATtdense(r1))
    1891           0 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    1892           0 :                 if (r2 && BATtdense(r2))
    1893           0 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    1894             :         } else {
    1895           0 :                 r1->tseqbase = 0;
    1896           0 :                 if (r2) {
    1897           0 :                         r2->tseqbase = 0;
    1898             :                 }
    1899             :         }
    1900           0 :         bat_iterator_end(&li);
    1901           0 :         bat_iterator_end(&ri);
    1902           0 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT ","
    1903             :                   "nil_matches=%s;%s %s "
    1904             :                   "-> " ALGOBATFMT "," ALGOOPTBATFMT " (" LLFMT "usec)\n",
    1905             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    1906             :                   nil_matches ? "true" : "false",
    1907             :                   swapped ? " swapped" : "", reason,
    1908             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    1909             :                   GDKusec() - t0);
    1910             : 
    1911             :         return GDK_SUCCEED;
    1912             : 
    1913           0 :   bailout:
    1914           0 :         bat_iterator_end(&li);
    1915           0 :         bat_iterator_end(&ri);
    1916           0 :         BBPreclaim(r1);
    1917           0 :         BBPreclaim(r2);
    1918             :         return GDK_FAIL;
    1919             : }
    1920             : 
    1921             : /* Perform a "merge" join on l and r (if both are sorted) with
    1922             :  * optional candidate lists, or join using binary search on r if l is
    1923             :  * not sorted.
    1924             :  *
    1925             :  * If nil_matches is set, nil values are treated as ordinary values
    1926             :  * that can match; otherwise nil values never match.
    1927             :  *
    1928             :  * If nil_on_miss is set, a nil value is returned in r2 if there is no
    1929             :  * match in r for a particular value in l (left outer join).
    1930             :  *
    1931             :  * If semi is set, only a single set of values in r1/r2 is returned if
    1932             :  * there is a match of l in r, no matter how many matches there are in
    1933             :  * r; otherwise all matches are returned.
    1934             :  *
    1935             :  * If max_one is set, only a single match is allowed.  This is like
    1936             :  * semi, but enforces the single match.
    1937             :  *
    1938             :  * t0 and swapped are only for debugging (ALGOMASK set in GDKdebug).
    1939             :  */
    1940             : static gdk_return
    1941       15143 : mergejoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r,
    1942             :           struct canditer *restrict lci, struct canditer *restrict rci,
    1943             :           bool nil_matches, bool nil_on_miss, bool semi, bool only_misses,
    1944             :           bool not_in, bool max_one, bool min_one, BUN estimate,
    1945             :           lng t0, bool swapped,
    1946             :           const char *reason)
    1947             : {
    1948             :         /* [lr]scan determine how far we look ahead in l/r in order to
    1949             :          * decide whether we want to do a binary search or a scan */
    1950       15143 :         BUN lscan, rscan;
    1951       15143 :         const void *lvals, *rvals; /* the values of l/r (NULL if dense) */
    1952       15143 :         const char *lvars, *rvars; /* the indirect values (NULL if fixed size) */
    1953       15143 :         const void *nil = ATOMnilptr(l->ttype);
    1954       15143 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    1955       15143 :         const void *v;          /* points to value under consideration */
    1956       15143 :         const void *prev = NULL;
    1957       15143 :         BUN nl, nr;
    1958       15143 :         bool insert_nil;
    1959             :         /* equal_order is set if we can scan both BATs in the same
    1960             :          * order, so when both are sorted or both are reverse sorted
    1961             :          * -- important to know in order to skip over values; if l is
    1962             :          * not sorted, this must be set to true and we will always do a
    1963             :          * binary search on all of r */
    1964       15143 :         bool equal_order;
    1965             :         /* [lr]ordering is either 1 or -1 depending on the order of
    1966             :          * l/r: it determines the comparison function used */
    1967       15143 :         int lordering, rordering;
    1968       15143 :         oid lv;
    1969       15143 :         BUN i, j;               /* counters */
    1970       15143 :         oid lval = oid_nil, rval = oid_nil; /* temporary space to point v to */
    1971       15143 :         struct canditer llci, rrci;
    1972       15143 :         struct canditer *mlci, xlci;
    1973       15143 :         struct canditer *mrci, xrci;
    1974             : 
    1975       15143 :         if (lci->tpe == cand_dense && lci->ncand == BATcount(l) &&
    1976       15109 :             rci->tpe == cand_dense && rci->ncand == BATcount(r) &&
    1977       14536 :             !nil_on_miss && !semi && !max_one && !min_one && !only_misses &&
    1978       10040 :             !not_in &&
    1979        8248 :             l->tsorted && r->tsorted) {
    1980             :                 /* special cases with far fewer options */
    1981        8198 :                 if (complex_cand(r))
    1982           0 :                         return mergejoin_cand(r1p, r2p, l, r, nil_matches,
    1983             :                                               estimate, t0, swapped, __func__);
    1984       16312 :                 switch (ATOMbasetype(l->ttype)) {
    1985        7894 :                 case TYPE_int:
    1986        7894 :                         return mergejoin_int(r1p, r2p, l, r, nil_matches,
    1987             :                                              estimate, t0, swapped, __func__);
    1988         220 :                 case TYPE_lng:
    1989         220 :                         return mergejoin_lng(r1p, r2p, l, r, nil_matches,
    1990             :                                              estimate, t0, swapped, __func__);
    1991             :                 }
    1992             :         }
    1993             : 
    1994       20970 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    1995        7029 :         assert(r->tsorted || r->trevsorted);
    1996             : 
    1997        7029 :         size_t counter = 0;
    1998        7029 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    1999             : 
    2000        7018 :         BATiter li = bat_iterator(l);
    2001        7027 :         BATiter ri = bat_iterator(r);
    2002        7030 :         MT_thread_setalgorithm(__func__);
    2003        7024 :         if (BATtvoid(l)) {
    2004             :                 /* l->ttype == TYPE_void && is_oid_nil(l->tseqbase) is
    2005             :                  * handled by selectjoin */
    2006          43 :                 assert(!is_oid_nil(l->tseqbase));
    2007          43 :                 canditer_init(&llci, NULL, l);
    2008          43 :                 lvals = NULL;
    2009             :         } else {
    2010        6981 :                 lvals = li.base;                              /* non NULL */
    2011        6981 :                 llci = (struct canditer) {.tpe = cand_dense}; /* not used */
    2012             :         }
    2013        7022 :         rrci = (struct canditer) {.tpe = cand_dense};
    2014        7022 :         if (BATtvoid(r)) {
    2015          53 :                 if (!is_oid_nil(r->tseqbase))
    2016          53 :                         canditer_init(&rrci, NULL, r);
    2017             :                 rvals = NULL;
    2018             :         } else {
    2019        6969 :                 rvals = ri.base;
    2020             :         }
    2021        7021 :         if (li.vh && li.type) {
    2022         162 :                 assert(ri.vh && ri.type);
    2023         162 :                 lvars = li.vh->base;
    2024         162 :                 rvars = ri.vh->base;
    2025             :         } else {
    2026        6859 :                 assert(ri.vh == NULL || ri.type == TYPE_void);
    2027             :                 lvars = rvars = NULL;
    2028             :         }
    2029             :         /* if the var pointer is not NULL, then so is the val pointer */
    2030        7021 :         assert(lvars == NULL || lvals != NULL);
    2031        7021 :         assert(rvars == NULL || rvals != NULL);
    2032             : 
    2033        7021 :         const bool rhasnil = !ri.nonil &&
    2034        1216 :                 ((BATtvoid(r) && r->tseqbase == oid_nil) ||
    2035        1216 :                  (rvals && cmp(nil, VALUE(r, (ri.sorted ? rci->seq : canditer_last(rci)) - r->hseqbase)) == 0));
    2036          10 :         const bit defmark = rhasnil ? bit_nil : 0;
    2037             : 
    2038        7022 :         if (not_in && (rhasnil || (BATtvoid(l) && l->tseqbase == oid_nil))) {
    2039           0 :                 bat_iterator_end(&li);
    2040           0 :                 bat_iterator_end(&ri);
    2041           0 :                 return nomatch(r1p, r2p, r3p, l, r, lci, defmark, false, false,
    2042             :                                __func__, t0);
    2043             :         }
    2044             : 
    2045        7022 :         if ((!nil_matches &&
    2046        6746 :              ((li.type == TYPE_void && is_oid_nil(l->tseqbase)) ||
    2047        6746 :               (ri.type == TYPE_void && is_oid_nil(r->tseqbase)))) ||
    2048        7022 :             (li.type == TYPE_void && is_oid_nil(l->tseqbase) &&
    2049           0 :              (ri.nonil ||
    2050           0 :               (ri.type == TYPE_void && !is_oid_nil(r->tseqbase)))) ||
    2051        7022 :             (ri.type == TYPE_void && is_oid_nil(r->tseqbase) &&
    2052           0 :              (li.nonil ||
    2053           0 :               (li.type == TYPE_void && !is_oid_nil(l->tseqbase))))) {
    2054             :                 /* there are no matches */
    2055           0 :                 bat_iterator_end(&li);
    2056           0 :                 bat_iterator_end(&ri);
    2057           0 :                 return nomatch(r1p, r2p, r3p, l, r, lci, defmark,
    2058             :                                nil_on_miss, only_misses, __func__, t0);
    2059             :         }
    2060             : 
    2061       14012 :         BUN maxsize = joininitresults(r1p, r2p, r3p, lci->ncand, rci->ncand,
    2062        7022 :                                       li.key, ri.key, semi | max_one,
    2063             :                                       nil_on_miss, only_misses, min_one,
    2064             :                                       estimate);
    2065        6990 :         if (maxsize == BUN_NONE) {
    2066           0 :                 bat_iterator_end(&li);
    2067           0 :                 bat_iterator_end(&ri);
    2068           0 :                 return GDK_FAIL;
    2069             :         }
    2070        6990 :         BAT *r1 = *r1p;
    2071        6990 :         BAT *r2 = r2p ? *r2p : NULL;
    2072        6990 :         BAT *r3 = r3p ? *r3p : NULL;
    2073             : 
    2074        6990 :         if (lci->tpe == cand_mask) {
    2075           0 :                 mlci = lci;
    2076           0 :                 canditer_init(&xlci, l, NULL);
    2077           0 :                 lci = &xlci;
    2078             :         } else {
    2079        6990 :                 mlci = NULL;
    2080        6990 :                 xlci = (struct canditer) {.tpe = cand_dense}; /* not used */
    2081             :         }
    2082        6990 :         if (rci->tpe == cand_mask) {
    2083           0 :                 mrci = rci;
    2084           0 :                 canditer_init(&xrci, r, NULL);
    2085           0 :                 rci = &xrci;
    2086             :         } else {
    2087        6990 :                 mrci = NULL;
    2088        6990 :                 xrci = (struct canditer) {.tpe = cand_dense}; /* not used */
    2089             :         }
    2090             : 
    2091        6990 :         if (li.sorted || li.revsorted) {
    2092        5001 :                 equal_order = (li.sorted && ri.sorted) ||
    2093         309 :                         (li.revsorted && ri.revsorted &&
    2094         113 :                          !BATtvoid(l) && !BATtvoid(r));
    2095        5001 :                 lordering = li.sorted && (ri.sorted || !equal_order) ? 1 : -1;
    2096        4909 :                 rordering = equal_order ? lordering : -lordering;
    2097        5001 :                 if (!li.nonil && !nil_matches && !nil_on_miss && lvals != NULL) {
    2098             :                         /* find first non-nil */
    2099         828 :                         nl = binsearch(NULL, 0, li.type, lvals, lvars, li.width, 0, BATcount(l), nil, li.sorted ? 1 : -1, li.sorted ? 1 : 0);
    2100         767 :                         nl = canditer_search(lci, nl + l->hseqbase, true);
    2101         763 :                         if (li.sorted) {
    2102         712 :                                 canditer_setidx(lci, nl);
    2103          51 :                         } else if (li.revsorted) {
    2104          51 :                                 lci->ncand = nl;
    2105             :                         }
    2106             :                 }
    2107             :                 /* determine opportunistic scan window for l */
    2108        9972 :                 lscan = 4 + ilog2(lci->ncand);
    2109             :         } else {
    2110             :                 /* if l not sorted, we will always use binary search
    2111             :                  * on r */
    2112        1989 :                 assert(!BATtvoid(l)); /* void is always sorted */
    2113        1989 :                 lscan = 0;
    2114        1989 :                 equal_order = true;
    2115        1989 :                 lordering = 1;
    2116        1989 :                 rordering = ri.sorted ? 1 : -1;
    2117             :         }
    2118             :         /* determine opportunistic scan window for r; if l is not
    2119             :          * sorted this is only used to find range of equal values */
    2120        6975 :         rscan = 4 + ilog2(rci->ncand);
    2121             : 
    2122        6975 :         if (!equal_order) {
    2123             :                 /* we go through r backwards */
    2124         195 :                 canditer_setidx(rci, rci->ncand);
    2125             :         }
    2126             :         /* At this point the various variables that help us through
    2127             :          * the algorithm have been set.  The table explains them.  The
    2128             :          * first two columns are the inputs, the next three columns
    2129             :          * are the variables, the final two columns indicate how the
    2130             :          * variables can be used.
    2131             :          *
    2132             :          * l/r    sl/sr | vals  cand  off | result   value being matched
    2133             :          * -------------+-----------------+----------------------------------
    2134             :          * dense  NULL  | NULL  NULL  set | i        off==nil?nil:i+off
    2135             :          * dense  dense | NULL  NULL  set | i        off==nil?nil:i+off
    2136             :          * dense  set   | NULL  set   set | cand[i]  off==nil?nil:cand[i]+off
    2137             :          * set    NULL  | set   NULL  0   | i        vals[i]
    2138             :          * set    dense | set   NULL  0   | i        vals[i]
    2139             :          * set    set   | set   set   0   | cand[i]  vals[cand[i]]
    2140             :          *
    2141             :          * If {l,r}off is lng_nil, all values in the corresponding bat
    2142             :          * are oid_nil because the bat has type VOID and the tseqbase
    2143             :          * is nil.
    2144             :          */
    2145             : 
    2146             : 
    2147             :         /* Before we start adding values to r1 and r2, the properties
    2148             :          * are as follows:
    2149             :          * tseqbase - 0
    2150             :          * tkey - true
    2151             :          * tsorted - true
    2152             :          * trevsorted - true
    2153             :          * tnil - false
    2154             :          * tnonil - true
    2155             :          * We will modify these as we go along.
    2156             :          */
    2157      534857 :         while (lci->next < lci->ncand) {
    2158      530135 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    2159             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    2160      530135 :                 bit mark = defmark;
    2161      530135 :                 if (lscan == 0) {
    2162             :                         /* always search r completely */
    2163      299175 :                         assert(equal_order);
    2164      299175 :                         canditer_reset(rci);
    2165             :                 } else {
    2166             :                         /* If l is sorted (lscan > 0), we look at the
    2167             :                          * next value in r to see whether we can jump
    2168             :                          * over a large section of l using binary
    2169             :                          * search.  We do this by looking ahead in l
    2170             :                          * (lscan far, to be precise) and seeing if
    2171             :                          * the value there is still too "small"
    2172             :                          * (definition depends on sort order of l).
    2173             :                          * If it is, we use binary search on l,
    2174             :                          * otherwise we scan l for the next position
    2175             :                          * with a value greater than or equal to the
    2176             :                          * value in r.
    2177             :                          * The next value to match in r is the first
    2178             :                          * if equal_order is set, the last
    2179             :                          * otherwise.
    2180             :                          * When skipping over values in l, we count
    2181             :                          * how many we skip in nlx.  We need this in
    2182             :                          * case only_misses or nil_on_miss is set, and
    2183             :                          * to properly set the dense property in the
    2184             :                          * first output BAT. */
    2185      230960 :                         BUN nlx = 0; /* number of non-matching values in l */
    2186             : 
    2187      230960 :                         if (equal_order) {
    2188      229959 :                                 if (rci->next == rci->ncand)
    2189             :                                         v = NULL; /* no more values */
    2190      227776 :                                 else if (mrci) {
    2191           0 :                                         oid rv = canditer_mask_next(mrci, canditer_peek(rci), true);
    2192           0 :                                         v = rv == oid_nil ? NULL : VALUE(r, rv - r->hseqbase);
    2193             :                                 } else
    2194      227776 :                                         v = VALUE(r, canditer_peek(rci) - r->hseqbase);
    2195             :                         } else {
    2196        1001 :                                 if (rci->next == 0)
    2197             :                                         v = NULL; /* no more values */
    2198         957 :                                 else if (mrci) {
    2199           0 :                                         oid rv = canditer_mask_next(mrci, canditer_peekprev(rci), false);
    2200           0 :                                         v = rv == oid_nil ? NULL : VALUE(r, rv - r->hseqbase);
    2201             :                                 } else
    2202         957 :                                         v = VALUE(r, canditer_peekprev(rci) - r->hseqbase);
    2203             :                         }
    2204             :                         /* here, v points to next value in r, or if
    2205             :                          * we're at the end of r, v is NULL */
    2206       11206 :                         if (v == NULL) {
    2207        2227 :                                 nlx = lci->ncand - lci->next;
    2208             :                         } else {
    2209      228824 :                                 if (lscan < lci->ncand - lci->next) {
    2210      207469 :                                         lv = canditer_idx(lci, lci->next + lscan);
    2211      207643 :                                         lv -= l->hseqbase;
    2212      207643 :                                         if (lvals) {
    2213      202766 :                                                 if (lordering * cmp(VALUE(l, lv), v) < 0) {
    2214        2162 :                                                         nlx = binsearch(NULL, 0, li.type, lvals, lvars, li.width, lv, BATcount(l), v, lordering, 0);
    2215        2162 :                                                         nlx = canditer_search(lci, nlx + l->hseqbase, true);
    2216        2162 :                                                         nlx -= lci->next;
    2217             :                                                 }
    2218             :                                         } else {
    2219        4877 :                                                 assert(lordering == 1);
    2220        4877 :                                                 if (canditer_idx(&llci, lv) < *(const oid *)v) {
    2221           8 :                                                         nlx = canditer_search(&llci, *(const oid *)v, true);
    2222           8 :                                                         nlx = canditer_search(lci, nlx + l->hseqbase, true);
    2223           8 :                                                         nlx -= lci->next;
    2224             :                                                 }
    2225             :                                         }
    2226      207632 :                                         if (mlci) {
    2227           0 :                                                 lv = canditer_mask_next(mlci, lci->seq + lci->next + nlx, true);
    2228           0 :                                                 if (lv == oid_nil)
    2229           0 :                                                         nlx = lci->ncand - lci->next;
    2230             :                                                 else
    2231           0 :                                                         nlx = lv - lci->seq - lci->next;
    2232             :                                         }
    2233      207632 :                                         if (lci->next + nlx == lci->ncand)
    2234          11 :                                                 v = NULL;
    2235             :                                 }
    2236             :                         }
    2237      209859 :                         if (nlx > 0) {
    2238        4397 :                                 if (only_misses) {
    2239        2752 :                                         if (maybeextend(r1, r2, r3, nlx, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    2240           0 :                                                 goto bailout;
    2241      232434 :                                         while (nlx > 0) {
    2242      229682 :                                                 lv = canditer_next(lci);
    2243      229683 :                                                 if (mlci == NULL || canditer_contains(mlci, lv))
    2244      229683 :                                                         APPEND(r1, lv);
    2245      229683 :                                                 nlx--;
    2246             :                                         }
    2247        2752 :                                         if (r1->trevsorted && BATcount(r1) > 1)
    2248         647 :                                                 r1->trevsorted = false;
    2249        1645 :                                 } else if (nil_on_miss) {
    2250          12 :                                         if (r2 && r2->tnonil) {
    2251           0 :                                                 r2->tnil = true;
    2252           0 :                                                 r2->tnonil = false;
    2253           0 :                                                 r2->tseqbase = oid_nil;
    2254           0 :                                                 r2->tsorted = false;
    2255           0 :                                                 r2->trevsorted = false;
    2256           0 :                                                 r2->tkey = false;
    2257             :                                         }
    2258          12 :                                         if (maybeextend(r1, r2, r3, nlx, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    2259           0 :                                                 goto bailout;
    2260          12 :                                         if (r3)
    2261          12 :                                                 r3->tnil = false;
    2262        2055 :                                         while (nlx > 0) {
    2263        2043 :                                                 lv = canditer_next(lci);
    2264        2043 :                                                 if (mlci == NULL || canditer_contains(mlci, lv)) {
    2265        2043 :                                                         APPEND(r1, lv);
    2266        2043 :                                                         if (r2)
    2267           0 :                                                                 APPEND(r2, oid_nil);
    2268        2043 :                                                         if (r3) {
    2269        2043 :                                                                 if (rhasnil || cmp(VALUE(l, lv - l->hseqbase), nil) == 0) {
    2270           0 :                                                                         ((bit *) r3->theap->base)[r3->batCount++] = bit_nil;
    2271           0 :                                                                         r3->tnil = true;
    2272             :                                                                 } else {
    2273        2043 :                                                                         ((bit *) r3->theap->base)[r3->batCount++] = 0;
    2274             :                                                                 }
    2275             :                                                         }
    2276             :                                                 }
    2277        2043 :                                                 nlx--;
    2278             :                                         }
    2279          12 :                                         if (r1->trevsorted && BATcount(r1) > 1)
    2280           3 :                                                 r1->trevsorted = false;
    2281             :                                 } else {
    2282        1633 :                                         canditer_setidx(lci, lci->next + nlx);
    2283             :                                 }
    2284             :                         }
    2285      231214 :                         if (v == NULL) {
    2286             :                                 /* we have exhausted the inputs */
    2287             :                                 break;
    2288             :                         }
    2289             :                 }
    2290             : 
    2291             :                 /* Here we determine the next value in l that we are
    2292             :                  * going to try to match in r.  We will also count the
    2293             :                  * number of occurrences in l of that value.
    2294             :                  * Afterwards, v points to the value and nl is the
    2295             :                  * number of times it occurs.  Also, lci will point to
    2296             :                  * the next value to be considered (ready for the next
    2297             :                  * iteration).
    2298             :                  * If there are many equal values in l (more than
    2299             :                  * lscan), we will use binary search to find the end
    2300             :                  * of the sequence.  Obviously, we can do this only if
    2301             :                  * l is actually sorted (lscan > 0). */
    2302      522500 :                 nl = 1;         /* we'll match (at least) one in l */
    2303      522500 :                 nr = 0;         /* maybe we won't match anything in r */
    2304      522500 :                 lv = canditer_peek(lci);
    2305      522355 :                 if (mlci) {
    2306           0 :                         lv = canditer_mask_next(mlci, lv, true);
    2307           0 :                         if (lv == oid_nil)
    2308             :                                 break;
    2309           0 :                         canditer_setidx(lci, canditer_search(lci, lv, true));
    2310             :                 }
    2311      522706 :                 v = VALUE(l, lv - l->hseqbase);
    2312      524771 :                 if (li.key) {
    2313             :                         /* if l is key, there is a single value */
    2314      334524 :                 } else if (lscan > 0 &&
    2315      111537 :                            lscan < lci->ncand - lci->next &&
    2316       55119 :                            cmp(v, VALUE(l, canditer_idx(lci, lci->next + lscan) - l->hseqbase)) == 0) {
    2317             :                         /* lots of equal values: use binary search to
    2318             :                          * find end */
    2319        1104 :                         assert(lvals != NULL);
    2320        2207 :                         nl = binsearch(NULL, 0,
    2321        1104 :                                        li.type, lvals, lvars,
    2322        1104 :                                        li.width, lci->next + lscan,
    2323             :                                        BATcount(l),
    2324             :                                        v, lordering, 1);
    2325        1103 :                         nl = canditer_search(lci, nl + l->hseqbase, true);
    2326        1104 :                         nl -= lci->next;
    2327             :                 } else {
    2328      333376 :                         struct canditer ci = *lci; /* work on copy */
    2329      333376 :                         nl = 0; /* it will be incremented again */
    2330      520697 :                         do {
    2331      520697 :                                 canditer_next(&ci);
    2332      516032 :                                 nl++;
    2333     1029470 :                         } while (ci.next < ci.ncand &&
    2334      514567 :                                  cmp(v, VALUE(l, canditer_peek(&ci) - l->hseqbase)) == 0);
    2335             :                 }
    2336             :                 /* lci->next + nl is the position for the next iteration */
    2337             : 
    2338      518933 :                 if ((!nil_matches || not_in) && !li.nonil && cmp(v, nil) == 0) {
    2339         965 :                         if (not_in) {
    2340             :                                 /* just skip the whole thing: nils
    2341             :                                  * don't cause any output */
    2342           1 :                                 canditer_setidx(lci, lci->next + nl);
    2343           1 :                                 continue;
    2344             :                         }
    2345             :                         /* v is nil and nils don't match anything, set
    2346             :                          * to NULL to indicate nil */
    2347         964 :                         v = NULL;
    2348         964 :                         mark = bit_nil;
    2349         964 :                         if (r3)
    2350          54 :                                 r3->tnil = true;
    2351             :                 }
    2352             : 
    2353             :                 /* First we find the "first" value in r that is "at
    2354             :                  * least as large" as v, then we find the "first"
    2355             :                  * value in r that is "larger" than v.  The difference
    2356             :                  * is the number of values equal to v and is stored in
    2357             :                  * nr.  The definitions of "larger" and "first" depend
    2358             :                  * on the orderings of l and r.  If equal_order is
    2359             :                  * set, we go through r from low to high (this
    2360             :                  * includes the case that l is not sorted); otherwise
    2361             :                  * we go through r from high to low.
    2362             :                  * In either case, we will use binary search on r to
    2363             :                  * find both ends of the sequence of values that are
    2364             :                  * equal to v in case the position is "too far" (more
    2365             :                  * than rscan away). */
    2366          54 :                 if (v == NULL) {
    2367             :                         nr = 0; /* nils don't match anything */
    2368      517078 :                 } else if (ri.type == TYPE_void && is_oid_nil(r->tseqbase)) {
    2369           0 :                         if (is_oid_nil(*(const oid *) v)) {
    2370             :                                 /* all values in r match */
    2371           0 :                                 nr = rci->ncand;
    2372             :                         } else {
    2373             :                                 /* no value in r matches */
    2374             :                                 nr = 0;
    2375             :                         }
    2376             :                         /* in either case, we're done after this */
    2377           0 :                         canditer_setidx(rci, equal_order ? rci->ncand : 0);
    2378      517078 :                 } else if (equal_order) {
    2379             :                         /* first find the location of the first value
    2380             :                          * in r that is >= v, then find the location
    2381             :                          * of the first value in r that is > v; the
    2382             :                          * difference is the number of values equal
    2383             :                          * v; we change rci */
    2384             : 
    2385             :                         /* look ahead a little (rscan) in r to
    2386             :                          * see whether we're better off doing
    2387             :                          * a binary search */
    2388      516121 :                         if (rvals) {
    2389      504915 :                                 if (rscan < rci->ncand - rci->next &&
    2390      462235 :                                     rordering * cmp(v, VALUE(r, canditer_idx(rci, rci->next + rscan) - r->hseqbase)) > 0) {
    2391             :                                         /* value too far away in r:
    2392             :                                          * use binary search */
    2393      116039 :                                         lv = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, rci->next + rscan, BATcount(r), v, rordering, 0);
    2394      127528 :                                         lv = canditer_search(rci, lv + r->hseqbase, true);
    2395      126737 :                                         canditer_setidx(rci, lv);
    2396             :                                 } else {
    2397             :                                         /* scan r for v */
    2398      409036 :                                         while (rci->next < rci->ncand) {
    2399      408426 :                                                 if (rordering * cmp(v, VALUE(r, canditer_peek(rci) - r->hseqbase)) <= 0)
    2400             :                                                         break;
    2401       19569 :                                                 canditer_next(rci);
    2402             :                                         }
    2403             :                                 }
    2404      999462 :                                 if (rci->next < rci->ncand &&
    2405      486452 :                                     cmp(v, VALUE(r, canditer_peek(rci) - r->hseqbase)) == 0) {
    2406             :                                         /* if we found an equal value,
    2407             :                                          * look for the last equal
    2408             :                                          * value */
    2409      270766 :                                         if (ri.key) {
    2410             :                                                 /* r is key, there can
    2411             :                                                  * only be a single
    2412             :                                                  * equal value */
    2413      149275 :                                                 nr = 1;
    2414      149275 :                                                 canditer_next(rci);
    2415      241270 :                                         } else if (rscan < rci->ncand - rci->next &&
    2416      119780 :                                                    cmp(v, VALUE(r, canditer_idx(rci, rci->next + rscan) - r->hseqbase)) == 0) {
    2417             :                                                 /* many equal values:
    2418             :                                                  * use binary search
    2419             :                                                  * to find the end */
    2420       65845 :                                                 nr = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, rci->next + rscan, BATcount(r), v, rordering, 1);
    2421       65845 :                                                 nr = canditer_search(rci, nr + r->hseqbase, true);
    2422       65845 :                                                 nr -= rci->next;
    2423       65845 :                                                 canditer_setidx(rci, rci->next + nr);
    2424             :                                         } else {
    2425             :                                                 /* scan r for end of
    2426             :                                                  * range */
    2427      152527 :                                                 do {
    2428      152527 :                                                         nr++;
    2429      152527 :                                                         canditer_next(rci);
    2430      304649 :                                                 } while (rci->next < rci->ncand &&
    2431      152131 :                                                          cmp(v, VALUE(r, canditer_peek(rci) - r->hseqbase)) == 0);
    2432             :                                         }
    2433             :                                 }
    2434             :                         } else {
    2435       11206 :                                 assert(rordering == 1);
    2436       11206 :                                 rval = canditer_search(&rrci, *(const oid*)v, true) + r->hseqbase;
    2437       11206 :                                 lv = canditer_search(rci, rval, true);
    2438       11206 :                                 canditer_setidx(rci, lv);
    2439       11206 :                                 nr = (canditer_idx(&rrci, canditer_peek(rci) - r->hseqbase) == *(oid*)v);
    2440       11206 :                                 if (nr == 1)
    2441       11206 :                                         canditer_next(rci);
    2442             :                         }
    2443             :                         /* rci points to first value > v or end of r,
    2444             :                          * and nr is the number of values in r that
    2445             :                          * are equal to v */
    2446             :                 } else {
    2447             :                         /* first find the location of the first value
    2448             :                          * in r that is > v, then find the location
    2449             :                          * of the first value in r that is >= v; the
    2450             :                          * difference is the number of values equal
    2451             :                          * v; we change rci */
    2452             : 
    2453             :                         /* look back from the end a little
    2454             :                          * (rscan) in r to see whether we're
    2455             :                          * better off doing a binary search */
    2456         957 :                         if (rvals) {
    2457         957 :                                 if (rci->next > rscan &&
    2458         580 :                                     rordering * cmp(v, VALUE(r, canditer_idx(rci, rci->next - rscan) - r->hseqbase)) < 0) {
    2459             :                                         /* value too far away
    2460             :                                          * in r: use binary
    2461             :                                          * search */
    2462          29 :                                         lv = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, 0, rci->next - rscan, v, rordering, 1);
    2463          29 :                                         lv = canditer_search(rci, lv + r->hseqbase, true);
    2464          29 :                                         canditer_setidx(rci, lv);
    2465             :                                 } else {
    2466             :                                         /* scan r for v */
    2467        1679 :                                         while (rci->next > 0 &&
    2468        1674 :                                                rordering * cmp(v, VALUE(r, canditer_peekprev(rci) - r->hseqbase)) < 0)
    2469         751 :                                                 canditer_prev(rci);
    2470             :                                 }
    2471        1894 :                                 if (rci->next > 0 &&
    2472         937 :                                     cmp(v, VALUE(r, canditer_peekprev(rci) - r->hseqbase)) == 0) {
    2473             :                                         /* if we found an equal value,
    2474             :                                          * look for the last equal
    2475             :                                          * value */
    2476         846 :                                         if (ri.key) {
    2477             :                                                 /* r is key, there can only be a single equal value */
    2478         286 :                                                 nr = 1;
    2479         286 :                                                 canditer_prev(rci);
    2480        1044 :                                         } else if (rci->next > rscan &&
    2481         484 :                                                    cmp(v, VALUE(r, canditer_idx(rci, rci->next - rscan) - r->hseqbase)) == 0) {
    2482             :                                                 /* use binary search to find the start */
    2483          37 :                                                 nr = binsearch(NULL, 0, ri.type, rvals, rvars, ri.width, 0, rci->next - rscan, v, rordering, 0);
    2484          37 :                                                 nr = canditer_search(rci, nr + r->hseqbase, true);
    2485          37 :                                                 nr = rci->next - nr;
    2486          37 :                                                 canditer_setidx(rci, rci->next - nr);
    2487             :                                         } else {
    2488             :                                                 /* scan r for start of range */
    2489         645 :                                                 do {
    2490         645 :                                                         canditer_prev(rci);
    2491         645 :                                                         nr++;
    2492        1249 :                                                 } while (rci->next > 0 &&
    2493         604 :                                                          cmp(v, VALUE(r, canditer_peekprev(rci) - r->hseqbase)) == 0);
    2494             :                                         }
    2495             :                                 }
    2496             :                         } else {
    2497           0 :                                 lv = canditer_search(&rrci, *(const oid *)v, true);
    2498           0 :                                 lv = canditer_search(rci, lv + r->hseqbase, true);
    2499           0 :                                 nr = (canditer_idx(rci, lv) == *(const oid*)v);
    2500           0 :                                 canditer_setidx(rci, lv);
    2501             :                         }
    2502             :                         /* rci points to first value > v
    2503             :                          * or end of r, and nr is the number of values
    2504             :                          * in r that are equal to v */
    2505             :                 }
    2506             : 
    2507      285400 :                 if (nr == 0) {
    2508             :                         /* no entries in r found */
    2509      245843 :                         if (!(nil_on_miss | only_misses)) {
    2510      205313 :                                 if (min_one) {
    2511           0 :                                         GDKerror("not enough matches");
    2512           0 :                                         goto bailout;
    2513             :                                 }
    2514      209529 :                                 if (lscan > 0 &&
    2515        4216 :                                     (equal_order ? rci->next == rci->ncand : rci->next == 0)) {
    2516             :                                         /* nothing more left to match
    2517             :                                          * in r */
    2518             :                                         break;
    2519             :                                 }
    2520      205279 :                                 canditer_setidx(lci, lci->next + nl);
    2521      204280 :                                 continue;
    2522             :                         }
    2523             :                         /* insert a nil to indicate a non-match */
    2524       40530 :                         insert_nil = true;
    2525       40530 :                         nr = 1;
    2526       40530 :                         if (r2) {
    2527           4 :                                 r2->tnil = true;
    2528           4 :                                 r2->tnonil = false;
    2529           4 :                                 r2->tsorted = false;
    2530           4 :                                 r2->trevsorted = false;
    2531           4 :                                 r2->tseqbase = oid_nil;
    2532           4 :                                 r2->tkey = false;
    2533             :                         }
    2534      282775 :                 } else if (nr > 1 && max_one) {
    2535          10 :                         GDKerror("more than one match");
    2536          10 :                         goto bailout;
    2537      282765 :                 } else if (only_misses) {
    2538             :                         /* we had a match, so we're not interested */
    2539      115976 :                         canditer_setidx(lci, lci->next + nl);
    2540      116253 :                         continue;
    2541             :                 } else {
    2542      166789 :                         insert_nil = false;
    2543      166789 :                         if (semi) {
    2544             :                                 /* for semi-join, only insert single
    2545             :                                  * value */
    2546       33452 :                                 nr = 1;
    2547             :                         }
    2548             :                 }
    2549             :                 /* make space: nl values in l match nr values in r, so
    2550             :                  * we need to add nl * nr values in the results */
    2551      207319 :                 if (maybeextend(r1, r2, r3, nl * nr, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    2552           0 :                         goto bailout;
    2553             : 
    2554             :                 /* maintain properties */
    2555      207672 :                 if (nl > 1) {
    2556       54942 :                         if (r2) {
    2557             :                                 /* value occurs multiple times in l,
    2558             :                                  * so entry in r will be repeated
    2559             :                                  * multiple times: hence r2 is not key
    2560             :                                  * and not dense */
    2561       14812 :                                 r2->tkey = false;
    2562       14812 :                                 r2->tseqbase = oid_nil;
    2563             :                         }
    2564             :                         /* multiple different values will be inserted
    2565             :                          * in r1 (always in order), so not reverse
    2566             :                          * ordered anymore */
    2567       54942 :                         r1->trevsorted = false;
    2568             :                 }
    2569      207672 :                 if (nr > 1) {
    2570             :                         /* value occurs multiple times in r, so entry
    2571             :                          * in l will be repeated multiple times: hence
    2572             :                          * r1 is not key and not dense */
    2573       65822 :                         r1->tkey = false;
    2574       65822 :                         if (r2) {
    2575             :                                 /* multiple different values will be
    2576             :                                  * inserted in r2 (in order), so not
    2577             :                                  * reverse ordered anymore */
    2578       65401 :                                 r2->trevsorted = false;
    2579       65401 :                                 if (nl > 1) {
    2580             :                                         /* multiple values in l match
    2581             :                                          * multiple values in r, so an
    2582             :                                          * ordered sequence will be
    2583             :                                          * inserted multiple times in
    2584             :                                          * r2, so r2 is not ordered
    2585             :                                          * anymore */
    2586        7170 :                                         r2->tsorted = false;
    2587             :                                 }
    2588             :                         }
    2589             :                 }
    2590      207672 :                 if (lscan == 0) {
    2591             :                         /* deduce relative positions of r matches for
    2592             :                          * this and previous value in v */
    2593       88357 :                         if (prev && r2) {
    2594             :                                 /* keyness or r2 can only be assured
    2595             :                                  * as long as matched values are
    2596             :                                  * ordered */
    2597       87217 :                                 int ord = rordering * cmp(prev, v ? v : nil);
    2598       87509 :                                 if (ord < 0) {
    2599             :                                         /* previous value in l was
    2600             :                                          * less than current */
    2601       29486 :                                         r2->trevsorted = false;
    2602       29486 :                                         r2->tkey &= r2->tsorted;
    2603       58023 :                                 } else if (ord > 0) {
    2604             :                                         /* previous value was
    2605             :                                          * greater */
    2606       28730 :                                         r2->tsorted = false;
    2607       28730 :                                         r2->tkey &= r2->trevsorted;
    2608             :                                 } else {
    2609             :                                         /* value can be equal if
    2610             :                                          * intervening values in l
    2611             :                                          * didn't match anything; if
    2612             :                                          * multiple values match in r,
    2613             :                                          * r2 won't be sorted */
    2614       29293 :                                         r2->tkey = false;
    2615       29293 :                                         if (nr > 1) {
    2616       29259 :                                                 r2->tsorted = false;
    2617       29259 :                                                 r2->trevsorted = false;
    2618             :                                         }
    2619             :                                 }
    2620             :                         }
    2621       88649 :                         prev = v ? v : nil;
    2622             :                 }
    2623      207964 :                 if (BATcount(r1) > 0) {
    2624             :                         /* a new, higher value will be inserted into
    2625             :                          * r1, so r1 is not reverse ordered anymore */
    2626      203974 :                         r1->trevsorted = false;
    2627      203974 :                         if (r2) {
    2628             :                                 /* depending on whether l and r are
    2629             :                                  * ordered the same or not, a new
    2630             :                                  * higher or lower value will be added
    2631             :                                  * to r2 */
    2632       90036 :                                 if (equal_order)
    2633       89908 :                                         r2->trevsorted = false;
    2634             :                                 else {
    2635         128 :                                         r2->tsorted = false;
    2636         128 :                                         r2->tseqbase = oid_nil;
    2637             :                                 }
    2638             :                         }
    2639             :                 }
    2640             : 
    2641             :                 /* insert values: first the left output */
    2642             :                 BUN nladded = 0;
    2643      541109 :                 for (i = 0; i < nl; i++) {
    2644      333769 :                         lv = canditer_next(lci);
    2645      333145 :                         if (mlci == NULL || canditer_contains(mlci, lv)) {
    2646      333145 :                                 nladded++;
    2647    60461670 :                                 for (j = 0; j < nr; j++)
    2648    60128525 :                                         APPEND(r1, lv);
    2649             :                         }
    2650             :                 }
    2651      207340 :                 nl = nladded;
    2652             :                 /* then the right output, various different ways of
    2653             :                  * doing it */
    2654      207340 :                 if (r2) {
    2655       90328 :                         if (insert_nil) {
    2656          11 :                                 for (i = 0; i < nl; i++) {
    2657          14 :                                         for (j = 0; j < nr; j++) {
    2658           7 :                                                 APPEND(r2, oid_nil);
    2659             :                                         }
    2660             :                                 }
    2661       90324 :                         } else if (equal_order) {
    2662       90069 :                                 struct canditer ci = *rci; /* work on copy */
    2663       90069 :                                 if (r2->batCount > 0 &&
    2664       92263 :                                     BATtdense(r2) &&
    2665        2781 :                                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != canditer_idx(&ci, ci.next - nr))
    2666          86 :                                         r2->tseqbase = oid_nil;
    2667      213826 :                                 for (i = 0; i < nl; i++) {
    2668      123749 :                                         canditer_setidx(&ci, ci.next - nr);
    2669    60165049 :                                         for (j = 0; j < nr; j++) {
    2670    59917543 :                                                 APPEND(r2, canditer_next(&ci));
    2671             :                                         }
    2672             :                                 }
    2673             :                         } else {
    2674         255 :                                 if (r2->batCount > 0 &&
    2675         128 :                                     BATtdense(r2) &&
    2676           0 :                                     ((oid *) r2->theap->base)[r2->batCount - 1] + 1 != canditer_peek(rci))
    2677           0 :                                         r2->tseqbase = oid_nil;
    2678        3558 :                                 for (i = 0; i < nl; i++) {
    2679        3303 :                                         struct canditer ci = *rci; /* work on copy */
    2680        7403 :                                         for (j = 0; j < nr; j++) {
    2681        4100 :                                                 APPEND(r2, canditer_next(&ci));
    2682             :                                         }
    2683             :                                 }
    2684             :                         }
    2685             :                 }
    2686             :                 /* finally the mark output */
    2687      207348 :                 if (r3) {
    2688        2667 :                         if (insert_nil) {
    2689         308 :                                 r3->tnil |= rhasnil;
    2690         784 :                                 for (i = 0; i < nl; i++) {
    2691         952 :                                         for (j = 0; j < nr; j++) {
    2692         476 :                                                 ((bit *) r3->theap->base)[r3->batCount++] = mark;
    2693             :                                         }
    2694             :                                 }
    2695             :                         } else {
    2696        8164 :                                 for (i = 0; i < nl; i++) {
    2697       11608 :                                         for (j = 0; j < nr; j++) {
    2698        5803 :                                                 ((bit *) r3->theap->base)[r3->batCount++] = 1;
    2699             :                                         }
    2700             :                                 }
    2701             :                         }
    2702             :                 }
    2703             :         }
    2704             :         /* also set other bits of heap to correct value to indicate size */
    2705        6994 :         BATsetcount(r1, BATcount(r1));
    2706        6985 :         r1->tseqbase = oid_nil;
    2707        6985 :         if (r1->tkey)
    2708        6892 :                 r1 = virtualize(r1);
    2709        7004 :         if (r2) {
    2710        1848 :                 BATsetcount(r2, BATcount(r2));
    2711        1848 :                 assert(BATcount(r1) == BATcount(r2));
    2712        1848 :                 r2->tseqbase = oid_nil;
    2713        1848 :                 if (BATcount(r2) <= 1) {
    2714        1136 :                         r2->tkey = true;
    2715        1136 :                         r2 = virtualize(r2);
    2716             :                 }
    2717             :         }
    2718        7012 :         if (r3) {
    2719          54 :                 BATsetcount(r3, BATcount(r3));
    2720          54 :                 assert(BATcount(r1) == BATcount(r3));
    2721          54 :                 r3->tseqbase = oid_nil;
    2722          54 :                 r3->tnonil = !r3->tnil;
    2723          54 :                 if (BATcount(r3) <= 1) {
    2724           0 :                         r3->tkey = true;
    2725           0 :                         r3->tsorted = true;
    2726           0 :                         r3->trevsorted = true;
    2727             :                 }
    2728             :         }
    2729        7012 :         bat_iterator_end(&li);
    2730        7002 :         bat_iterator_end(&ri);
    2731        6918 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
    2732             :                   "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    2733             :                   "sr=" ALGOOPTBATFMT ","
    2734             :                   "nil_on_miss=%s,semi=%s,only_misses=%s,not_in=%s;%s %s "
    2735             :                   "-> " ALGOBATFMT "," ALGOOPTBATFMT " (" LLFMT "usec)\n",
    2736             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    2737             :                   ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
    2738             :                   nil_on_miss ? "true" : "false",
    2739             :                   semi ? "true" : "false",
    2740             :                   only_misses ? "true" : "false",
    2741             :                   not_in ? "true" : "false",
    2742             :                   swapped ? " swapped" : "", reason,
    2743             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    2744             :                   GDKusec() - t0);
    2745             : 
    2746             :         return GDK_SUCCEED;
    2747             : 
    2748          10 :   bailout:
    2749          10 :         bat_iterator_end(&li);
    2750          10 :         bat_iterator_end(&ri);
    2751          10 :         BBPreclaim(r1);
    2752          10 :         BBPreclaim(r2);
    2753          10 :         BBPreclaim(r3);
    2754             :         return GDK_FAIL;
    2755             : }
    2756             : 
    2757             : #define HASHLOOPBODY()                                                  \
    2758             :         do {                                                            \
    2759             :                 if (nr >= 1 && max_one) {                            \
    2760             :                         GDKerror("more than one match");              \
    2761             :                         goto bailout;                                   \
    2762             :                 }                                                       \
    2763             :                 if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED) \
    2764             :                         goto bailout;                                   \
    2765             :                 APPEND(r1, lo);                                         \
    2766             :                 if (r2)                                                 \
    2767             :                         APPEND(r2, ro);                                 \
    2768             :                 if (r3)                                                 \
    2769             :                         ((bit *) r3->theap->base)[r3->batCount++] = 1; \
    2770             :                 nr++;                                                   \
    2771             :         } while (false)
    2772             : 
    2773             : #define EQ_int(a, b)    ((a) == (b))
    2774             : #define EQ_lng(a, b)    ((a) == (b))
    2775             : #ifdef HAVE_HGE
    2776             : #define EQ_uuid(a, b)   ((a).h == (b).h)
    2777             : #else
    2778             : #define EQ_uuid(a, b)   (memcmp((a).u, (b).u, UUID_SIZE) == 0)
    2779             : #endif
    2780             : 
    2781             : #define HASHJOIN(TYPE)                                                  \
    2782             :         do {                                                            \
    2783             :                 TYPE *rvals = ri.base;                                  \
    2784             :                 TYPE *lvals = li.base;                                  \
    2785             :                 TYPE v;                                                 \
    2786             :                 while (lci->next < lci->ncand) {                       \
    2787             :                         GDK_CHECK_TIMEOUT(qry_ctx, counter, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx)); \
    2788             :                         lo = canditer_next(lci);                        \
    2789             :                         v = lvals[lo - l->hseqbase];                 \
    2790             :                         nr = 0;                                         \
    2791             :                         bit mark = defmark;                             \
    2792             :                         if ((!nil_matches || not_in) && is_##TYPE##_nil(v)) { \
    2793             :                                 /* no match */                          \
    2794             :                                 if (not_in) {                           \
    2795             :                                         lskipped = BATcount(r1) > 0; \
    2796             :                                         continue;                       \
    2797             :                                 }                                       \
    2798             :                                 mark = bit_nil;                         \
    2799             :                         } else if (hash_cand) {                         \
    2800             :                                 /* private hash: no locks */            \
    2801             :                                 for (rb = HASHget(hsh, hash_##TYPE(hsh, &v)); \
    2802             :                                      rb != BUN_NONE;                    \
    2803             :                                      rb = HASHgetlink(hsh, rb)) {       \
    2804             :                                         ro = canditer_idx(rci, rb);     \
    2805             :                                         if (!EQ_##TYPE(v, rvals[ro - r->hseqbase])) \
    2806             :                                                 continue;               \
    2807             :                                         if (only_misses) {              \
    2808             :                                                 nr++;                   \
    2809             :                                                 break;                  \
    2810             :                                         }                               \
    2811             :                                         HASHLOOPBODY();                 \
    2812             :                                         if (semi && !max_one)           \
    2813             :                                                 break;                  \
    2814             :                                 }                                       \
    2815             :                         } else if (rci->tpe != cand_dense) {         \
    2816             :                                 for (rb = HASHget(hsh, hash_##TYPE(hsh, &v)); \
    2817             :                                      rb != BUN_NONE;                    \
    2818             :                                      rb = HASHgetlink(hsh, rb)) {       \
    2819             :                                         if (rb >= rl && rb < rh &&        \
    2820             :                                             EQ_##TYPE(v, rvals[rb]) &&  \
    2821             :                                             canditer_contains(rci, ro = (oid) (rb - roff + rseq))) { \
    2822             :                                                 if (only_misses) {      \
    2823             :                                                         nr++;           \
    2824             :                                                         break;          \
    2825             :                                                 }                       \
    2826             :                                                 HASHLOOPBODY();         \
    2827             :                                                 if (semi && !max_one)   \
    2828             :                                                         break;          \
    2829             :                                         }                               \
    2830             :                                 }                                       \
    2831             :                         } else {                                        \
    2832             :                                 for (rb = HASHget(hsh, hash_##TYPE(hsh, &v)); \
    2833             :                                      rb != BUN_NONE;                    \
    2834             :                                      rb = HASHgetlink(hsh, rb)) {       \
    2835             :                                         if (rb >= rl && rb < rh &&        \
    2836             :                                             EQ_##TYPE(v, rvals[rb])) {  \
    2837             :                                                 if (only_misses) {      \
    2838             :                                                         nr++;           \
    2839             :                                                         break;          \
    2840             :                                                 }                       \
    2841             :                                                 ro = (oid) (rb - roff + rseq); \
    2842             :                                                 HASHLOOPBODY();         \
    2843             :                                                 if (semi && !max_one)   \
    2844             :                                                         break;          \
    2845             :                                         }                               \
    2846             :                                 }                                       \
    2847             :                         }                                               \
    2848             :                         if (nr == 0) {                                  \
    2849             :                                 if (only_misses) {                      \
    2850             :                                         nr = 1;                         \
    2851             :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED) \
    2852             :                                                 goto bailout;           \
    2853             :                                         APPEND(r1, lo);                 \
    2854             :                                         if (lskipped)                   \
    2855             :                                                 r1->tseqbase = oid_nil;      \
    2856             :                                 } else if (nil_on_miss) {               \
    2857             :                                         nr = 1;                         \
    2858             :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED) \
    2859             :                                                 goto bailout;           \
    2860             :                                         APPEND(r1, lo);                 \
    2861             :                                         if (r2) {                       \
    2862             :                                                 r2->tnil = true;     \
    2863             :                                                 r2->tnonil = false;  \
    2864             :                                                 r2->tkey = false;    \
    2865             :                                                 APPEND(r2, oid_nil);    \
    2866             :                                         }                               \
    2867             :                                         if (r3) {                       \
    2868             :                                                 r3->tnil |= mark == bit_nil; \
    2869             :                                                 ((bit *) r3->theap->base)[r3->batCount++] = mark; \
    2870             :                                         }                               \
    2871             :                                 } else if (min_one) {                   \
    2872             :                                         GDKerror("not enough matches");       \
    2873             :                                         goto bailout;                   \
    2874             :                                 } else {                                \
    2875             :                                         lskipped = BATcount(r1) > 0; \
    2876             :                                 }                                       \
    2877             :                         } else if (only_misses) {                       \
    2878             :                                 lskipped = BATcount(r1) > 0;         \
    2879             :                         } else {                                        \
    2880             :                                 if (lskipped) {                         \
    2881             :                                         /* note, we only get here in an \
    2882             :                                          * iteration *after* lskipped was \
    2883             :                                          * first set to true, i.e. we did \
    2884             :                                          * indeed skip values in l */   \
    2885             :                                         r1->tseqbase = oid_nil;              \
    2886             :                                 }                                       \
    2887             :                                 if (nr > 1) {                                \
    2888             :                                         r1->tkey = false;            \
    2889             :                                         r1->tseqbase = oid_nil;              \
    2890             :                                 }                                       \
    2891             :                         }                                               \
    2892             :                         if (nr > 0 && BATcount(r1) > nr)          \
    2893             :                                 r1->trevsorted = false;                      \
    2894             :                 }                                                       \
    2895             :         } while (0)
    2896             : 
    2897             : /* Implementation of join using a hash lookup of values in the right
    2898             :  * column. */
    2899             : static gdk_return
    2900       16345 : hashjoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r,
    2901             :          struct canditer *restrict lci, struct canditer *restrict rci,
    2902             :          bool nil_matches, bool nil_on_miss, bool semi, bool only_misses,
    2903             :          bool not_in, bool max_one, bool min_one,
    2904             :          BUN estimate, lng t0, bool swapped,
    2905             :          bool hash, bool phash, bool hash_cand,
    2906             :          const char *reason)
    2907             : {
    2908       16345 :         oid lo, ro;
    2909       16345 :         BATiter li, ri;
    2910       16345 :         BUN rb, roff = 0;
    2911             :         /* rl, rh: lower and higher bounds for BUN values in hash table */
    2912       16345 :         BUN rl, rh;
    2913       16345 :         oid rseq;
    2914       16345 :         BUN nr;
    2915       16345 :         const char *lvals;
    2916       16345 :         const char *lvars;
    2917       16345 :         const void *nil = ATOMnilptr(l->ttype);
    2918       16345 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    2919       16345 :         oid lval = oid_nil;     /* hold value if l is dense */
    2920       16345 :         const char *v = (const char *) &lval;
    2921       16345 :         bool lskipped = false;  /* whether we skipped values in l */
    2922       16345 :         Hash *restrict hsh = NULL;
    2923       16345 :         bool locked = false;
    2924       16345 :         BUN maxsize;
    2925       16345 :         BAT *r1 = NULL;
    2926       16345 :         BAT *r2 = NULL;
    2927       16345 :         BAT *r3 = NULL;
    2928       16345 :         BAT *b = NULL;
    2929             : 
    2930       48993 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    2931             : 
    2932       16345 :         size_t counter = 0;
    2933       16345 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    2934             : 
    2935       16346 :         li = bat_iterator(l);
    2936       16359 :         ri = bat_iterator(r);
    2937             : 
    2938       16357 :         int t = ATOMbasetype(ri.type);
    2939       16357 :         if (BATtvoid(r) || BATtvoid(l))
    2940           6 :                 t = TYPE_void;
    2941             : 
    2942       16357 :         lvals = (const char *) li.base;
    2943       16357 :         if (li.vh && li.type) {
    2944        1089 :                 assert(ri.vh && ri.type);
    2945        1089 :                 lvars = li.vh->base;
    2946             :         } else {
    2947       15268 :                 assert(ri.vh == NULL);
    2948             :                 lvars = NULL;
    2949             :         }
    2950             :         /* offset to convert BUN to OID for value in right column */
    2951       16357 :         rseq = r->hseqbase;
    2952             : 
    2953       16357 :         rl = rci->seq - r->hseqbase;
    2954       16357 :         rh = canditer_last(rci) + 1 - r->hseqbase;
    2955       16350 :         if (hash_cand) {
    2956             :                 /* we need to create a hash on r specific for the
    2957             :                  * candidate list */
    2958         176 :                 char ext[32];
    2959         176 :                 assert(rci->s);
    2960         220 :                 MT_thread_setalgorithm(swapped ? "hashjoin using candidate hash (swapped)" : "hashjoin using candidate hash");
    2961         176 :                 TRC_DEBUG(ALGO, ALGOBATFMT ": creating "
    2962             :                           "hash for candidate list " ALGOBATFMT "%s%s\n",
    2963             :                           ALGOBATPAR(r), ALGOBATPAR(rci->s),
    2964             :                           r->thash ? " ignoring existing hash" : "",
    2965             :                           swapped ? " (swapped)" : "");
    2966         176 :                 if (snprintf(ext, sizeof(ext), "thshjn%x",
    2967         176 :                              (unsigned) MT_getpid()) >= (int) sizeof(ext))
    2968           0 :                         goto bailout;
    2969         176 :                 if ((hsh = BAThash_impl(r, rci, ext)) == NULL) {
    2970           0 :                         goto bailout;
    2971             :                 }
    2972       16174 :         } else if (phash) {
    2973             :                 /* there is a hash on the parent which we should use */
    2974        2007 :                 MT_thread_setalgorithm(swapped ? "hashjoin using parent hash (swapped)" : "hashjoin using parent hash");
    2975        1783 :                 b = BATdescriptor(VIEWtparent(r));
    2976        1783 :                 if (b == NULL)
    2977           0 :                         goto bailout;
    2978        1783 :                 TRC_DEBUG(ALGO, "%s(%s): using "
    2979             :                           "parent(" ALGOBATFMT ") for hash%s\n",
    2980             :                           __func__,
    2981             :                           BATgetId(r), ALGOBATPAR(b),
    2982             :                           swapped ? " (swapped)" : "");
    2983        1783 :                 roff = r->tbaseoff - b->tbaseoff;
    2984        1783 :                 rl += roff;
    2985        1783 :                 rh += roff;
    2986        1783 :                 r = b;
    2987        1783 :                 bat_iterator_end(&ri);
    2988        1782 :                 ri = bat_iterator(r);
    2989        1783 :                 MT_rwlock_rdlock(&r->thashlock);
    2990        1783 :                 hsh = r->thash;
    2991        1783 :                 locked = true;
    2992       14392 :         } else if (hash) {
    2993             :                 /* there is a hash on r which we should use */
    2994       12534 :                 MT_thread_setalgorithm(swapped ? "hashjoin using existing hash (swapped)" : "hashjoin using existing hash");
    2995        7262 :                 MT_rwlock_rdlock(&r->thashlock);
    2996        7263 :                 hsh = r->thash;
    2997        7263 :                 locked = true;
    2998        7263 :                 TRC_DEBUG(ALGO, ALGOBATFMT ": using "
    2999             :                           "existing hash%s\n",
    3000             :                           ALGOBATPAR(r),
    3001             :                           swapped ? " (swapped)" : "");
    3002        7136 :         } else if (BATtdensebi(&ri)) {
    3003             :                 /* no hash, just dense lookup */
    3004           0 :                 MT_thread_setalgorithm(swapped ? "hashjoin on dense (swapped)" : "hashjoin on dense");
    3005             :         } else {
    3006             :                 /* we need to create a hash on r */
    3007        9889 :                 MT_thread_setalgorithm(swapped ? "hashjoin using new hash (swapped)" : "hashjoin using new hash");
    3008        7144 :                 TRC_DEBUG(ALGO, ALGOBATFMT ": creating hash%s\n",
    3009             :                           ALGOBATPAR(r),
    3010             :                           swapped ? " (swapped)" : "");
    3011        7144 :                 if (BAThash(r) != GDK_SUCCEED)
    3012           0 :                         goto bailout;
    3013        7110 :                 MT_rwlock_rdlock(&r->thashlock);
    3014        7141 :                 hsh = r->thash;
    3015        7141 :                 locked = true;
    3016             :         }
    3017       16363 :         if (locked && hsh == NULL) {
    3018           0 :                 GDKerror("Hash disappeared for "ALGOBATFMT"\n", ALGOBATPAR(r));
    3019           0 :                 goto bailout;
    3020             :         }
    3021       16363 :         assert(hsh != NULL || BATtdensebi(&ri));
    3022             :         if (hsh) {
    3023       16363 :                 TRC_DEBUG(ALGO, "hash for " ALGOBATFMT ": nbucket " BUNFMT ", nunique " BUNFMT ", nheads " BUNFMT "\n", ALGOBATPAR(r), hsh->nbucket, hsh->nunique, hsh->nheads);
    3024             :         }
    3025             : 
    3026       16363 :         bit defmark = 0;
    3027       16363 :         if ((not_in || r3p) && !ri.nonil) {
    3028             :                 /* check whether there is a nil on the right, since if
    3029             :                  * so, we should return an empty result if not_in is
    3030             :                  * set, or use a NIL mark for non-matches if r3p is
    3031             :                  * set */
    3032         541 :                 if (hash_cand) {
    3033           0 :                         for (rb = HASHget(hsh, HASHprobe(hsh, nil));
    3034           0 :                              rb != BUN_NONE;
    3035           0 :                              rb = HASHgetlink(hsh, rb)) {
    3036           0 :                                 ro = canditer_idx(rci, rb);
    3037           0 :                                 if ((*cmp)(nil, BUNtail(ri, ro - r->hseqbase)) == 0) {
    3038           0 :                                         assert(!locked);
    3039           0 :                                         if (r3p) {
    3040           0 :                                                 defmark = bit_nil;
    3041           0 :                                                 break;
    3042             :                                         }
    3043           0 :                                         HEAPfree(&hsh->heaplink, true);
    3044           0 :                                         HEAPfree(&hsh->heapbckt, true);
    3045           0 :                                         GDKfree(hsh);
    3046           0 :                                         bat_iterator_end(&li);
    3047           0 :                                         bat_iterator_end(&ri);
    3048           0 :                                         BBPreclaim(b);
    3049           0 :                                         return nomatch(r1p, r2p, r3p, l, r, lci,
    3050             :                                                        bit_nil, false, false,
    3051             :                                                        __func__, t0);
    3052             :                                 }
    3053             :                         }
    3054         541 :                 } else if (!BATtdensebi(&ri)) {
    3055         541 :                         for (rb = HASHget(hsh, HASHprobe(hsh, nil));
    3056       12587 :                              rb != BUN_NONE;
    3057       12045 :                              rb = HASHgetlink(hsh, rb)) {
    3058       12072 :                                 if (rb >= rl && rb < rh &&
    3059       12070 :                                     (cmp == NULL ||
    3060       12071 :                                      (*cmp)(nil, BUNtail(ri, rb)) == 0)) {
    3061          26 :                                         if (r3p) {
    3062          25 :                                                 defmark = bit_nil;
    3063          25 :                                                 break;
    3064             :                                         }
    3065           1 :                                         if (locked)
    3066           1 :                                                 MT_rwlock_rdunlock(&r->thashlock);
    3067           1 :                                         bat_iterator_end(&li);
    3068           1 :                                         bat_iterator_end(&ri);
    3069           1 :                                         BBPreclaim(b);
    3070           1 :                                         return nomatch(r1p, r2p, r3p, l, r, lci,
    3071             :                                                        bit_nil, false, false,
    3072             :                                                        __func__, t0);
    3073             :                                 }
    3074             :                         }
    3075             :                 }
    3076             :         }
    3077             : 
    3078       32639 :         maxsize = joininitresults(r1p, r2p, r3p, lci->ncand, rci->ncand,
    3079       16362 :                                   li.key, ri.key, semi | max_one,
    3080             :                                   nil_on_miss, only_misses, min_one,
    3081             :                                   estimate);
    3082       16277 :         if (maxsize == BUN_NONE) {
    3083           0 :                 goto bailout;
    3084             :         }
    3085             : 
    3086       16277 :         r1 = *r1p;
    3087       16277 :         r2 = r2p ? *r2p : NULL;
    3088       16277 :         r3 = r3p ? *r3p : NULL;
    3089             : 
    3090             :         /* basic properties will be adjusted if necessary later on,
    3091             :          * they were initially set by joininitresults() */
    3092             : 
    3093       16277 :         if (r2) {
    3094       13192 :                 r2->tkey = li.key;
    3095             :                 /* r2 is not likely to be sorted (although it is
    3096             :                  * certainly possible) */
    3097       13192 :                 r2->tsorted = false;
    3098       13192 :                 r2->trevsorted = false;
    3099       13192 :                 r2->tseqbase = oid_nil;
    3100             :         }
    3101             : 
    3102       16277 :         if (lci->tpe != cand_dense)
    3103         394 :                 r1->tseqbase = oid_nil;
    3104             : 
    3105             : 
    3106       16277 :         switch (t) {
    3107       13041 :         case TYPE_int:
    3108   336144799 :                 HASHJOIN(int);
    3109             :                 break;
    3110        1434 :         case TYPE_lng:
    3111   108632482 :                 HASHJOIN(lng);
    3112             :                 break;
    3113           0 :         case TYPE_uuid:
    3114           0 :                 HASHJOIN(uuid);
    3115           0 :                 break;
    3116             :         default:
    3117     2568758 :                 while (lci->next < lci->ncand) {
    3118     2566960 :                         GDK_CHECK_TIMEOUT(qry_ctx, counter,
    3119             :                                         GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    3120     2566960 :                         lo = canditer_next(lci);
    3121     2581445 :                         if (BATtdensebi(&li))
    3122         321 :                                 lval = lo - l->hseqbase + l->tseqbase;
    3123     2581124 :                         else if (li.type != TYPE_void)
    3124     2571234 :                                 v = VALUE(l, lo - l->hseqbase);
    3125     2601408 :                         nr = 0;
    3126     2601408 :                         bit mark = defmark;
    3127     2601408 :                         if ((!nil_matches || not_in) && cmp(v, nil) == 0) {
    3128             :                                 /* no match */
    3129        2980 :                                 if (not_in) {
    3130          10 :                                         lskipped = BATcount(r1) > 0;
    3131          10 :                                         continue;
    3132             :                                 }
    3133        2970 :                                 mark = bit_nil;
    3134     2599171 :                         } else if (hash_cand) {
    3135           0 :                                 for (rb = HASHget(hsh, HASHprobe(hsh, v));
    3136           0 :                                      rb != BUN_NONE;
    3137           0 :                                      rb = HASHgetlink(hsh, rb)) {
    3138           0 :                                         ro = canditer_idx(rci, rb);
    3139           0 :                                         if ((*cmp)(v, BUNtail(ri, ro - r->hseqbase)) != 0)
    3140           0 :                                                 continue;
    3141           0 :                                         if (only_misses) {
    3142           0 :                                                 nr++;
    3143           0 :                                                 break;
    3144             :                                         }
    3145           0 :                                         HASHLOOPBODY();
    3146           0 :                                         if (semi && !max_one)
    3147             :                                                 break;
    3148             :                                 }
    3149     2599171 :                         } else if (hsh == NULL) {
    3150           0 :                                 assert(BATtdensebi(&ri));
    3151           0 :                                 ro = *(const oid *) v;
    3152           0 :                                 if (ro >= r->tseqbase &&
    3153           0 :                                     ro < r->tseqbase + r->batCount) {
    3154           0 :                                         ro -= r->tseqbase;
    3155           0 :                                         ro += rseq;
    3156           0 :                                         if (canditer_contains(rci, ro)) {
    3157           0 :                                                 if (only_misses) {
    3158       16318 :                                                         nr++;
    3159             :                                                         break;
    3160             :                                                 }
    3161           0 :                                                 HASHLOOPBODY();
    3162           0 :                                                 if (semi && !max_one)
    3163             :                                                         break;
    3164             :                                         }
    3165             :                                 }
    3166     2599171 :                         } else if (rci->tpe != cand_dense) {
    3167           0 :                                 for (rb = HASHget(hsh, HASHprobe(hsh, v));
    3168           0 :                                      rb != BUN_NONE;
    3169           0 :                                      rb = HASHgetlink(hsh, rb)) {
    3170           0 :                                         if (rb >= rl && rb < rh &&
    3171           0 :                                             (*(cmp))(v, BUNtail(ri, rb)) == 0 &&
    3172           0 :                                             canditer_contains(rci, ro = (oid) (rb - roff + rseq))) {
    3173           0 :                                                 if (only_misses) {
    3174           0 :                                                         nr++;
    3175           0 :                                                         break;
    3176             :                                                 }
    3177           0 :                                                 HASHLOOPBODY();
    3178           0 :                                                 if (semi && !max_one)
    3179             :                                                         break;
    3180             :                                         }
    3181             :                                 }
    3182             :                         } else {
    3183     2599171 :                                 for (rb = HASHget(hsh, HASHprobe(hsh, v));
    3184     5076257 :                                      rb != BUN_NONE;
    3185     2450393 :                                      rb = HASHgetlink(hsh, rb)) {
    3186     5155142 :                                         if (rb >= rl && rb < rh &&
    3187     2612815 :                                             (*(cmp))(v, BUNtail(ri, rb)) == 0) {
    3188     2200623 :                                                 if (only_misses) {
    3189       57596 :                                                         nr++;
    3190       57596 :                                                         break;
    3191             :                                                 }
    3192     2143027 :                                                 ro = (oid) (rb - roff + rseq);
    3193     2143027 :                                                 HASHLOOPBODY();
    3194     2109320 :                                                 if (semi && !max_one)
    3195             :                                                         break;
    3196             :                                         }
    3197             :                                 }
    3198             :                         }
    3199     2567269 :                         if (nr == 0) {
    3200      391874 :                                 if (only_misses) {
    3201         260 :                                         nr = 1;
    3202         260 :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    3203           0 :                                                 goto bailout;
    3204         260 :                                         APPEND(r1, lo);
    3205         260 :                                         if (lskipped)
    3206         231 :                                                 r1->tseqbase = oid_nil;
    3207      391614 :                                 } else if (nil_on_miss) {
    3208       11547 :                                         nr = 1;
    3209       11547 :                                         if (maybeextend(r1, r2, r3, 1, lci->next, lci->ncand, maxsize) != GDK_SUCCEED)
    3210           0 :                                                 goto bailout;
    3211       11224 :                                         APPEND(r1, lo);
    3212       11224 :                                         if (r2) {
    3213           0 :                                                 r2->tnil = true;
    3214           0 :                                                 r2->tnonil = false;
    3215           0 :                                                 r2->tkey = false;
    3216           0 :                                                 APPEND(r2, oid_nil);
    3217             :                                         }
    3218       11224 :                                         if (r3) {
    3219       11224 :                                                 r3->tnil |= mark == bit_nil;
    3220       11224 :                                                 ((bit *) r3->theap->base)[r3->batCount++] = mark;
    3221             :                                         }
    3222      380067 :                                 } else if (min_one) {
    3223           0 :                                         GDKerror("not enough matches");
    3224           0 :                                         goto bailout;
    3225             :                                 } else {
    3226      380067 :                                         lskipped = BATcount(r1) > 0;
    3227             :                                 }
    3228     2175395 :                         } else if (only_misses) {
    3229       57597 :                                 lskipped = BATcount(r1) > 0;
    3230             :                         } else {
    3231     2117798 :                                 if (lskipped) {
    3232             :                                         /* note, we only get here in an
    3233             :                                          * iteration *after* lskipped was
    3234             :                                          * first set to true, i.e. we did
    3235             :                                          * indeed skip values in l */
    3236     1958815 :                                         r1->tseqbase = oid_nil;
    3237             :                                 }
    3238     2117798 :                                 if (nr > 1) {
    3239        2476 :                                         r1->tkey = false;
    3240        2476 :                                         r1->tseqbase = oid_nil;
    3241             :                                 }
    3242             :                         }
    3243     2566946 :                         if (nr > 0 && BATcount(r1) > nr)
    3244     2166078 :                                 r1->trevsorted = false;
    3245             :                 }
    3246             :                 break;
    3247             :         }
    3248       16318 :         if (locked) {
    3249       16109 :                 locked = false;
    3250       16109 :                 MT_rwlock_rdunlock(&r->thashlock);
    3251             :         }
    3252       16393 :         bat_iterator_end(&li);
    3253       16351 :         bat_iterator_end(&ri);
    3254             : 
    3255       16350 :         if (hash_cand) {
    3256         176 :                 HEAPfree(&hsh->heaplink, true);
    3257         176 :                 HEAPfree(&hsh->heapbckt, true);
    3258         176 :                 GDKfree(hsh);
    3259             :         }
    3260             :         /* also set other bits of heap to correct value to indicate size */
    3261       16350 :         BATsetcount(r1, BATcount(r1));
    3262       16277 :         r1->tunique_est = MIN(l->tunique_est, r->tunique_est);
    3263       16277 :         if (BATcount(r1) <= 1) {
    3264        6349 :                 r1->tsorted = true;
    3265        6349 :                 r1->trevsorted = true;
    3266        6349 :                 r1->tkey = true;
    3267        6349 :                 r1->tseqbase = 0;
    3268             :         }
    3269       16277 :         if (r2) {
    3270       13243 :                 BATsetcount(r2, BATcount(r2));
    3271       13250 :                 assert(BATcount(r1) == BATcount(r2));
    3272       13250 :                 if (BATcount(r2) <= 1) {
    3273        5292 :                         r2->tsorted = true;
    3274        5292 :                         r2->trevsorted = true;
    3275        5292 :                         r2->tkey = true;
    3276        5292 :                         r2->tseqbase = 0;
    3277             :                 }
    3278       19836 :                 r2->tunique_est = MIN(l->tunique_est, r->tunique_est);
    3279             :         }
    3280       16284 :         if (r3) {
    3281          47 :                 r3->tnonil = !r3->tnil;
    3282          47 :                 BATsetcount(r3, BATcount(r3));
    3283          47 :                 assert(BATcount(r1) == BATcount(r3));
    3284          82 :                 r3->tunique_est = MIN(l->tunique_est, r->tunique_est);
    3285             :         }
    3286       16284 :         if (BATcount(r1) > 0) {
    3287       11200 :                 if (BATtdense(r1))
    3288        5759 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    3289       11200 :                 if (r2 && BATtdense(r2))
    3290        1201 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    3291             :         } else {
    3292        5084 :                 r1->tseqbase = 0;
    3293        5084 :                 if (r2) {
    3294        4038 :                         r2->tseqbase = 0;
    3295             :                 }
    3296             :         }
    3297       16284 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT
    3298             :                   ",sl=" ALGOOPTBATFMT "," "sr=" ALGOOPTBATFMT ","
    3299             :                   "nil_matches=%s,nil_on_miss=%s,semi=%s,only_misses=%s,"
    3300             :                   "not_in=%s,max_one=%s,min_one=%s;%s %s -> " ALGOBATFMT "," ALGOOPTBATFMT
    3301             :                   " (" LLFMT "usec)\n",
    3302             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    3303             :                   ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
    3304             :                   nil_matches ? "true" : "false",
    3305             :                   nil_on_miss ? "true" : "false",
    3306             :                   semi ? "true" : "false",
    3307             :                   only_misses ? "true" : "false",
    3308             :                   not_in ? "true" : "false",
    3309             :                   max_one ? "true" : "false",
    3310             :                   min_one ? "true" : "false",
    3311             :                   swapped ? " swapped" : "", reason,
    3312             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    3313             :                   GDKusec() - t0);
    3314             : 
    3315       16284 :         BBPreclaim(b);
    3316             :         return GDK_SUCCEED;
    3317             : 
    3318           4 :   bailout:
    3319           4 :         bat_iterator_end(&li);
    3320           4 :         bat_iterator_end(&ri);
    3321           4 :         if (locked)
    3322           4 :                 MT_rwlock_rdunlock(&r->thashlock);
    3323           4 :         if (hash_cand && hsh) {
    3324           0 :                 HEAPfree(&hsh->heaplink, true);
    3325           0 :                 HEAPfree(&hsh->heapbckt, true);
    3326           0 :                 GDKfree(hsh);
    3327             :         }
    3328           4 :         BBPreclaim(r1);
    3329           4 :         BBPreclaim(r2);
    3330           4 :         BBPreclaim(b);
    3331             :         return GDK_FAIL;
    3332             : }
    3333             : 
    3334             : /* Count the number of unique values for the first half and the complete
    3335             :  * set (the sample s of b) and return the two values in *cnt1 and
    3336             :  * *cnt2. In case of error, both values are 0. */
    3337             : static gdk_return
    3338     1026209 : count_unique(BAT *b, BAT *s, BUN *cnt1, BUN *cnt2)
    3339             : {
    3340     1026209 :         struct canditer ci;
    3341     1026209 :         BUN half;
    3342     1026209 :         BUN cnt = 0;
    3343     1026209 :         const void *v;
    3344     1026209 :         const char *bvals;
    3345     1026209 :         const char *bvars;
    3346     1026209 :         oid bval;
    3347     1026209 :         oid i, o;
    3348     1026209 :         const char *nme;
    3349     1026209 :         BUN hb;
    3350     1026209 :         BATiter bi;
    3351     1026209 :         int (*cmp)(const void *, const void *);
    3352     1026209 :         const char *algomsg = "";
    3353     1026209 :         lng t0 = 0;
    3354             : 
    3355     1026209 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    3356     1026209 :         canditer_init(&ci, b, s);
    3357     1026607 :         half = ci.ncand / 2;
    3358             : 
    3359     1026607 :         MT_lock_set(&b->theaplock);
    3360     1026732 :         if (b->tkey || ci.ncand <= 1 || BATtdense(b)) {
    3361             :                 /* trivial: already unique */
    3362        1418 :                 MT_lock_unset(&b->theaplock);
    3363        1418 :                 *cnt1 = half;
    3364        1418 :                 *cnt2 = ci.ncand;
    3365        1418 :                 return GDK_SUCCEED;
    3366             :         }
    3367     1025314 :         MT_lock_unset(&b->theaplock);
    3368             : 
    3369     1025416 :         (void) BATordered(b);
    3370     1025376 :         (void) BATordered_rev(b);
    3371     1025418 :         bi = bat_iterator(b);
    3372     1025064 :         if ((bi.sorted && bi.revsorted) ||
    3373      972173 :             (bi.type == TYPE_void && is_oid_nil(bi.tseq))) {
    3374             :                 /* trivial: all values are the same */
    3375       52891 :                 *cnt1 = *cnt2 = 1;
    3376       52891 :                 bat_iterator_end(&bi);
    3377       52891 :                 return GDK_SUCCEED;
    3378             :         }
    3379             : 
    3380      972173 :         assert(bi.type != TYPE_void);
    3381             : 
    3382      972173 :         bvals = bi.base;
    3383      972173 :         if (bi.vh && bi.type)
    3384       70198 :                 bvars = bi.vh->base;
    3385             :         else
    3386             :                 bvars = NULL;
    3387      972173 :         cmp = ATOMcompare(bi.type);
    3388             : 
    3389      972173 :         *cnt1 = *cnt2 = 0;
    3390             : 
    3391      972173 :         if (bi.sorted || bi.revsorted) {
    3392             :                 const void *prev = NULL;
    3393     9775645 :                 algomsg = "sorted";
    3394     9775645 :                 for (i = 0; i < ci.ncand; i++) {
    3395     9691849 :                         if (i == half)
    3396       83743 :                                 *cnt1 = cnt;
    3397     9691849 :                         o = canditer_next(&ci);
    3398     9692051 :                         v = VALUE(b, o - b->hseqbase);
    3399     9692051 :                         if (prev == NULL || (*cmp)(v, prev) != 0) {
    3400     4393833 :                                 cnt++;
    3401             :                         }
    3402     9692014 :                         prev = v;
    3403             :                 }
    3404       83796 :                 *cnt2 = cnt;
    3405      888542 :         } else if (ATOMbasetype(bi.type) == TYPE_bte) {
    3406       38894 :                 unsigned char val;
    3407       38894 :                 uint32_t seen[256 / 32];
    3408             : 
    3409       38894 :                 algomsg = "byte-sized atoms";
    3410       38894 :                 assert(bvars == NULL);
    3411       38894 :                 memset(seen, 0, sizeof(seen));
    3412     6019709 :                 for (i = 0; i < ci.ncand; i++) {
    3413     5980736 :                         if (i == ci.ncand/ 2) {
    3414             :                                 cnt = 0;
    3415      349170 :                                 for (int j = 0; j < 256 / 32; j++)
    3416      310192 :                                         cnt += candmask_pop(seen[j]);
    3417       38978 :                                 *cnt1 = cnt;
    3418             :                         }
    3419     5980736 :                         o = canditer_next(&ci);
    3420     5980815 :                         val = ((const unsigned char *) bvals)[o - b->hseqbase];
    3421     5980815 :                         if (!(seen[val >> 5] & (1U << (val & 0x1F)))) {
    3422       97294 :                                 seen[val >> 5] |= 1U << (val & 0x1F);
    3423             :                         }
    3424             :                 }
    3425             :                 cnt = 0;
    3426      349501 :                 for (int j = 0; j < 256 / 32; j++)
    3427      310528 :                         cnt += candmask_pop(seen[j]);
    3428       38973 :                 *cnt2 = cnt;
    3429      849648 :         } else if (ATOMbasetype(bi.type) == TYPE_sht) {
    3430       43825 :                 unsigned short val;
    3431       43825 :                 uint32_t *seen = NULL;
    3432             : 
    3433       43825 :                 algomsg = "short-sized atoms";
    3434       43825 :                 assert(bvars == NULL);
    3435       43825 :                 seen = GDKzalloc((65536 / 32) * sizeof(seen[0]));
    3436       43826 :                 if (seen == NULL) {
    3437           0 :                         bat_iterator_end(&bi);
    3438           0 :                         return GDK_FAIL;
    3439             :                 }
    3440     6827123 :                 for (i = 0; i < ci.ncand; i++) {
    3441     6783297 :                         if (i == half) {
    3442             :                                 cnt = 0;
    3443    89578289 :                                 for (int j = 0; j < 65536 / 32; j++)
    3444    89534464 :                                         cnt += candmask_pop(seen[j]);
    3445       43825 :                                 *cnt1 = cnt;
    3446             :                         }
    3447     6783297 :                         o = canditer_next(&ci);
    3448     6783297 :                         val = ((const unsigned short *) bvals)[o - b->hseqbase];
    3449     6783297 :                         if (!(seen[val >> 5] & (1U << (val & 0x1F)))) {
    3450      133819 :                                 seen[val >> 5] |= 1U << (val & 0x1F);
    3451             :                         }
    3452             :                 }
    3453             :                 cnt = 0;
    3454    89592626 :                 for (int j = 0; j < 65536 / 32; j++)
    3455    89548800 :                         cnt += candmask_pop(seen[j]);
    3456       43826 :                 *cnt2 = cnt;
    3457       43826 :                 GDKfree(seen);
    3458       43826 :                 seen = NULL;
    3459             :         } else {
    3460      805823 :                 BUN prb;
    3461      805823 :                 BUN mask;
    3462      805823 :                 Hash hs = {
    3463             :                         .heapbckt.parentid = b->batCacheid,
    3464      805823 :                         .heaplink.parentid = b->batCacheid,
    3465             :                 };
    3466             : 
    3467      805823 :                 GDKclrerr();    /* not interested in BAThash errors */
    3468      805821 :                 algomsg = "new partial hash";
    3469      805821 :                 nme = BBP_physical(b->batCacheid);
    3470      805821 :                 mask = HASHmask(ci.ncand);
    3471      591752 :                 if (mask < ((BUN) 1 << 16))
    3472      805821 :                         mask = (BUN) 1 << 16;
    3473      805821 :                 if ((hs.heaplink.farmid = BBPselectfarm(TRANSIENT, bi.type, hashheap)) < 0 ||
    3474      805822 :                     (hs.heapbckt.farmid = BBPselectfarm(TRANSIENT, bi.type, hashheap)) < 0 ||
    3475      805824 :                     snprintf(hs.heaplink.filename, sizeof(hs.heaplink.filename), "%s.thshjnl%x", nme, (unsigned) MT_getpid()) >= (int) sizeof(hs.heaplink.filename) ||
    3476     1611638 :                     snprintf(hs.heapbckt.filename, sizeof(hs.heapbckt.filename), "%s.thshjnb%x", nme, (unsigned) MT_getpid()) >= (int) sizeof(hs.heapbckt.filename) ||
    3477      805824 :                     HASHnew(&hs, bi.type, ci.ncand, mask, BUN_NONE, false) != GDK_SUCCEED) {
    3478           4 :                         GDKerror("cannot allocate hash table\n");
    3479           0 :                         HEAPfree(&hs.heaplink, true);
    3480           0 :                         HEAPfree(&hs.heapbckt, true);
    3481           0 :                         bat_iterator_end(&bi);
    3482           0 :                         return GDK_FAIL;
    3483             :                 }
    3484   406310704 :                 for (i = 0; i < ci.ncand; i++) {
    3485   405504883 :                         if (i == half)
    3486      805820 :                                 *cnt1 = cnt;
    3487   405504883 :                         o = canditer_next(&ci);
    3488   405500045 :                         v = VALUE(b, o - b->hseqbase);
    3489   405500102 :                         prb = HASHprobe(&hs, v);
    3490   405514433 :                         for (hb = HASHget(&hs, prb);
    3491   405521773 :                              hb != BUN_NONE;
    3492        7340 :                              hb = HASHgetlink(&hs, hb)) {
    3493   240604629 :                                 BUN p = canditer_idx(&ci, hb) - b->hseqbase;
    3494   240627000 :                                 if (cmp(v, BUNtail(bi, p)) == 0)
    3495             :                                         break;
    3496             :                         }
    3497   405499791 :                         if (hb == BUN_NONE) {
    3498   164906247 :                                 cnt++;
    3499             :                                 /* enter into hash table */
    3500   164906247 :                                 HASHputlink(&hs, i, HASHget(&hs, prb));
    3501   164913693 :                                 HASHput(&hs, prb, i);
    3502             :                         }
    3503             :                 }
    3504      805821 :                 *cnt2 = cnt;
    3505      805821 :                 HEAPfree(&hs.heaplink, true);
    3506      805822 :                 HEAPfree(&hs.heapbckt, true);
    3507             :         }
    3508      972419 :         bat_iterator_end(&bi);
    3509             : 
    3510      972224 :         TRC_DEBUG(ALGO, "b=" ALGOBATFMT ",s=" ALGOOPTBATFMT
    3511             :                   " -> " BUNFMT " " BUNFMT " (%s -- " LLFMT "usec)\n",
    3512             :                   ALGOBATPAR(b), ALGOOPTBATPAR(s),
    3513             :                   *cnt1, *cnt2, algomsg, GDKusec() - t0);
    3514             : 
    3515             :         return GDK_SUCCEED;
    3516             : }
    3517             : 
    3518             : static double
    3519     1999674 : guess_uniques(BAT *b, struct canditer *ci)
    3520             : {
    3521     1999674 :         BUN cnt1, cnt2;
    3522     1999674 :         BAT *s1;
    3523             : 
    3524     1999674 :         MT_lock_set(&b->theaplock);
    3525     2000602 :         bool key = b->tkey;
    3526     2000602 :         double unique_est = b->tunique_est;
    3527     2000602 :         BUN batcount = BATcount(b);
    3528     2000602 :         MT_lock_unset(&b->theaplock);
    3529     2000769 :         if (key)
    3530      973808 :                 return (double) ci->ncand;
    3531             : 
    3532     1026961 :         if (ci->s == NULL ||
    3533           0 :             (ci->tpe == cand_dense && ci->ncand == batcount)) {
    3534     1026961 :                 if (unique_est != 0) {
    3535         190 :                         TRC_DEBUG(ALGO, "b=" ALGOBATFMT " use cached value\n",
    3536             :                                   ALGOBATPAR(b));
    3537         190 :                         return unique_est;
    3538             :                 }
    3539     1026771 :                 s1 = BATsample(b, 1000);
    3540             :         } else {
    3541           0 :                 BAT *s2 = BATsample(ci->s, 1000);
    3542           0 :                 if (s2 == NULL)
    3543             :                         return -1;
    3544           0 :                 s1 = BATproject(s2, ci->s);
    3545           0 :                 BBPreclaim(s2);
    3546             :         }
    3547     1026379 :         if (s1 == NULL)
    3548             :                 return -1;
    3549     1026379 :         BUN n2 = BATcount(s1);
    3550     1026379 :         BUN n1 = n2 / 2;
    3551     1026379 :         if (count_unique(b, s1, &cnt1, &cnt2) != GDK_SUCCEED) {
    3552           0 :                 BBPreclaim(s1);
    3553           0 :                 return -1;
    3554             :         }
    3555     1026495 :         BBPreclaim(s1);
    3556             : 
    3557     1026699 :         double A = (double) (cnt2 - cnt1) / (n2 - n1);
    3558     1026699 :         double B = cnt1 - n1 * A;
    3559             : 
    3560     1026699 :         B += A * ci->ncand;
    3561     1026699 :         MT_lock_set(&b->theaplock);
    3562     1026638 :         if (ci->s == NULL ||
    3563           0 :             (ci->tpe == cand_dense && ci->ncand == BATcount(b) && ci->ncand == batcount)) {
    3564     1026638 :                 if (b->tunique_est == 0)
    3565     1024243 :                         b->tunique_est = B;
    3566             :         }
    3567     1026638 :         MT_lock_unset(&b->theaplock);
    3568     1026671 :         return B;
    3569             : }
    3570             : 
    3571             : BUN
    3572     1224364 : BATguess_uniques(BAT *b, struct canditer *ci)
    3573             : {
    3574     1224364 :         struct canditer lci;
    3575     1224364 :         if (ci == NULL) {
    3576     1224630 :                 canditer_init(&lci, b, NULL);
    3577     1224630 :                 ci = &lci;
    3578             :         }
    3579     1224637 :         return (BUN) guess_uniques(b, ci);
    3580             : }
    3581             : 
    3582             : /* estimate the cost of doing a hashjoin with a hash on r; return value
    3583             :  * is the estimated cost, the last three arguments receive some extra
    3584             :  * information */
    3585             : double
    3586     1443461 : joincost(BAT *r, BUN lcount, struct canditer *rci,
    3587             :          bool *hash, bool *phash, bool *cand)
    3588             : {
    3589     1443461 :         bool rhash;
    3590     1443461 :         bool prhash = false;
    3591     1443461 :         bool rcand = false;
    3592     1443461 :         double rcost = 1;
    3593     1443461 :         bat parent;
    3594     1443461 :         BAT *b;
    3595     1443461 :         BUN nheads;
    3596     1443461 :         BUN cnt;
    3597             : 
    3598     1443461 :         (void) BATcheckhash(r);
    3599     1444125 :         MT_rwlock_rdlock(&r->thashlock);
    3600     1444481 :         rhash = r->thash != NULL;
    3601     1444481 :         nheads = r->thash ? r->thash->nheads : 0;
    3602     1444481 :         cnt = BATcount(r);
    3603     1444481 :         MT_rwlock_rdunlock(&r->thashlock);
    3604             : 
    3605     1443307 :         if ((rci->tpe == cand_materialized || rci->tpe == cand_except) &&
    3606      316258 :             rci->nvals > 0) {
    3607             :                 /* if we need to do binary search on candidate list,
    3608             :                  * take that into account; note checking the other
    3609             :                  * candidate types is essentially free */
    3610      316269 :                 rcost += log2((double) rci->nvals);
    3611             :         }
    3612     1443307 :         rcost *= lcount;
    3613     1443307 :         if (BATtdense(r)) {
    3614             :                 /* no need for a hash, and lookup is free */
    3615             :                 rhash = false;  /* don't use it, even if it's there */
    3616             :         } else {
    3617     1443306 :                 if (rhash) {
    3618             :                         /* average chain length */
    3619        9724 :                         rcost *= (double) cnt / nheads;
    3620     1433582 :                 } else if ((parent = VIEWtparent(r)) != 0 &&
    3621     1305174 :                            (b = BATdescriptor(parent)) != NULL) {
    3622     1305668 :                         if (BATcheckhash(b)) {
    3623       67759 :                                 MT_rwlock_rdlock(&b->thashlock);
    3624       67753 :                                 rhash = prhash = b->thash != NULL;
    3625       67753 :                                 if (rhash) {
    3626             :                                         /* average chain length */
    3627       67753 :                                         rcost *= (double) BATcount(b) / b->thash->nheads;
    3628             :                                 }
    3629       67753 :                                 MT_rwlock_rdunlock(&b->thashlock);
    3630             :                         }
    3631     1305635 :                         BBPunfix(b->batCacheid);
    3632             :                 }
    3633     1443791 :                 if (!rhash) {
    3634     1366425 :                         MT_lock_set(&r->theaplock);
    3635     1366963 :                         double unique_est = r->tunique_est;
    3636     1366963 :                         MT_lock_unset(&r->theaplock);
    3637     1367189 :                         if (unique_est == 0) {
    3638      775498 :                                 unique_est = guess_uniques(r, &(struct canditer){.tpe=cand_dense, .ncand=BATcount(r)});
    3639      775434 :                                 if (unique_est < 0)
    3640           0 :                                         return -1;
    3641             :                         }
    3642             :                         /* we have an estimate of the number of unique
    3643             :                          * values, assume some collisions */
    3644     1367125 :                         rcost *= 1.1 * ((double) cnt / unique_est);
    3645             :                         /* only count the cost of creating the hash for
    3646             :                          * non-persistent bats */
    3647     1367125 :                         MT_lock_set(&r->theaplock);
    3648     1366959 :                         if (r->batRole != PERSISTENT /* || r->theap->dirty */ || GDKinmemory(r->theap->farmid))
    3649     1339189 :                                 rcost += cnt * 2.0;
    3650     1366959 :                         MT_lock_unset(&r->theaplock);
    3651             :                 }
    3652             :         }
    3653     1444544 :         if (cand) {
    3654       34929 :                 if (rci->ncand != BATcount(r) && rci->tpe != cand_mask) {
    3655             :                         /* instead of using the hash on r (cost in
    3656             :                          * rcost), we can build a new hash on r taking
    3657             :                          * the candidate list into account; don't do
    3658             :                          * this for masked candidate since the searching
    3659             :                          * of the candidate list (canditer_idx) will
    3660             :                          * kill us */
    3661        2181 :                         double rccost;
    3662        2181 :                         if (rhash && !prhash) {
    3663         826 :                                 rccost = (double) cnt / nheads;
    3664             :                         } else {
    3665        1355 :                                 MT_lock_set(&r->theaplock);
    3666        1355 :                                 double unique_est = r->tunique_est;
    3667        1355 :                                 MT_lock_unset(&r->theaplock);
    3668        1355 :                                 if (unique_est == 0) {
    3669          83 :                                         unique_est = guess_uniques(r, rci);
    3670          83 :                                         if (unique_est < 0)
    3671             :                                                 return -1;
    3672             :                                 }
    3673             :                                 /* we have an estimate of the number of unique
    3674             :                                  * values, assume some chains */
    3675        1355 :                                 rccost = 1.1 * ((double) cnt / unique_est);
    3676             :                         }
    3677        2181 :                         rccost *= lcount;
    3678        2181 :                         rccost += rci->ncand * 2.0; /* cost of building the hash */
    3679        2181 :                         if (rccost < rcost) {
    3680       34929 :                                 rcost = rccost;
    3681       34929 :                                 rcand = true;
    3682             :                         }
    3683             :                 }
    3684       34929 :                 *cand = rcand;
    3685             :         }
    3686     1444544 :         *hash = rhash;
    3687     1444544 :         *phash = prhash;
    3688     1444544 :         return rcost;
    3689             : }
    3690             : 
    3691             : #define MASK_EQ         1
    3692             : #define MASK_LT         2
    3693             : #define MASK_GT         4
    3694             : #define MASK_LE         (MASK_EQ | MASK_LT)
    3695             : #define MASK_GE         (MASK_EQ | MASK_GT)
    3696             : #define MASK_NE         (MASK_LT | MASK_GT)
    3697             : 
    3698             : static gdk_return
    3699       50782 : thetajoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, int opcode,
    3700             :           BUN estimate, bool nil_matches, const char *reason, lng t0)
    3701             : {
    3702       50782 :         struct canditer lci, rci;
    3703       50782 :         const char *lvals, *rvals;
    3704       50782 :         const char *lvars, *rvars;
    3705       50782 :         const void *nil = ATOMnilptr(l->ttype);
    3706       50782 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    3707       50782 :         const void *vl, *vr;
    3708       50782 :         oid lastr = 0;          /* last value inserted into r2 */
    3709       50782 :         BUN nr;
    3710       50782 :         oid lo, ro;
    3711       50782 :         int c;
    3712       50782 :         bool lskipped = false;  /* whether we skipped values in l */
    3713       50782 :         lng loff = 0, roff = 0;
    3714       50782 :         oid lval = oid_nil, rval = oid_nil;
    3715             : 
    3716       50782 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    3717             : 
    3718      152335 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    3719       50777 :         assert((opcode & (MASK_EQ | MASK_LT | MASK_GT)) != 0);
    3720             : 
    3721       50777 :         BATiter li = bat_iterator(l);
    3722       50898 :         BATiter ri = bat_iterator(r);
    3723             : 
    3724       50901 :         canditer_init(&lci, l, sl);
    3725       50852 :         canditer_init(&rci, r, sr);
    3726             : 
    3727       50733 :         lvals = BATtvoid(l) ? NULL : (const char *) li.base;
    3728       50733 :         rvals = BATtvoid(r) ? NULL : (const char *) ri.base;
    3729       50733 :         if (li.vh && li.type) {
    3730          16 :                 assert(ri.vh && ri.type);
    3731          16 :                 lvars = li.vh->base;
    3732          16 :                 rvars = ri.vh->base;
    3733             :         } else {
    3734       50717 :                 assert(ri.vh == NULL);
    3735             :                 lvars = rvars = NULL;
    3736             :         }
    3737             : 
    3738       50733 :         if (BATtvoid(l)) {
    3739           0 :                 if (!BATtdensebi(&li)) {
    3740           0 :                         if (!nil_matches) {
    3741             :                                 /* trivial: nils don't match anything */
    3742           0 :                                 bat_iterator_end(&li);
    3743           0 :                                 bat_iterator_end(&ri);
    3744           0 :                                 return nomatch(r1p, r2p, NULL, l, r, &lci,
    3745             :                                                0, false, false, __func__, t0);
    3746             :                         }
    3747             :                 } else {
    3748           0 :                         loff = (lng) l->tseqbase - (lng) l->hseqbase;
    3749             :                 }
    3750             :         }
    3751       50733 :         if (BATtvoid(r)) {
    3752           1 :                 if (!BATtdensebi(&ri)) {
    3753           0 :                         if (!nil_matches) {
    3754             :                                 /* trivial: nils don't match anything */
    3755           0 :                                 bat_iterator_end(&li);
    3756           0 :                                 bat_iterator_end(&ri);
    3757           0 :                                 return nomatch(r1p, r2p, NULL, l, r, &lci,
    3758             :                                                0, false, false, __func__, t0);
    3759             :                         }
    3760             :                 } else {
    3761           1 :                         roff = (lng) r->tseqbase - (lng) r->hseqbase;
    3762             :                 }
    3763             :         }
    3764             : 
    3765       50733 :         BUN maxsize = joininitresults(r1p, r2p, NULL, lci.ncand, rci.ncand, false, false,
    3766             :                                       false, false, false, false, estimate);
    3767       49994 :         if (maxsize == BUN_NONE) {
    3768           0 :                 bat_iterator_end(&li);
    3769           0 :                 bat_iterator_end(&ri);
    3770           0 :                 return GDK_FAIL;
    3771             :         }
    3772       49994 :         BAT *r1 = *r1p;
    3773       49994 :         BAT *r2 = r2p ? *r2p : NULL;
    3774             : 
    3775       49994 :         r1->tkey = true;
    3776       49994 :         r1->tsorted = true;
    3777       49994 :         r1->trevsorted = true;
    3778       49994 :         if (r2) {
    3779        8214 :                 r2->tkey = true;
    3780        8214 :                 r2->tsorted = true;
    3781        8214 :                 r2->trevsorted = true;
    3782             :         }
    3783             : 
    3784             :         /* nested loop implementation for theta join */
    3785             :         vl = &lval;
    3786             :         vr = &rval;
    3787      347337 :         for (BUN lidx = 0; lidx < lci.ncand; lidx++) {
    3788      296850 :                 lo = canditer_next(&lci);
    3789      285535 :                 if (lvals)
    3790      285535 :                         vl = VALUE(l, lo - l->hseqbase);
    3791           0 :                 else if (BATtdensebi(&li))
    3792           0 :                         lval = (oid) ((lng) lo + loff);
    3793      285535 :                 nr = 0;
    3794      285535 :                 if (nil_matches || cmp(vl, nil) != 0) {
    3795      278724 :                         canditer_reset(&rci);
    3796     3565237 :                         TIMEOUT_LOOP(rci.ncand, qry_ctx) {
    3797     3018588 :                                 ro = canditer_next(&rci);
    3798     2951691 :                                 if (rvals)
    3799     2951687 :                                         vr = VALUE(r, ro - r->hseqbase);
    3800           4 :                                 else if (BATtdensebi(&ri))
    3801           4 :                                         rval = (oid) ((lng) ro + roff);
    3802     2951691 :                                 if (!nil_matches && cmp(vr, nil) == 0)
    3803       59283 :                                         continue;
    3804     2886691 :                                 c = cmp(vl, vr);
    3805     2924854 :                                 if (!((opcode & MASK_LT && c < 0) ||
    3806     2725634 :                                       (opcode & MASK_GT && c > 0) ||
    3807     1478866 :                                       (opcode & MASK_EQ && c == 0)))
    3808     1478842 :                                         continue;
    3809     1446012 :                                 if (maybeextend(r1, r2, NULL, 1, lci.next, lci.ncand, maxsize) != GDK_SUCCEED)
    3810           0 :                                         goto bailout;
    3811     1472740 :                                 if (BATcount(r1) > 0) {
    3812     1453227 :                                         if (r2 && lastr + 1 != ro)
    3813       53535 :                                                 r2->tseqbase = oid_nil;
    3814     1453227 :                                         if (nr == 0) {
    3815      151101 :                                                 r1->trevsorted = false;
    3816      151101 :                                                 if (r2 == NULL) {
    3817             :                                                         /* nothing */
    3818       43826 :                                                 } else if (lastr > ro) {
    3819       40400 :                                                         r2->tsorted = false;
    3820       40400 :                                                         r2->tkey = false;
    3821        3426 :                                                 } else if (lastr < ro) {
    3822           0 :                                                         r2->trevsorted = false;
    3823             :                                                 } else {
    3824        3426 :                                                         r2->tkey = false;
    3825             :                                                 }
    3826             :                                         }
    3827             :                                 }
    3828     1472740 :                                 APPEND(r1, lo);
    3829     1472740 :                                 if (r2) {
    3830     1198895 :                                         APPEND(r2, ro);
    3831             :                                 }
    3832     1472740 :                                 lastr = ro;
    3833     1472740 :                                 nr++;
    3834             :                         }
    3835      275775 :                         TIMEOUT_CHECK(qry_ctx,
    3836             :                                       GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    3837             :                 }
    3838      297343 :                 if (nr > 1) {
    3839      144527 :                         r1->tkey = false;
    3840      144527 :                         r1->tseqbase = oid_nil;
    3841      144527 :                         if (r2) {
    3842       46806 :                                 r2->trevsorted = false;
    3843             :                         }
    3844      152816 :                 } else if (nr == 0) {
    3845      119697 :                         lskipped = BATcount(r1) > 0;
    3846       33119 :                 } else if (lskipped) {
    3847       20928 :                         r1->tseqbase = oid_nil;
    3848             :                 }
    3849             :         }
    3850             :         /* also set other bits of heap to correct value to indicate size */
    3851       50487 :         BATsetcount(r1, BATcount(r1));
    3852       50329 :         if (r2) {
    3853        8280 :                 BATsetcount(r2, BATcount(r2));
    3854        8327 :                 assert(BATcount(r1) == BATcount(r2));
    3855             :         }
    3856       50376 :         if (BATcount(r1) > 0) {
    3857       25387 :                 if (BATtdense(r1))
    3858        1220 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    3859       25387 :                 if (r2 && BATtdense(r2))
    3860        1006 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    3861             :         } else {
    3862       24989 :                 r1->tseqbase = 0;
    3863       24989 :                 if (r2) {
    3864        1640 :                         r2->tseqbase = 0;
    3865             :                 }
    3866             :         }
    3867       50376 :         bat_iterator_end(&li);
    3868       50709 :         bat_iterator_end(&ri);
    3869       49786 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT
    3870             :                   ",sl=" ALGOOPTBATFMT "," "sr=" ALGOOPTBATFMT ","
    3871             :                   "opcode=%s%s%s; %s -> " ALGOBATFMT "," ALGOOPTBATFMT
    3872             :                   " (" LLFMT "usec)\n",
    3873             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    3874             :                   ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    3875             :                   opcode & MASK_LT ? "<" : "",
    3876             :                   opcode & MASK_GT ? ">" : "",
    3877             :                   opcode & MASK_EQ ? "=" : "",
    3878             :                   reason,
    3879             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    3880             :                   GDKusec() - t0);
    3881             :         return GDK_SUCCEED;
    3882             : 
    3883           0 :   bailout:
    3884           0 :         bat_iterator_end(&li);
    3885           0 :         bat_iterator_end(&ri);
    3886           0 :         BBPreclaim(r1);
    3887           0 :         BBPreclaim(r2);
    3888             :         return GDK_FAIL;
    3889             : }
    3890             : 
    3891             : /* small ordered right, dense left, oid's only, do fetches */
    3892             : static gdk_return
    3893           0 : fetchjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    3894             :           struct canditer *restrict lci, struct canditer *restrict rci,
    3895             :           const char *reason, lng t0)
    3896             : {
    3897           0 :         oid lo = lci->seq - l->hseqbase + l->tseqbase, hi = lo + lci->ncand;
    3898           0 :         BUN b, e, p;
    3899           0 :         BAT *r1, *r2 = NULL;
    3900             : 
    3901           0 :         MT_thread_setalgorithm(__func__);
    3902           0 :         if (r->tsorted) {
    3903           0 :                 b = SORTfndfirst(r, &lo);
    3904           0 :                 e = SORTfndfirst(r, &hi);
    3905             :         } else {
    3906           0 :                 assert(r->trevsorted);
    3907           0 :                 b = SORTfndlast(r, &hi);
    3908           0 :                 e = SORTfndlast(r, &lo);
    3909             :         }
    3910           0 :         if (b < rci->seq - r->hseqbase)
    3911             :                 b = rci->seq - r->hseqbase;
    3912           0 :         if (e > rci->seq + rci->ncand - r->hseqbase)
    3913             :                 e = rci->seq + rci->ncand - r->hseqbase;
    3914           0 :         if (e == b) {
    3915           0 :                 return nomatch(r1p, r2p, NULL, l, r, lci,
    3916             :                                0, false, false, __func__, t0);
    3917             :         }
    3918           0 :         r1 = COLnew(0, TYPE_oid, e - b, TRANSIENT);
    3919           0 :         if (r1 == NULL)
    3920             :                 return GDK_FAIL;
    3921           0 :         if (r2p) {
    3922           0 :                 if ((r2 = BATdense(0, r->hseqbase + b, e - b)) == NULL) {
    3923           0 :                         BBPreclaim(r1);
    3924           0 :                         return GDK_FAIL;
    3925             :                 }
    3926           0 :                 *r2p = r2;
    3927             :         }
    3928           0 :         *r1p = r1;
    3929           0 :         oid *op = (oid *) Tloc(r1, 0);
    3930           0 :         BATiter ri = bat_iterator(r);
    3931           0 :         const oid *rp = (const oid *) ri.base;
    3932           0 :         for (p = b; p < e; p++) {
    3933           0 :                 *op++ = rp[p] + l->hseqbase - l->tseqbase;
    3934             :         }
    3935           0 :         BATsetcount(r1, e - b);
    3936           0 :         r1->tkey = ri.key;
    3937           0 :         r1->tsorted = ri.sorted || e - b <= 1;
    3938           0 :         r1->trevsorted = ri.revsorted || e - b <= 1;
    3939           0 :         r1->tseqbase = e == b ? 0 : e - b == 1 ? *(const oid *)Tloc(r1, 0) : oid_nil;
    3940           0 :         bat_iterator_end(&ri);
    3941           0 :         TRC_DEBUG(ALGO, "%s(l=" ALGOBATFMT ","
    3942             :                   "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    3943             :                   "sr=" ALGOOPTBATFMT ") %s "
    3944             :                   "-> (" ALGOBATFMT "," ALGOOPTBATFMT ") " LLFMT "us\n",
    3945             :                   __func__,
    3946             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    3947             :                   ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    3948             :                   reason,
    3949             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    3950             :                   GDKusec() - t0);
    3951             : 
    3952             :         return GDK_SUCCEED;
    3953             : }
    3954             : 
    3955             : static BAT *
    3956        5080 : bitmaskjoin(BAT *l, BAT *r,
    3957             :             struct canditer *restrict lci, struct canditer *restrict rci,
    3958             :             bool only_misses,
    3959             :             const char *reason, lng t0)
    3960             : {
    3961        5080 :         BAT *r1;
    3962        5080 :         size_t nmsk = (lci->ncand + 31) / 32;
    3963        5080 :         uint32_t *mask = GDKzalloc(nmsk * sizeof(uint32_t));
    3964        5089 :         BUN cnt = 0;
    3965             : 
    3966        5089 :         MT_thread_setalgorithm(__func__);
    3967        5083 :         if (mask == NULL)
    3968             :                 return NULL;
    3969             : 
    3970    21209631 :         for (BUN n = 0; n < rci->ncand; n++) {
    3971    21204542 :                 oid o = canditer_next(rci) - r->hseqbase;
    3972    21206213 :                 o = BUNtoid(r, o);
    3973    21204548 :                 if (is_oid_nil(o))
    3974           0 :                         continue;
    3975    21204548 :                 o += l->hseqbase;
    3976    21204548 :                 if (o < lci->seq + l->tseqbase)
    3977           2 :                         continue;
    3978    21204546 :                 o -= lci->seq + l->tseqbase;
    3979    21204546 :                 if (o >= lci->ncand)
    3980           0 :                         continue;
    3981    21204546 :                 if ((mask[o >> 5] & (1U << (o & 0x1F))) == 0) {
    3982    15890805 :                         cnt++;
    3983    15890805 :                         mask[o >> 5] |= 1U << (o & 0x1F);
    3984             :                 }
    3985             :         }
    3986        5089 :         if (only_misses)
    3987        3585 :                 cnt = lci->ncand - cnt;
    3988        5089 :         if (cnt == 0 || cnt == lci->ncand) {
    3989        1473 :                 GDKfree(mask);
    3990        1473 :                 if (cnt == 0)
    3991         321 :                         return BATdense(0, 0, 0);
    3992        1152 :                 return BATdense(0, lci->seq, lci->ncand);
    3993             :         }
    3994        3616 :         r1 = COLnew(0, TYPE_oid, cnt, TRANSIENT);
    3995        3616 :         if (r1 != NULL) {
    3996        3616 :                 oid *r1p = Tloc(r1, 0);
    3997             : 
    3998        3616 :                 r1->tkey = true;
    3999        3616 :                 r1->tnil = false;
    4000        3616 :                 r1->tnonil = true;
    4001        3616 :                 r1->tsorted = true;
    4002        3616 :                 r1->trevsorted = cnt <= 1;
    4003        3616 :                 if (only_misses) {
    4004             :                         /* set the bits for unused values at the
    4005             :                          * end so that we don't need special
    4006             :                          * code in the loop */
    4007        3264 :                         if (lci->ncand & 0x1F)
    4008        3201 :                                 mask[nmsk - 1] |= ~0U << (lci->ncand & 0x1F);
    4009     1852644 :                         for (size_t i = 0; i < nmsk; i++)
    4010     1849380 :                                 if (mask[i] != ~0U)
    4011    58340172 :                                         for (uint32_t j = 0; j < 32; j++)
    4012    56572288 :                                                 if ((mask[i] & (1U << j)) == 0)
    4013    50349925 :                                                         *r1p++ = i * 32 + j + lci->seq;
    4014             :                 } else {
    4015      306289 :                         for (size_t i = 0; i < nmsk; i++)
    4016      305937 :                                 if (mask[i] != 0U)
    4017     7713849 :                                         for (uint32_t j = 0; j < 32; j++)
    4018     7480096 :                                                 if ((mask[i] & (1U << j)) != 0)
    4019     6730336 :                                                         *r1p++ = i * 32 + j + lci->seq;
    4020             :                 }
    4021        3616 :                 BATsetcount(r1, cnt);
    4022        3616 :                 assert((BUN) (r1p - (oid*) Tloc(r1, 0)) == BATcount(r1));
    4023             : 
    4024        3616 :                 TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
    4025             :                           "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    4026             :                           "sr=" ALGOOPTBATFMT ",only_misses=%s; %s "
    4027             :                           "-> " ALGOBATFMT " (" LLFMT "usec)\n",
    4028             :                           ALGOBATPAR(l), ALGOBATPAR(r),
    4029             :                           ALGOOPTBATPAR(lci->s), ALGOOPTBATPAR(rci->s),
    4030             :                           only_misses ? "true" : "false",
    4031             :                           reason,
    4032             :                           ALGOBATPAR(r1),
    4033             :                           GDKusec() - t0);
    4034             :         }
    4035        3616 :         GDKfree(mask);
    4036        3616 :         return r1;
    4037             : }
    4038             : 
    4039             : /* Make the implementation choices for various left joins.
    4040             :  * If r3p is set, this is a "mark join" and *r3p will be a third return value containing a bat with type msk with a bit set for each
    4041             :  * nil_matches: nil is an ordinary value that can match;
    4042             :  * nil_on_miss: outer join: fill in a nil value in case of no match;
    4043             :  * semi: semi join: return one of potentially more than one matches;
    4044             :  * only_misses: difference: list rows without match on the right;
    4045             :  * not_in: for implementing NOT IN: if nil on right then there are no matches;
    4046             :  * max_one: error if there is more than one match;
    4047             :  * min_one: error if there are no matches. */
    4048             : static gdk_return
    4049      125993 : leftjoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4050             :          bool nil_matches, bool nil_on_miss, bool semi, bool only_misses,
    4051             :          bool not_in, bool max_one, bool min_one, BUN estimate,
    4052             :          const char *func, lng t0)
    4053             : {
    4054      125993 :         struct canditer lci, rci;
    4055      125993 :         bool rhash, prhash, rcand;
    4056      125993 :         bat parent;
    4057      125993 :         double rcost = 0;
    4058      125993 :         gdk_return rc;
    4059      125993 :         BAT *lp = NULL;
    4060      125993 :         BAT *rp = NULL;
    4061             : 
    4062      125993 :         MT_thread_setalgorithm(__func__);
    4063             :         /* only_misses implies left output only */
    4064      125954 :         assert(!only_misses || r2p == NULL);
    4065             :         /* if nil_on_miss is set, we really need a right output */
    4066      125954 :         assert(!nil_on_miss || r2p != NULL || r3p != NULL);
    4067             :         /* if not_in is set, then so is only_misses */
    4068      125954 :         assert(!not_in || only_misses);
    4069             :         /* if r3p is set, then so is nil_on_miss */
    4070      125954 :         assert(r3p == NULL || nil_on_miss);
    4071      125954 :         *r1p = NULL;
    4072      125954 :         if (r2p)
    4073         869 :                 *r2p = NULL;
    4074      125954 :         if (r3p)
    4075        4221 :                 *r3p = NULL;
    4076             : 
    4077      125954 :         canditer_init(&lci, l, sl);
    4078      126418 :         canditer_init(&rci, r, sr);
    4079             : 
    4080      126412 :         if ((parent = VIEWtparent(l)) != 0) {
    4081        3707 :                 lp = BATdescriptor(parent);
    4082        3710 :                 if (lp == NULL)
    4083             :                         return GDK_FAIL;
    4084        3710 :                 if (l->hseqbase == lp->hseqbase &&
    4085        4443 :                     BATcount(l) == BATcount(lp) &&
    4086        3248 :                     ATOMtype(l->ttype) == ATOMtype(lp->ttype)) {
    4087             :                         l = lp;
    4088             :                 } else {
    4089        2086 :                         BBPunfix(lp->batCacheid);
    4090        2086 :                         lp = NULL;
    4091             :                 }
    4092             :         }
    4093      126415 :         if ((parent = VIEWtparent(r)) != 0) {
    4094        3955 :                 rp = BATdescriptor(parent);
    4095        3956 :                 if (rp == NULL) {
    4096           0 :                         BBPreclaim(lp);
    4097           0 :                         return GDK_FAIL;
    4098             :                 }
    4099        3956 :                 if (r->hseqbase == rp->hseqbase &&
    4100        6661 :                     BATcount(r) == BATcount(rp) &&
    4101        5410 :                     ATOMtype(r->ttype) == ATOMtype(rp->ttype)) {
    4102             :                         r = rp;
    4103             :                 } else {
    4104        1253 :                         BBPunfix(rp->batCacheid);
    4105        1253 :                         rp = NULL;
    4106             :                 }
    4107             :         }
    4108             : 
    4109      126417 :         if (l->ttype == TYPE_msk || mask_cand(l)) {
    4110           5 :                 l = BATunmask(l);
    4111           5 :                 BBPreclaim(lp);
    4112           5 :                 if (l == NULL) {
    4113           0 :                         BBPreclaim(rp);
    4114           0 :                         return GDK_FAIL;
    4115             :                 }
    4116             :                 lp = l;
    4117             :         }
    4118      126417 :         if (r->ttype == TYPE_msk || mask_cand(r)) {
    4119          66 :                 r = BATunmask(r);
    4120          66 :                 BBPreclaim(rp);
    4121          66 :                 if (r == NULL) {
    4122           0 :                         BBPreclaim(lp);
    4123           0 :                         return GDK_FAIL;
    4124             :                 }
    4125             :                 rp = r;
    4126             :         }
    4127             : 
    4128      126417 :         if (joinparamcheck(l, r, NULL, sl, sr, func) != GDK_SUCCEED) {
    4129           0 :                 rc = GDK_FAIL;
    4130           0 :                 goto doreturn;
    4131             :         }
    4132             : 
    4133      126203 :         if (lci.ncand == 0 || rci.ncand == 0) {
    4134       89476 :                 TRC_DEBUG(ALGO, "%s(l=" ALGOBATFMT ","
    4135             :                           "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    4136             :                           "sr=" ALGOOPTBATFMT ",nil_matches=%d,"
    4137             :                           "nil_on_miss=%d,semi=%d,only_misses=%d,"
    4138             :                           "not_in=%d,max_one=%d,min_one=%d)\n",
    4139             :                           func,
    4140             :                           ALGOBATPAR(l), ALGOBATPAR(r),
    4141             :                           ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    4142             :                           nil_matches, nil_on_miss, semi, only_misses,
    4143             :                           not_in, max_one, min_one);
    4144       89476 :                 rc = nomatch(r1p, r2p, r3p, l, r, &lci,
    4145             :                              0, nil_on_miss, only_misses, func, t0);
    4146       89381 :                 goto doreturn;
    4147             :         }
    4148             : 
    4149       36727 :         if (!only_misses && !not_in &&
    4150        4026 :             (lci.ncand == 1 || (BATordered(l) && BATordered_rev(l)) ||
    4151        3963 :              (l->ttype == TYPE_void && is_oid_nil(l->tseqbase)))) {
    4152             :                 /* single value to join, use select */
    4153        1535 :                 rc = selectjoin(r1p, r2p, r3p, l, r, &lci, &rci,
    4154             :                                 nil_matches, nil_on_miss, semi, max_one, min_one,
    4155             :                                 t0, false, func);
    4156        1536 :                 goto doreturn;
    4157       35195 :         } else if (BATtdense(r) && rci.tpe == cand_dense) {
    4158             :                 /* use special implementation for dense right-hand side */
    4159       23520 :                 rc = mergejoin_void(r1p, r2p, r3p, l, r, &lci, &rci,
    4160             :                                     nil_on_miss, only_misses, t0, false,
    4161             :                                     func);
    4162       23487 :                 goto doreturn;
    4163       11675 :         } else if (BATtdense(l)
    4164        5133 :                    && lci.tpe == cand_dense
    4165        5112 :                    && rci.tpe == cand_dense
    4166             :                    && !semi
    4167        5113 :                    && !max_one
    4168             :                    && !min_one
    4169        3594 :                    && !nil_matches
    4170             :                    && !only_misses
    4171        3595 :                    && !not_in
    4172             :                    /* && (rci.ncand * 1024) < lci.ncand */
    4173           0 :                    && (BATordered(r) || BATordered_rev(r))) {
    4174           0 :                 assert(ATOMtype(l->ttype) == TYPE_oid); /* tdense */
    4175           0 :                 rc = fetchjoin(r1p, r2p, l, r, sl, sr, &lci, &rci, func, t0);
    4176           0 :                 goto doreturn;
    4177       11675 :         } else if (BATtdense(l)
    4178        5135 :                    && lci.tpe == cand_dense
    4179        5114 :                    && r2p == NULL
    4180        5100 :                    && (semi || only_misses)
    4181             :                    && !nil_on_miss
    4182        5100 :                    && !not_in
    4183             :                    && !max_one
    4184        5087 :                    && !min_one) {
    4185        5088 :                 *r1p = bitmaskjoin(l, r, &lci, &rci, only_misses, func, t0);
    4186        5089 :                 rc = *r1p == NULL ? GDK_FAIL : GDK_SUCCEED;
    4187        5089 :                 goto doreturn;
    4188             :         } else {
    4189             :                 /* looking at r->tvheap, so we need a lock */
    4190        6587 :                 MT_lock_set(&r->theaplock);
    4191        6597 :                 BUN hsz = r->tvheap ? r->tvheap->size : 0;
    4192        6597 :                 MT_lock_unset(&r->theaplock);
    4193        6600 :                 if ((BATordered(r) || BATordered_rev(r))
    4194        4728 :                     && (BATordered(l)
    4195         533 :                         || BATordered_rev(l)
    4196         496 :                         || BATtdense(r)
    4197         496 :                         || lci.ncand < 1024
    4198         262 :                         || BATcount(r) * (r->twidth + hsz + 2 * sizeof(BUN)) > GDK_mem_maxsize / (GDKnr_threads ? GDKnr_threads : 1))) {
    4199        4597 :                         rc = mergejoin(r1p, r2p, r3p, l, r, &lci, &rci,
    4200             :                                        nil_matches, nil_on_miss, semi, only_misses,
    4201             :                                        not_in, max_one, min_one, estimate, t0, false, func);
    4202        4546 :                         goto doreturn;
    4203             :                 }
    4204             :         }
    4205        2003 :         rcost = joincost(r, lci.ncand, &rci, &rhash, &prhash, &rcand);
    4206        1995 :         if (rcost < 0) {
    4207           0 :                 rc = GDK_FAIL;
    4208           0 :                 goto doreturn;
    4209             :         }
    4210             : 
    4211        1995 :         if (!nil_on_miss && !only_misses && !not_in && !max_one && !min_one) {
    4212             :                 /* maybe do a hash join on the swapped operands; if we
    4213             :                  * do, we need to sort the output, so we take that into
    4214             :                  * account as well */
    4215         942 :                 bool lhash, plhash, lcand, rkey = r->tkey;
    4216         942 :                 double lcost;
    4217             : 
    4218         942 :                 lcost = joincost(l, rci.ncand, &lci, &lhash, &plhash, &lcand);
    4219         941 :                 if (lcost < 0) {
    4220           0 :                         rc = GDK_FAIL;
    4221         813 :                         goto doreturn;
    4222             :                 }
    4223         941 :                 if (semi && !rkey)
    4224         830 :                         lcost += rci.ncand; /* cost of BATunique(r) */
    4225             :                 /* add cost of sorting; obviously we don't know the
    4226             :                  * size, so we guess that the size of the output is
    4227             :                  * the same as the right input */
    4228         941 :                 lcost += rci.ncand * log((double) rci.ncand); /* sort */
    4229         941 :                 if (lcost < rcost) {
    4230         813 :                         BAT *tmp = sr;
    4231         813 :                         BAT *r1, *r2;
    4232         813 :                         if (semi && !rkey) {
    4233         808 :                                 sr = BATunique(r, sr);
    4234         808 :                                 if (sr == NULL) {
    4235           0 :                                         rc = GDK_FAIL;
    4236           0 :                                         goto doreturn;
    4237             :                                 }
    4238         808 :                                 canditer_init(&rci, r, sr);
    4239             :                         }
    4240         813 :                         rc = hashjoin(&r2, &r1, NULL, r, l, &rci, &lci, nil_matches,
    4241             :                                       false, false, false, false, false, false, estimate,
    4242             :                                       t0, true, lhash, plhash, lcand, func);
    4243         813 :                         if (semi && !rkey)
    4244         808 :                                 BBPunfix(sr->batCacheid);
    4245         813 :                         if (rc != GDK_SUCCEED)
    4246           0 :                                 goto doreturn;
    4247         813 :                         if (r2p == NULL) {
    4248         808 :                                 BBPunfix(r2->batCacheid);
    4249         808 :                                 r2 = NULL;
    4250             :                         }
    4251         813 :                         if (semi)
    4252         808 :                                 r1->tkey = true;
    4253         813 :                         if (!VIEWtparent(r1) &&
    4254         813 :                             r1->ttype == TYPE_oid &&
    4255         813 :                             BBP_refs(r1->batCacheid) == 1 &&
    4256         813 :                             (r2 == NULL ||
    4257           5 :                              (!VIEWtparent(r2) &&
    4258           5 :                               BBP_refs(r2->batCacheid) == 1 &&
    4259           5 :                               r2->ttype == TYPE_oid))) {
    4260             :                                 /* in-place sort if we can */
    4261         813 :                                 if (r2) {
    4262           5 :                                         GDKqsort(r1->theap->base, r2->theap->base,
    4263           5 :                                                  NULL, r1->batCount, r1->twidth,
    4264           5 :                                                  r2->twidth, TYPE_oid, false,
    4265             :                                                  false);
    4266           5 :                                         r2->tsorted = false;
    4267           5 :                                         r2->trevsorted = false;
    4268           5 :                                         r2->tseqbase = oid_nil;
    4269           5 :                                         *r2p = r2;
    4270             :                                 } else {
    4271         808 :                                         GDKqsort(r1->theap->base, NULL, NULL,
    4272         808 :                                                  r1->batCount, r1->twidth, 0,
    4273             :                                                  TYPE_oid, false, false);
    4274             :                                 }
    4275         813 :                                 r1->tsorted = true;
    4276         813 :                                 r1->trevsorted = false;
    4277         813 :                                 *r1p = r1;
    4278             :                         } else {
    4279           0 :                                 BAT *ob;
    4280           0 :                                 rc = BATsort(&tmp, r2p ? &ob : NULL, NULL,
    4281             :                                              r1, NULL, NULL, false, false, false);
    4282           0 :                                 BBPunfix(r1->batCacheid);
    4283           0 :                                 if (rc != GDK_SUCCEED) {
    4284           0 :                                         BBPreclaim(r2);
    4285           0 :                                         goto doreturn;
    4286             :                                 }
    4287           0 :                                 *r1p = r1 = tmp;
    4288           0 :                                 if (r2p) {
    4289           0 :                                         tmp = BATproject(ob, r2);
    4290           0 :                                         BBPunfix(r2->batCacheid);
    4291           0 :                                         BBPunfix(ob->batCacheid);
    4292           0 :                                         if (tmp == NULL) {
    4293           0 :                                                 BBPunfix(r1->batCacheid);
    4294           0 :                                                 rc = GDK_FAIL;
    4295           0 :                                                 goto doreturn;
    4296             :                                         }
    4297           0 :                                         *r2p = tmp;
    4298             :                                 }
    4299             :                         }
    4300         813 :                         rc = GDK_SUCCEED;
    4301         813 :                         goto doreturn;
    4302             :                 }
    4303             :         }
    4304        1181 :         rc = hashjoin(r1p, r2p, r3p, l, r, &lci, &rci,
    4305             :                       nil_matches, nil_on_miss, semi, only_misses,
    4306             :                       not_in, max_one, min_one, estimate, t0, false, rhash, prhash,
    4307             :                       rcand, func);
    4308      126033 :   doreturn:
    4309      126033 :         BBPreclaim(lp);
    4310      125994 :         BBPreclaim(rp);
    4311      126272 :         if (rc == GDK_SUCCEED && (semi | only_misses))
    4312      125533 :                 *r1p = virtualize(*r1p);
    4313             :         return rc;
    4314             : }
    4315             : 
    4316             : /* Perform an equi-join over l and r.  Returns two new, aligned, bats
    4317             :  * with the oids of matching tuples.  The result is in the same order
    4318             :  * as l (i.e. r1 is sorted). */
    4319             : gdk_return
    4320         645 : BATleftjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, BUN estimate)
    4321             : {
    4322         645 :         return leftjoin(r1p, r2p, NULL, l, r, sl, sr, nil_matches,
    4323             :                         false, false, false, false, false, false,
    4324             :                         estimate, __func__,
    4325         645 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4326             : }
    4327             : 
    4328             : /* Performs a left outer join over l and r.  Returns two new, aligned,
    4329             :  * bats with the oids of matching tuples, or the oid in the first
    4330             :  * output bat and nil in the second output bat if the value in l does
    4331             :  * not occur in r.  The result is in the same order as l (i.e. r1 is
    4332             :  * sorted). */
    4333             : gdk_return
    4334          55 : BATouterjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, bool match_one, BUN estimate)
    4335             : {
    4336          55 :         return leftjoin(r1p, r2p, NULL, l, r, sl, sr, nil_matches,
    4337             :                         true, false, false, false, match_one, match_one,
    4338             :                         estimate, __func__,
    4339          55 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4340             : }
    4341             : 
    4342             : /* Perform a semi-join over l and r.  Returns one or two new bats
    4343             :  * with the oids of matching tuples.  The result is in the same order
    4344             :  * as l (i.e. r1 is sorted).  If a single bat is returned, it is a
    4345             :  * candidate list. */
    4346             : gdk_return
    4347         963 : BATsemijoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4348             :             bool nil_matches, bool max_one, BUN estimate)
    4349             : {
    4350         963 :         return leftjoin(r1p, r2p, NULL, l, r, sl, sr, nil_matches,
    4351             :                         false, true, false, false, max_one, false,
    4352             :                         estimate, __func__,
    4353         963 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4354             : }
    4355             : 
    4356             : /* Perform a mark-join over l and r.  Returns one or two new bats with
    4357             :  * the oids of matching tuples.  In addition, returns a bat with "marks"
    4358             :  * that indicate the type of match.  This is an outer join, so returns
    4359             :  * at least one value for each row on the left.  If the second output
    4360             :  * pointer (r2p) is NULL, this is also a semi-join, so returns exactly
    4361             :  * one row for each row on the left.  If there is a match, the mark
    4362             :  * column will be TRUE, of there is no match, the second output is NIL,
    4363             :  * and the mark output is FALSE if there are no NILs in the right input,
    4364             :  * and the left input is also not NIL, otherwise the mark output is
    4365             :  * NIL. */
    4366             : gdk_return
    4367        4283 : BATmarkjoin(BAT **r1p, BAT **r2p, BAT **r3p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4368             :             BUN estimate)
    4369             : {
    4370        4283 :         return leftjoin(r1p, r2p, r3p, l, r, sl, sr, false, true, r2p == NULL,
    4371             :                         false, false, false, false, estimate, __func__,
    4372        4283 :                         GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0);
    4373             : }
    4374             : 
    4375             : /* Return a candidate list with the list of rows in l whose value also
    4376             :  * occurs in r.  This is just the left output of a semi-join. */
    4377             : BAT *
    4378        8989 : BATintersect(BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, bool max_one,
    4379             :              BUN estimate)
    4380             : {
    4381        8989 :         BAT *bn;
    4382             : 
    4383        8989 :         if (leftjoin(&bn, NULL, NULL, l, r, sl, sr, nil_matches,
    4384             :                      false, true, false, false, max_one, false,
    4385             :                      estimate, __func__,
    4386        8989 :                      GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0) == GDK_SUCCEED)
    4387        9003 :                 return bn;
    4388             :         return NULL;
    4389             : }
    4390             : 
    4391             : /* Return the difference of l and r.  The result is a BAT with the
    4392             :  * oids of those values in l that do not occur in r.  This is what you
    4393             :  * might call an anti-semi-join.  The result is a candidate list. */
    4394             : BAT *
    4395      111169 : BATdiff(BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, bool not_in,
    4396             :         BUN estimate)
    4397             : {
    4398      111169 :         BAT *bn;
    4399             : 
    4400      111169 :         if (leftjoin(&bn, NULL, NULL, l, r, sl, sr, nil_matches,
    4401             :                      false, false, true, not_in, false, false,
    4402             :                      estimate, __func__,
    4403      111169 :                      GDK_TRACER_TEST(M_DEBUG, ALGO) ? GDKusec() : 0) == GDK_SUCCEED)
    4404      111137 :                 return bn;
    4405             :         return NULL;
    4406             : }
    4407             : 
    4408             : gdk_return
    4409       50853 : BATthetajoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, int op, bool nil_matches, BUN estimate)
    4410             : {
    4411       50853 :         int opcode = 0;
    4412       50853 :         lng t0 = 0;
    4413             : 
    4414             :         /* encode operator as a bit mask into opcode */
    4415       50853 :         switch (op) {
    4416           0 :         case JOIN_EQ:
    4417           0 :                 return BATjoin(r1p, r2p, l, r, sl, sr, nil_matches, estimate);
    4418             :         case JOIN_NE:
    4419             :                 opcode = MASK_NE;
    4420             :                 break;
    4421        8367 :         case JOIN_LT:
    4422        8367 :                 opcode = MASK_LT;
    4423        8367 :                 break;
    4424          11 :         case JOIN_LE:
    4425          11 :                 opcode = MASK_LE;
    4426          11 :                 break;
    4427       42406 :         case JOIN_GT:
    4428       42406 :                 opcode = MASK_GT;
    4429       42406 :                 break;
    4430          34 :         case JOIN_GE:
    4431          34 :                 opcode = MASK_GE;
    4432          34 :                 break;
    4433           0 :         default:
    4434           0 :                 GDKerror("unknown operator %d.\n", op);
    4435           0 :                 return GDK_FAIL;
    4436             :         }
    4437             : 
    4438       50853 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4439       50853 :         *r1p = NULL;
    4440       50853 :         if (r2p) {
    4441        8419 :                 *r2p = NULL;
    4442             :         }
    4443       50853 :         if (joinparamcheck(l, r, NULL, sl, sr, __func__) != GDK_SUCCEED)
    4444             :                 return GDK_FAIL;
    4445             : 
    4446       50843 :         return thetajoin(r1p, r2p, l, r, sl, sr, opcode, estimate, nil_matches,
    4447             :                          __func__, t0);
    4448             : }
    4449             : 
    4450             : gdk_return
    4451      354633 : BATjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool nil_matches, BUN estimate)
    4452             : {
    4453      354633 :         struct canditer lci, rci;
    4454      354633 :         bool lhash = false, rhash = false, lcand = false;
    4455      354633 :         bool plhash = false, prhash = false, rcand = false;
    4456      354633 :         bool swap;
    4457      354633 :         bat parent;
    4458      354633 :         double rcost = 0;
    4459      354633 :         double lcost = 0;
    4460      354633 :         gdk_return rc;
    4461      354633 :         lng t0 = 0;
    4462      354633 :         BAT *r2 = NULL;
    4463      354633 :         BAT *lp = NULL;
    4464      354633 :         BAT *rp = NULL;
    4465             : 
    4466      354633 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4467             : 
    4468      354633 :         canditer_init(&lci, l, sl);
    4469      355021 :         canditer_init(&rci, r, sr);
    4470             : 
    4471      355111 :         if ((parent = VIEWtparent(l)) != 0) {
    4472       64805 :                 lp = BATdescriptor(parent);
    4473       64824 :                 if (lp == NULL)
    4474             :                         return GDK_FAIL;
    4475       64824 :                 if (l->hseqbase == lp->hseqbase &&
    4476       64876 :                     BATcount(l) == BATcount(lp) &&
    4477       24613 :                     ATOMtype(l->ttype) == ATOMtype(lp->ttype)) {
    4478             :                         l = lp;
    4479             :                 } else {
    4480       52519 :                         BBPunfix(lp->batCacheid);
    4481       52519 :                         lp = NULL;
    4482             :                 }
    4483             :         }
    4484      355131 :         if ((parent = VIEWtparent(r)) != 0) {
    4485      281762 :                 rp = BATdescriptor(parent);
    4486      281733 :                 if (rp == NULL) {
    4487           0 :                         BBPreclaim(lp);
    4488           0 :                         return GDK_FAIL;
    4489             :                 }
    4490      281733 :                 if (r->hseqbase == rp->hseqbase &&
    4491      499634 :                     BATcount(r) == BATcount(rp) &&
    4492      463429 :                     ATOMtype(r->ttype) == ATOMtype(rp->ttype)) {
    4493             :                         r = rp;
    4494             :                 } else {
    4495       50071 :                         BBPunfix(rp->batCacheid);
    4496       50071 :                         rp = NULL;
    4497             :                 }
    4498             :         }
    4499             : 
    4500      355082 :         if (l->ttype == TYPE_msk || mask_cand(l)) {
    4501           0 :                 l = BATunmask(l);
    4502           0 :                 BBPreclaim(lp);
    4503           0 :                 if (l == NULL) {
    4504           0 :                         BBPreclaim(rp);
    4505           0 :                         return GDK_FAIL;
    4506             :                 }
    4507             :                 lp = l;
    4508             :         }
    4509      355082 :         if (r->ttype == TYPE_msk || mask_cand(r)) {
    4510          24 :                 r = BATunmask(r);
    4511          24 :                 BBPreclaim(rp);
    4512          24 :                 if (r == NULL) {
    4513           0 :                         BBPreclaim(lp);
    4514           0 :                         return GDK_FAIL;
    4515             :                 }
    4516             :                 rp = r;
    4517             :         }
    4518             : 
    4519      355082 :         *r1p = NULL;
    4520      355082 :         if (r2p)
    4521      317135 :                 *r2p = NULL;
    4522             : 
    4523      355082 :         if (joinparamcheck(l, r, NULL, sl, sr, __func__) != GDK_SUCCEED) {
    4524           0 :                 rc = GDK_FAIL;
    4525           0 :                 goto doreturn;
    4526             :         }
    4527             : 
    4528      354878 :         if (lci.ncand == 0 || rci.ncand == 0) {
    4529      280000 :                 TRC_DEBUG(ALGO, "BATjoin(l=" ALGOBATFMT ","
    4530             :                           "r=" ALGOBATFMT ",sl=" ALGOOPTBATFMT ","
    4531             :                           "sr=" ALGOOPTBATFMT ",nil_matches=%d)\n",
    4532             :                           ALGOBATPAR(l), ALGOBATPAR(r),
    4533             :                           ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    4534             :                           nil_matches);
    4535      280000 :                 rc = nomatch(r1p, r2p, NULL, l, r, &lci,
    4536             :                              0, false, false, __func__, t0);
    4537      279266 :                 goto doreturn;
    4538             :         }
    4539             : 
    4540       74878 :         swap = false;
    4541             : 
    4542       74878 :         if (lci.ncand == 1 || (BATordered(l) && BATordered_rev(l)) || (l->ttype == TYPE_void && is_oid_nil(l->tseqbase))) {
    4543             :                 /* single value to join, use select */
    4544       39482 :                 rc = selectjoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4545             :                                 nil_matches, false, false, false, false,
    4546             :                                 t0, false, __func__);
    4547       39411 :                 goto doreturn;
    4548       35402 :         } else if (rci.ncand == 1 || (BATordered(r) && BATordered_rev(r)) || (r->ttype == TYPE_void && is_oid_nil(r->tseqbase))) {
    4549             :                 /* single value to join, use select */
    4550       12199 :                 rc = selectjoin(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4551             :                                 nil_matches, false, false, false, false,
    4552             :                                 t0, true, __func__);
    4553        8755 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4554        5382 :                         BBPunfix(r2->batCacheid);
    4555        8735 :                 goto doreturn;
    4556       26606 :         } else if (BATtdense(r) && rci.tpe == cand_dense) {
    4557             :                 /* use special implementation for dense right-hand side */
    4558        1635 :                 rc = mergejoin_void(r1p, r2p, NULL, l, r, &lci, &rci,
    4559             :                                     false, false, t0, false, __func__);
    4560        1624 :                 goto doreturn;
    4561       24971 :         } else if (BATtdense(l) && lci.tpe == cand_dense) {
    4562             :                 /* use special implementation for dense right-hand side */
    4563          73 :                 rc = mergejoin_void(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4564             :                                     false, false, t0, true, __func__);
    4565          50 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4566          27 :                         BBPunfix(r2->batCacheid);
    4567          50 :                 goto doreturn;
    4568       38008 :         } else if ((BATordered(l) || BATordered_rev(l)) &&
    4569       17322 :                    (BATordered(r) || BATordered_rev(r))) {
    4570             :                 /* both sorted */
    4571        8921 :                 rc = mergejoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4572             :                                nil_matches, false, false, false, false, false, false,
    4573             :                                estimate, t0, false, __func__);
    4574        8810 :                 goto doreturn;
    4575             :         }
    4576             : 
    4577       16007 :         lcost = joincost(l, rci.ncand, &lci, &lhash, &plhash, &lcand);
    4578       15994 :         rcost = joincost(r, lci.ncand, &rci, &rhash, &prhash, &rcand);
    4579       15984 :         if (lcost < 0 || rcost < 0) {
    4580           0 :                 rc = GDK_FAIL;
    4581           0 :                 goto doreturn;
    4582             :         }
    4583             : 
    4584             :         /* if the cost of doing searches on l is lower than the cost
    4585             :          * of doing searches on r, we swap */
    4586       15984 :         swap = (lcost < rcost);
    4587             : 
    4588       31989 :         if ((r->ttype == TYPE_void && r->tvheap != NULL) ||
    4589       32118 :             ((BATordered(r) || BATordered_rev(r)) &&
    4590        4725 :              (lci.ncand * (log2((double) rci.ncand) + 1) < (swap ? lcost : rcost)))) {
    4591             :                 /* r is sorted and it is cheaper to do multiple binary
    4592             :                  * searches than it is to use a hash */
    4593         355 :                 rc = mergejoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4594             :                                nil_matches, false, false, false, false, false, false,
    4595             :                                estimate, t0, false, __func__);
    4596       31326 :         } else if ((l->ttype == TYPE_void && l->tvheap != NULL) ||
    4597       31545 :             ((BATordered(l) || BATordered_rev(l)) &&
    4598        4168 :              (rci.ncand * (log2((double) lci.ncand) + 1) < (swap ? lcost : rcost)))) {
    4599             :                 /* l is sorted and it is cheaper to do multiple binary
    4600             :                  * searches than it is to use a hash */
    4601        2623 :                 rc = mergejoin(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4602             :                                nil_matches, false, false, false, false, false, false,
    4603             :                                estimate, t0, true, __func__);
    4604        1263 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4605           3 :                         BBPunfix(r2->batCacheid);
    4606       14350 :         } else if (swap) {
    4607       13914 :                 rc = hashjoin(r2p ? r2p : &r2, r1p, NULL, r, l, &rci, &lci,
    4608             :                               nil_matches, false, false, false, false, false, false,
    4609             :                               estimate, t0, true, lhash, plhash, lcand,
    4610             :                               __func__);
    4611        7223 :                 if (rc == GDK_SUCCEED && r2p == NULL)
    4612         567 :                         BBPunfix(r2->batCacheid);
    4613             :         } else {
    4614        7110 :                 rc = hashjoin(r1p, r2p, NULL, l, r, &lci, &rci,
    4615             :                               nil_matches, false, false, false, false, false, false,
    4616             :                               estimate, t0, false, rhash, prhash, rcand,
    4617             :                               __func__);
    4618             :         }
    4619      353800 :   doreturn:
    4620      353800 :         BBPreclaim(lp);
    4621      353442 :         BBPreclaim(rp);
    4622             :         return rc;
    4623             : }
    4624             : 
    4625             : gdk_return
    4626           0 : BATbandjoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr,
    4627             :             const void *c1, const void *c2, bool linc, bool hinc, BUN estimate)
    4628             : {
    4629           0 :         lng t0 = 0;
    4630           0 :         struct canditer lci, rci;
    4631           0 :         const char *lvals, *rvals;
    4632           0 :         int t;
    4633           0 :         const void *nil = ATOMnilptr(l->ttype);
    4634           0 :         int (*cmp)(const void *, const void *) = ATOMcompare(l->ttype);
    4635           0 :         const char *vl, *vr;
    4636           0 :         oid lastr = 0;          /* last value inserted into r2 */
    4637           0 :         BUN nr;
    4638           0 :         oid lo, ro;
    4639           0 :         bool lskipped = false;  /* whether we skipped values in l */
    4640             : 
    4641           0 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    4642             : 
    4643           0 :         size_t counter = 0;
    4644           0 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    4645             : 
    4646             : 
    4647           0 :         MT_thread_setalgorithm(__func__);
    4648           0 :         *r1p = NULL;
    4649           0 :         if (r2p) {
    4650           0 :                 *r2p = NULL;
    4651             :         }
    4652           0 :         if (joinparamcheck(l, r, NULL, sl, sr, __func__) != GDK_SUCCEED)
    4653             :                 return GDK_FAIL;
    4654             : 
    4655           0 :         assert(ATOMtype(l->ttype) == ATOMtype(r->ttype));
    4656             : 
    4657           0 :         t = ATOMtype(l->ttype);
    4658           0 :         t = ATOMbasetype(t);
    4659             : 
    4660           0 :         canditer_init(&lci, l, sl);
    4661           0 :         canditer_init(&rci, r, sr);
    4662             : 
    4663           0 :         if (lci.ncand == 0 || rci.ncand == 0)
    4664           0 :                 return nomatch(r1p, r2p, NULL, l, r, &lci,
    4665             :                                0, false, false, __func__, t0);
    4666             : 
    4667           0 :         switch (t) {
    4668           0 :         case TYPE_bte:
    4669           0 :                 if (is_bte_nil(*(const bte *)c1) ||
    4670           0 :                     is_bte_nil(*(const bte *)c2) ||
    4671           0 :                     -*(const bte *)c1 > *(const bte *)c2 ||
    4672           0 :                     ((!hinc || !linc) && -*(const bte *)c1 == *(const bte *)c2))
    4673           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4674             :                                        0, false, false, __func__, t0);
    4675             :                 break;
    4676           0 :         case TYPE_sht:
    4677           0 :                 if (is_sht_nil(*(const sht *)c1) ||
    4678           0 :                     is_sht_nil(*(const sht *)c2) ||
    4679           0 :                     -*(const sht *)c1 > *(const sht *)c2 ||
    4680           0 :                     ((!hinc || !linc) && -*(const sht *)c1 == *(const sht *)c2))
    4681           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4682             :                                        0, false, false, __func__, t0);
    4683             :                 break;
    4684           0 :         case TYPE_int:
    4685           0 :                 if (is_int_nil(*(const int *)c1) ||
    4686           0 :                     is_int_nil(*(const int *)c2) ||
    4687           0 :                     -*(const int *)c1 > *(const int *)c2 ||
    4688           0 :                     ((!hinc || !linc) && -*(const int *)c1 == *(const int *)c2))
    4689           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4690             :                                        0, false, false, __func__, t0);
    4691             :                 break;
    4692           0 :         case TYPE_lng:
    4693           0 :                 if (is_lng_nil(*(const lng *)c1) ||
    4694           0 :                     is_lng_nil(*(const lng *)c2) ||
    4695           0 :                     -*(const lng *)c1 > *(const lng *)c2 ||
    4696           0 :                     ((!hinc || !linc) && -*(const lng *)c1 == *(const lng *)c2))
    4697           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4698             :                                        0, false, false, __func__, t0);
    4699             :                 break;
    4700             : #ifdef HAVE_HGE
    4701           0 :         case TYPE_hge:
    4702           0 :                 if (is_hge_nil(*(const hge *)c1) ||
    4703           0 :                     is_hge_nil(*(const hge *)c2) ||
    4704           0 :                     -*(const hge *)c1 > *(const hge *)c2 ||
    4705           0 :                     ((!hinc || !linc) && -*(const hge *)c1 == *(const hge *)c2))
    4706           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4707             :                                        0, false, false, __func__, t0);
    4708             :                 break;
    4709             : #endif
    4710           0 :         case TYPE_flt:
    4711           0 :                 if (is_flt_nil(*(const flt *)c1) ||
    4712           0 :                     is_flt_nil(*(const flt *)c2) ||
    4713           0 :                     -*(const flt *)c1 > *(const flt *)c2 ||
    4714           0 :                     ((!hinc || !linc) && -*(const flt *)c1 == *(const flt *)c2))
    4715           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4716             :                                        0, false, false, __func__, t0);
    4717             :                 break;
    4718           0 :         case TYPE_dbl:
    4719           0 :                 if (is_dbl_nil(*(const dbl *)c1) ||
    4720           0 :                     is_dbl_nil(*(const dbl *)c2) ||
    4721           0 :                     -*(const dbl *)c1 > *(const dbl *)c2 ||
    4722           0 :                     ((!hinc || !linc) && -*(const dbl *)c1 == *(const dbl *)c2))
    4723           0 :                         return nomatch(r1p, r2p, NULL, l, r, &lci,
    4724             :                                        0, false, false, __func__, t0);
    4725             :                 break;
    4726           0 :         default:
    4727           0 :                 GDKerror("unsupported type\n");
    4728           0 :                 return GDK_FAIL;
    4729             :         }
    4730             : 
    4731           0 :         BUN maxsize = joininitresults(r1p, r2p, NULL, lci.ncand, rci.ncand, false, false,
    4732             :                                       false, false, false, false, estimate);
    4733           0 :         if (maxsize == BUN_NONE)
    4734             :                 return GDK_FAIL;
    4735           0 :         BAT *r1 = *r1p;
    4736           0 :         BAT *r2 = r2p ? *r2p : NULL;
    4737           0 :         BATiter li = bat_iterator(l);
    4738           0 :         BATiter ri = bat_iterator(r);
    4739             : 
    4740           0 :         lvals = (const char *) li.base;
    4741           0 :         rvals = (const char *) ri.base;
    4742           0 :         assert(ri.vh == NULL);
    4743             : 
    4744           0 :         assert(lvals != NULL);
    4745           0 :         assert(rvals != NULL);
    4746             : 
    4747           0 :         r1->tkey = true;
    4748           0 :         r1->tsorted = true;
    4749           0 :         r1->trevsorted = true;
    4750           0 :         if (r2) {
    4751           0 :                 r2->tkey = true;
    4752           0 :                 r2->tsorted = true;
    4753           0 :                 r2->trevsorted = true;
    4754             :         }
    4755             : 
    4756             :         /* nested loop implementation for band join */
    4757           0 :         for (BUN lidx = 0; lidx < lci.ncand; lidx++) {
    4758           0 :                 GDK_CHECK_TIMEOUT(qry_ctx, counter,
    4759             :                                 GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    4760           0 :                 lo = canditer_next(&lci);
    4761           0 :                 vl = FVALUE(l, lo - l->hseqbase);
    4762           0 :                 if (cmp(vl, nil) == 0)
    4763           0 :                         continue;
    4764           0 :                 nr = 0;
    4765           0 :                 canditer_reset(&rci);
    4766           0 :                 for (BUN ridx = 0; ridx < rci.ncand; ridx++) {
    4767           0 :                         ro = canditer_next(&rci);
    4768           0 :                         vr = FVALUE(r, ro - r->hseqbase);
    4769           0 :                         switch (ATOMtype(li.type)) {
    4770           0 :                         case TYPE_bte: {
    4771           0 :                                 if (is_bte_nil(*(const bte *) vr))
    4772           0 :                                         continue;
    4773           0 :                                 sht v1 = (sht) *(const bte *) vr, v2;
    4774           0 :                                 v2 = v1;
    4775           0 :                                 v1 -= *(const bte *)c1;
    4776           0 :                                 if (*(const bte *)vl <= v1 &&
    4777           0 :                                     (!linc || *(const bte *)vl != v1))
    4778           0 :                                         continue;
    4779           0 :                                 v2 += *(const bte *)c2;
    4780           0 :                                 if (*(const bte *)vl >= v2 &&
    4781           0 :                                     (!hinc || *(const bte *)vl != v2))
    4782           0 :                                         continue;
    4783             :                                 break;
    4784             :                         }
    4785           0 :                         case TYPE_sht: {
    4786           0 :                                 if (is_sht_nil(*(const sht *) vr))
    4787           0 :                                         continue;
    4788           0 :                                 int v1 = (int) *(const sht *) vr, v2;
    4789           0 :                                 v2 = v1;
    4790           0 :                                 v1 -= *(const sht *)c1;
    4791           0 :                                 if (*(const sht *)vl <= v1 &&
    4792           0 :                                     (!linc || *(const sht *)vl != v1))
    4793           0 :                                         continue;
    4794           0 :                                 v2 += *(const sht *)c2;
    4795           0 :                                 if (*(const sht *)vl >= v2 &&
    4796           0 :                                     (!hinc || *(const sht *)vl != v2))
    4797           0 :                                         continue;
    4798             :                                 break;
    4799             :                         }
    4800           0 :                         case TYPE_int: {
    4801           0 :                                 if (is_int_nil(*(const int *) vr))
    4802           0 :                                         continue;
    4803           0 :                                 lng v1 = (lng) *(const int *) vr, v2;
    4804           0 :                                 v2 = v1;
    4805           0 :                                 v1 -= *(const int *)c1;
    4806           0 :                                 if (*(const int *)vl <= v1 &&
    4807           0 :                                     (!linc || *(const int *)vl != v1))
    4808           0 :                                         continue;
    4809           0 :                                 v2 += *(const int *)c2;
    4810           0 :                                 if (*(const int *)vl >= v2 &&
    4811           0 :                                     (!hinc || *(const int *)vl != v2))
    4812           0 :                                         continue;
    4813             :                                 break;
    4814             :                         }
    4815             : #ifdef HAVE_HGE
    4816           0 :                         case TYPE_lng: {
    4817           0 :                                 if (is_lng_nil(*(const lng *) vr))
    4818           0 :                                         continue;
    4819           0 :                                 hge v1 = (hge) *(const lng *) vr, v2;
    4820           0 :                                 v2 = v1;
    4821           0 :                                 v1 -= *(const lng *)c1;
    4822           0 :                                 if (*(const lng *)vl <= v1 &&
    4823           0 :                                     (!linc || *(const lng *)vl != v1))
    4824           0 :                                         continue;
    4825           0 :                                 v2 += *(const lng *)c2;
    4826           0 :                                 if (*(const lng *)vl >= v2 &&
    4827           0 :                                     (!hinc || *(const lng *)vl != v2))
    4828           0 :                                         continue;
    4829             :                                 break;
    4830             :                         }
    4831             : #else
    4832             : #ifdef HAVE___INT128
    4833             :                         case TYPE_lng: {
    4834             :                                 if (is_lng_nil(*(const lng *) vr))
    4835             :                                         continue;
    4836             :                                 __int128 v1 = (__int128) *(const lng *) vr, v2;
    4837             :                                 v2 = v1;
    4838             :                                 v1 -= *(const lng *)c1;
    4839             :                                 if (*(const lng *)vl <= v1 &&
    4840             :                                     (!linc || *(const lng *)vl != v1))
    4841             :                                         continue;
    4842             :                                 v2 += *(const lng *)c2;
    4843             :                                 if (*(const lng *)vl >= v2 &&
    4844             :                                     (!hinc || *(const lng *)vl != v2))
    4845             :                                         continue;
    4846             :                                 break;
    4847             :                         }
    4848             : #else
    4849             : #ifdef HAVE___INT128_T
    4850             :                         case TYPE_lng: {
    4851             :                                 if (is_lng_nil(*(const lng *) vr))
    4852             :                                         continue;
    4853             :                                 __int128_t v1 = (__int128_t) *(const lng *) vr, v2;
    4854             :                                 v2 = v1;
    4855             :                                 v1 -= *(const lng *)c1;
    4856             :                                 if (*(const lng *)vl <= v1 &&
    4857             :                                     (!linc || *(const lng *)vl != v1))
    4858             :                                         continue;
    4859             :                                 v2 += *(const lng *)c2;
    4860             :                                 if (*(const lng *)vl >= v2 &&
    4861             :                                     (!hinc || *(const lng *)vl != v2))
    4862             :                                         continue;
    4863             :                                 break;
    4864             :                         }
    4865             : #else
    4866             :                         case TYPE_lng: {
    4867             :                                 if (is_lng_nil(*(const lng *) vr))
    4868             :                                         continue;
    4869             :                                 lng v1, v2;
    4870             :                                 SUBI_WITH_CHECK(*(const lng *)vr,
    4871             :                                                *(const lng *)c1,
    4872             :                                                lng, v1,
    4873             :                                                GDK_lng_max,
    4874             :                                                do{if(*(const lng*)c1<0)goto nolmatch;else goto lmatch1;}while(false));
    4875             :                                 if (*(const lng *)vl <= v1 &&
    4876             :                                     (!linc || *(const lng *)vl != v1))
    4877             :                                         continue;
    4878             :                                   lmatch1:
    4879             :                                 ADDI_WITH_CHECK(*(const lng *)vr,
    4880             :                                                *(const lng *)c2,
    4881             :                                                lng, v2,
    4882             :                                                GDK_lng_max,
    4883             :                                                do{if(*(const lng*)c2>0)goto nolmatch;else goto lmatch2;}while(false));
    4884             :                                 if (*(const lng *)vl >= v2 &&
    4885             :                                     (!hinc || *(const lng *)vl != v2))
    4886             :                                         continue;
    4887             :                                   lmatch2:
    4888             :                                 break;
    4889             :                                   nolmatch:
    4890             :                                 continue;
    4891             :                         }
    4892             : #endif
    4893             : #endif
    4894             : #endif
    4895             : #ifdef HAVE_HGE
    4896           0 :                         case TYPE_hge: {
    4897           0 :                                 if (is_hge_nil(*(const hge *) vr))
    4898           0 :                                         continue;
    4899           0 :                                 hge v1, v2;
    4900           0 :                                 SUBI_WITH_CHECK(*(const hge *)vr,
    4901             :                                                *(const hge *)c1,
    4902             :                                                hge, v1,
    4903             :                                                GDK_hge_max,
    4904             :                                                do{if(*(const hge*)c1<0)goto nohmatch;else goto hmatch1;}while(false));
    4905           0 :                                 if (*(const hge *)vl <= v1 &&
    4906           0 :                                     (!linc || *(const hge *)vl != v1))
    4907           0 :                                         continue;
    4908           0 :                                   hmatch1:
    4909           0 :                                 ADDI_WITH_CHECK(*(const hge *)vr,
    4910             :                                                *(const hge *)c2,
    4911             :                                                hge, v2,
    4912             :                                                GDK_hge_max,
    4913             :                                                do{if(*(const hge*)c2>0)goto nohmatch;else goto hmatch2;}while(false));
    4914           0 :                                 if (*(const hge *)vl >= v2 &&
    4915           0 :                                     (!hinc || *(const hge *)vl != v2))
    4916           0 :                                         continue;
    4917           0 :                                   hmatch2:
    4918             :                                 break;
    4919           0 :                                   nohmatch:
    4920           0 :                                 continue;
    4921             :                         }
    4922             : #endif
    4923           0 :                         case TYPE_flt: {
    4924           0 :                                 if (is_flt_nil(*(const flt *) vr))
    4925           0 :                                         continue;
    4926           0 :                                 dbl v1 = (dbl) *(const flt *) vr, v2;
    4927           0 :                                 v2 = v1;
    4928           0 :                                 v1 -= *(const flt *)c1;
    4929           0 :                                 if (*(const flt *)vl <= v1 &&
    4930           0 :                                     (!linc || *(const flt *)vl != v1))
    4931           0 :                                         continue;
    4932           0 :                                 v2 += *(const flt *)c2;
    4933           0 :                                 if (*(const flt *)vl >= v2 &&
    4934           0 :                                     (!hinc || *(const flt *)vl != v2))
    4935           0 :                                         continue;
    4936             :                                 break;
    4937             :                         }
    4938           0 :                         case TYPE_dbl: {
    4939           0 :                                 if (is_dbl_nil(*(const dbl *) vr))
    4940           0 :                                         continue;
    4941           0 :                                 dbl v1, v2;
    4942           0 :                                 SUBF_WITH_CHECK(*(const dbl *)vr,
    4943             :                                                *(const dbl *)c1,
    4944             :                                                dbl, v1,
    4945             :                                                GDK_dbl_max,
    4946             :                                                do{if(*(const dbl*)c1<0)goto nodmatch;else goto dmatch1;}while(false));
    4947           0 :                                 if (*(const dbl *)vl <= v1 &&
    4948           0 :                                     (!linc || *(const dbl *)vl != v1))
    4949           0 :                                         continue;
    4950           0 :                                   dmatch1:
    4951           0 :                                 ADDF_WITH_CHECK(*(const dbl *)vr,
    4952             :                                                *(const dbl *)c2,
    4953             :                                                dbl, v2,
    4954             :                                                GDK_dbl_max,
    4955             :                                                do{if(*(const dbl*)c2>0)goto nodmatch;else goto dmatch2;}while(false));
    4956           0 :                                 if (*(const dbl *)vl >= v2 &&
    4957           0 :                                     (!hinc || *(const dbl *)vl != v2))
    4958           0 :                                         continue;
    4959           0 :                                   dmatch2:
    4960             :                                 break;
    4961           0 :                                   nodmatch:
    4962           0 :                                 continue;
    4963             :                         }
    4964             :                         }
    4965           0 :                         if (maybeextend(r1, r2, NULL, 1, lci.next, lci.ncand, maxsize) != GDK_SUCCEED)
    4966           0 :                                 goto bailout;
    4967           0 :                         if (BATcount(r1) > 0) {
    4968           0 :                                 if (r2 && lastr + 1 != ro)
    4969           0 :                                         r2->tseqbase = oid_nil;
    4970           0 :                                 if (nr == 0) {
    4971           0 :                                         r1->trevsorted = false;
    4972           0 :                                         if (r2 == NULL) {
    4973             :                                                 /* nothing */
    4974           0 :                                         } else if (lastr > ro) {
    4975           0 :                                                 r2->tsorted = false;
    4976           0 :                                                 r2->tkey = false;
    4977           0 :                                         } else if (lastr < ro) {
    4978           0 :                                                 r2->trevsorted = false;
    4979             :                                         } else {
    4980           0 :                                                 r2->tkey = false;
    4981             :                                         }
    4982             :                                 }
    4983             :                         }
    4984           0 :                         APPEND(r1, lo);
    4985           0 :                         if (r2) {
    4986           0 :                                 APPEND(r2, ro);
    4987             :                         }
    4988           0 :                         lastr = ro;
    4989           0 :                         nr++;
    4990             :                 }
    4991           0 :                 if (nr > 1) {
    4992           0 :                         r1->tkey = false;
    4993           0 :                         r1->tseqbase = oid_nil;
    4994           0 :                         if (r2) {
    4995           0 :                                 r2->trevsorted = false;
    4996             :                         }
    4997           0 :                 } else if (nr == 0) {
    4998           0 :                         lskipped = BATcount(r1) > 0;
    4999           0 :                 } else if (lskipped) {
    5000           0 :                         r1->tseqbase = oid_nil;
    5001             :                 }
    5002             :         }
    5003             :         /* also set other bits of heap to correct value to indicate size */
    5004           0 :         BATsetcount(r1, BATcount(r1));
    5005           0 :         if (r2) {
    5006           0 :                 BATsetcount(r2, BATcount(r2));
    5007           0 :                 assert(BATcount(r1) == BATcount(r2));
    5008             :         }
    5009           0 :         if (BATcount(r1) > 0) {
    5010           0 :                 if (BATtdense(r1))
    5011           0 :                         r1->tseqbase = ((oid *) r1->theap->base)[0];
    5012           0 :                 if (r2 && BATtdense(r2))
    5013           0 :                         r2->tseqbase = ((oid *) r2->theap->base)[0];
    5014             :         } else {
    5015           0 :                 r1->tseqbase = 0;
    5016           0 :                 if (r2) {
    5017           0 :                         r2->tseqbase = 0;
    5018             :                 }
    5019             :         }
    5020           0 :         bat_iterator_end(&li);
    5021           0 :         bat_iterator_end(&ri);
    5022           0 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT "," "r=" ALGOBATFMT
    5023             :                   ",sl=" ALGOOPTBATFMT "," "sr=" ALGOOPTBATFMT ","
    5024             :                   " -> " ALGOBATFMT "," ALGOOPTBATFMT
    5025             :                   " (" LLFMT "usec)\n",
    5026             :                   ALGOBATPAR(l), ALGOBATPAR(r),
    5027             :                   ALGOOPTBATPAR(sl), ALGOOPTBATPAR(sr),
    5028             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2),
    5029             :                   GDKusec() - t0);
    5030             :         return GDK_SUCCEED;
    5031             : 
    5032           0 :   bailout:
    5033           0 :         bat_iterator_end(&li);
    5034           0 :         bat_iterator_end(&ri);
    5035           0 :         BBPreclaim(r1);
    5036           0 :         BBPreclaim(r2);
    5037             :         return GDK_FAIL;
    5038             : }
    5039             : 
    5040             : #define LTany(a,b)      ((*cmp)(a, b) < 0)
    5041             : #define EQany(a,b)      ((*cmp)(a, b) == 0)
    5042             : #define is_any_nil(v)   ((v) == NULL || (*cmp)((v), nil) == 0)
    5043             : 
    5044             : #define less3(a,b,i,t)  (is_##t##_nil(a) || is_##t##_nil(b) ? bit_nil : LT##t(a, b) || (i && EQ##t(a, b)))
    5045             : #define grtr3(a,b,i,t)  (is_##t##_nil(a) || is_##t##_nil(b) ? bit_nil : LT##t(b, a) || (i && EQ##t(a, b)))
    5046             : #define or3(a,b)        ((a) == 1 || (b) == 1 ? 1 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 0)
    5047             : #define and3(a,b)       ((a) == 0 || (b) == 0 ? 0 : is_bit_nil(a) || is_bit_nil(b) ? bit_nil : 1)
    5048             : #define not3(a)         (is_bit_nil(a) ? bit_nil : !(a))
    5049             : 
    5050             : #define between3(v, lo, linc, hi, hinc, TYPE)                           \
    5051             :         and3(grtr3(v, lo, linc, TYPE), less3(v, hi, hinc, TYPE))
    5052             : 
    5053             : #define BETWEEN(v, lo, linc, hi, hinc, TYPE)                            \
    5054             :         (is_##TYPE##_nil(v)                                             \
    5055             :          ? bit_nil                                                      \
    5056             :          : (bit) (anti                                                  \
    5057             :                   ? (symmetric                                          \
    5058             :                      ? not3(or3(between3(v, lo, linc, hi, hinc, TYPE),  \
    5059             :                                 between3(v, hi, hinc, lo, linc, TYPE))) \
    5060             :                      : not3(between3(v, lo, linc, hi, hinc, TYPE)))     \
    5061             :                   : (symmetric                                          \
    5062             :                      ? or3(between3(v, lo, linc, hi, hinc, TYPE),       \
    5063             :                            between3(v, hi, hinc, lo, linc, TYPE))       \
    5064             :                      : between3(v, lo, linc, hi, hinc, TYPE))))
    5065             : 
    5066             : static gdk_return
    5067         122 : rangejoin(BAT *r1, BAT *r2, BAT *l, BAT *rl, BAT *rh,
    5068             :           struct canditer *lci, struct canditer *rci,
    5069             :           bool linc, bool hinc, bool anti, bool symmetric, BUN maxsize)
    5070             : {
    5071         122 :         if (!anti && !symmetric) {
    5072             :                 /* we'll need these */
    5073         111 :                 (void) BATordered(l);
    5074         113 :                 (void) BATordered_rev(l);
    5075             :         }
    5076         125 :         BATiter li = bat_iterator(l);
    5077         125 :         BATiter rli = bat_iterator(rl);
    5078         125 :         BATiter rhi = bat_iterator(rh);
    5079         125 :         const char *rlvals, *rhvals;
    5080         125 :         const char *lvars, *rlvars, *rhvars;
    5081         125 :         const void *nil = ATOMnilptr(li.type);
    5082         125 :         int (*cmp)(const void *, const void *) = ATOMcompare(li.type);
    5083         125 :         int t;
    5084         125 :         BUN cnt, ncnt, lncand = lci->ncand, rncand = rci->ncand;
    5085         125 :         oid *restrict dst1, *restrict dst2;
    5086         125 :         const void *vrl, *vrh;
    5087         125 :         oid ro;
    5088         125 :         oid rlval = oid_nil, rhval = oid_nil;
    5089         125 :         int sorted = 0;         /* which output column is sorted */
    5090         125 :         Heap *oidxh = NULL;
    5091             : 
    5092         125 :         QryCtx *qry_ctx = MT_thread_get_qry_ctx();
    5093             : 
    5094         375 :         assert(ATOMtype(li.type) == ATOMtype(rli.type));
    5095         250 :         assert(ATOMtype(li.type) == ATOMtype(rhi.type));
    5096         125 :         assert(BATcount(rl) == BATcount(rh));
    5097         125 :         assert(rl->hseqbase == rh->hseqbase);
    5098         125 :         assert(r1->ttype == TYPE_oid);
    5099         125 :         assert(r2 == NULL || r2->ttype == TYPE_oid);
    5100         106 :         assert(r2 == NULL || BATcount(r1) == BATcount(r2));
    5101         125 :         assert(li.type != TYPE_void || !is_oid_nil(l->tseqbase));
    5102         125 :         assert(rli.type != TYPE_void || !is_oid_nil(rl->tseqbase));
    5103         125 :         assert(rhi.type != TYPE_void || !is_oid_nil(rh->tseqbase));
    5104             : 
    5105         125 :         TRC_DEBUG(ALGO, "l=" ALGOBATFMT ","
    5106             :                   "rl=" ALGOBATFMT ",rh=" ALGOBATFMT ","
    5107             :                   "sl=" ALGOOPTBATFMT ",sr=" ALGOOPTBATFMT ","
    5108             :                   "anti=%s,symmetric=%s\n",
    5109             :                   ALGOBATPAR(l),
    5110             :                   ALGOBATPAR(rl),
    5111             :                   ALGOBATPAR(rh),
    5112             :                   ALGOOPTBATPAR(lci->s),
    5113             :                   ALGOOPTBATPAR(rci->s),
    5114             :                   anti ? "true" : "false",
    5115             :                   symmetric ? "true" : "false");
    5116             : 
    5117         125 :         rlvals = rli.type == TYPE_void ? NULL : (const char *) rli.base;
    5118         125 :         rhvals = rhi.type == TYPE_void ? NULL : (const char *) rhi.base;
    5119         125 :         dst1 = (oid *) Tloc(r1, 0);
    5120         125 :         dst2 = r2 ? (oid *) Tloc(r2, 0) : NULL;
    5121             : 
    5122         125 :         t = ATOMtype(li.type);
    5123         125 :         t = ATOMbasetype(t);
    5124             : 
    5125         125 :         if (li.vh && li.type) {
    5126          17 :                 assert(rli.vh && rli.type);
    5127          17 :                 assert(rhi.vh && rhi.type);
    5128          17 :                 lvars = li.vh->base;
    5129          17 :                 rlvars = rli.vh->base;
    5130          17 :                 rhvars = rhi.vh->base;
    5131             :         } else {
    5132         108 :                 assert(rli.vh == NULL);
    5133         108 :                 assert(rhi.vh == NULL);
    5134             :                 lvars = rlvars = rhvars = NULL;
    5135             :         }
    5136             : 
    5137         125 :         if (!anti && !symmetric && !li.sorted && !li.revsorted) {
    5138          13 :                 (void) BATcheckorderidx(l);
    5139          13 :                 MT_lock_set(&l->batIdxLock);
    5140          13 :                 if ((oidxh = l->torderidx) != NULL)
    5141           0 :                         HEAPincref(oidxh);
    5142          13 :                 MT_lock_unset(&l->batIdxLock);
    5143             : #if 0 /* needs checking */
    5144             :                 if (oidxh == NULL && VIEWtparent(l)) {
    5145             : /* if enabled, need to fix/unfix parent bat */
    5146             :                         BAT *pb = BBP_desc(VIEWtparent(l));
    5147             :                         (void) BATcheckorderidx(pb);
    5148             :                         MT_lock_set(&pb->batIdxLock);
    5149             :                         if ((oidxh = pb->torderidx) != NULL) {
    5150             :                                 HEAPincref(oidxh);
    5151             :                                 l = pb;
    5152             :                         }
    5153             :                         MT_lock_unset(&pb->batIdxLock);
    5154             :                 }
    5155             : #endif
    5156             :         }
    5157             : 
    5158         125 :         vrl = &rlval;
    5159         125 :         vrh = &rhval;
    5160         125 :         if (!anti && !symmetric && (li.sorted || li.revsorted || oidxh)) {
    5161             :                 /* left column is sorted, use binary search */
    5162         101 :                 sorted = 2;
    5163         616 :                 TIMEOUT_LOOP(rncand, qry_ctx) {
    5164         416 :                         BUN low, high;
    5165             : 
    5166         416 :                         ro = canditer_next(rci);
    5167         397 :                         if (rlvals) {
    5168         397 :                                 vrl = VALUE(rl, ro - rl->hseqbase);
    5169             :                         } else {
    5170             :                                 /* TYPE_void */
    5171           0 :                                 rlval = ro - rl->hseqbase + rl->tseqbase;
    5172             :                         }
    5173         397 :                         if (rhvals) {
    5174         397 :                                 vrh = VALUE(rh, ro - rh->hseqbase);
    5175             :                         } else {
    5176             :                                 /* TYPE_void */
    5177           0 :                                 rhval = ro - rh->hseqbase + rh->tseqbase;
    5178             :                         }
    5179         399 :                         if (cmp(vrl, nil) == 0 || cmp(vrh, nil) == 0)
    5180           9 :                                 continue;
    5181         381 :                         if (li.sorted) {
    5182         378 :                                 if (linc)
    5183         268 :                                         low = SORTfndfirst(l, vrl);
    5184             :                                 else
    5185         110 :                                         low = SORTfndlast(l, vrl);
    5186         403 :                                 if (hinc)
    5187         344 :                                         high = SORTfndlast(l, vrh);
    5188             :                                 else
    5189          59 :                                         high = SORTfndfirst(l, vrh);
    5190           3 :                         } else  if (li.revsorted) {
    5191           3 :                                 if (hinc)
    5192           3 :                                         low = SORTfndfirst(l, vrh);
    5193             :                                 else
    5194           0 :                                         low = SORTfndlast(l, vrh);
    5195           3 :                                 if (linc)
    5196           3 :                                         high = SORTfndlast(l, vrl);
    5197             :                                 else
    5198           0 :                                         high = SORTfndfirst(l, vrl);
    5199             :                         } else {
    5200           0 :                                 assert(oidxh);
    5201           0 :                                 if (linc)
    5202           0 :                                         low = ORDERfndfirst(l, oidxh, vrl);
    5203             :                                 else
    5204           0 :                                         low = ORDERfndlast(l, oidxh, vrl);
    5205           0 :                                 if (hinc)
    5206           0 :                                         high = ORDERfndlast(l, oidxh, vrh);
    5207             :                                 else
    5208           0 :                                         high = ORDERfndfirst(l, oidxh, vrh);
    5209             :                         }
    5210         410 :                         if (high <= low)
    5211         226 :                                 continue;
    5212         184 :                         if (li.sorted || li.revsorted) {
    5213         184 :                                 low = canditer_search(lci, low + l->hseqbase, true);
    5214         184 :                                 high = canditer_search(lci, high + l->hseqbase, true);
    5215         184 :                                 assert(high >= low);
    5216             : 
    5217         184 :                                 if (BATcapacity(r1) < BATcount(r1) + high - low) {
    5218           0 :                                         cnt = BATcount(r1) + high - low + 1024;
    5219           0 :                                         if (cnt > maxsize)
    5220             :                                                 cnt = maxsize;
    5221           0 :                                         BATsetcount(r1, BATcount(r1));
    5222           0 :                                         if (BATextend(r1, cnt) != GDK_SUCCEED)
    5223           0 :                                                 goto bailout;
    5224           0 :                                         dst1 = (oid *) Tloc(r1, 0);
    5225           0 :                                         if (r2) {
    5226           0 :                                                 BATsetcount(r2, BATcount(r2));
    5227           0 :                                                 if (BATextend(r2, cnt) != GDK_SUCCEED)
    5228           0 :                                                         goto bailout;
    5229           0 :                                                 assert(BATcapacity(r1) == BATcapacity(r2));
    5230           0 :                                                 dst2 = (oid *) Tloc(r2, 0);
    5231             :                                         }
    5232             :                                 }
    5233         184 :                                 canditer_setidx(lci, low);
    5234        1000 :                                 while (low < high) {
    5235         818 :                                         dst1[r1->batCount++] = canditer_next(lci);
    5236         816 :                                         if (r2) {
    5237         804 :                                                 dst2[r2->batCount++] = ro;
    5238             :                                         }
    5239         816 :                                         low++;
    5240             :                                 }
    5241             :                         } else {
    5242           0 :                                 const oid *ord;
    5243             : 
    5244           0 :                                 assert(oidxh);
    5245           0 :                                 ord = (const oid *) oidxh->base + ORDERIDXOFF;
    5246             : 
    5247           0 :                                 if (BATcapacity(r1) < BATcount(r1) + high - low) {
    5248           0 :                                         cnt = BATcount(r1) + high - low + 1024;
    5249           0 :                                         if (cnt > maxsize)
    5250             :                                                 cnt = maxsize;
    5251           0 :                                         BATsetcount(r1, BATcount(r1));
    5252           0 :                                         if (BATextend(r1, cnt) != GDK_SUCCEED)
    5253           0 :                                                 goto bailout;
    5254           0 :                                         dst1 = (oid *) Tloc(r1, 0);
    5255           0 :                                         if (r2) {
    5256           0 :                                                 BATsetcount(r2, BATcount(r2));
    5257           0 :                                                 if (BATextend(r2, cnt) != GDK_SUCCEED)
    5258           0 :                                                         goto bailout;
    5259           0 :                                                 assert(BATcapacity(r1) == BATcapacity(r2));
    5260           0 :                                                 dst2 = (oid *) Tloc(r2, 0);
    5261             :                                         }
    5262             :                                 }
    5263             : 
    5264           0 :                                 while (low < high) {
    5265           0 :                                         if (canditer_contains(lci, ord[low])) {
    5266           0 :                                                 dst1[r1->batCount++] = ord[low];
    5267           0 :                                                 if (r2) {
    5268           0 :                                                         dst2[r2->batCount++] = ro;
    5269             :                                                 }
    5270             :                                         }
    5271           0 :                                         low++;
    5272             :                                 }
    5273             :                         }
    5274             :                 }
    5275         100 :                 if (oidxh)
    5276           0 :                         HEAPdecref(oidxh, false);
    5277         100 :                 TIMEOUT_CHECK(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    5278         100 :                 cnt = BATcount(r1);
    5279         100 :                 assert(r2 == NULL || BATcount(r1) == BATcount(r2));
    5280             :         } else {
    5281             :                 /* nested loop implementation */
    5282          24 :                 const void *vl;
    5283          24 :                 const char *lvals;
    5284          24 :                 oid lval;
    5285             : 
    5286          24 :                 sorted = 1;
    5287          24 :                 lvals = li.type == TYPE_void ? NULL : (const char *) li.base;
    5288          24 :                 vl = &lval;
    5289         283 :                 TIMEOUT_LOOP(lncand, qry_ctx) {
    5290         236 :                         oid lo;
    5291             : 
    5292         236 :                         lo = canditer_next(lci);
    5293         235 :                         if (lvals) {
    5294         235 :                                 vl = VALUE(l, lo - l->hseqbase);
    5295         235 :                                 if (cmp(vl, nil) == 0)
    5296           8 :                                         continue;
    5297             :                         } else {
    5298           0 :                                 lval = lo - l->hseqbase + l->tseqbase;
    5299             :                         }
    5300         227 :                         canditer_reset(rci);
    5301       26013 :                         for (BUN j = 0; j < rncand; j++) {
    5302       25784 :                                 ro = canditer_next(rci);
    5303       19628 :                                 if (rlvals) {
    5304       19628 :                                         vrl = VALUE(rl, ro - rl->hseqbase);
    5305             :                                 } else {
    5306             :                                         /* TYPE_void */
    5307           0 :                                         rlval = ro - rl->hseqbase + rl->tseqbase;
    5308             :                                 }
    5309       19628 :                                 if (rhvals) {
    5310       19628 :                                         vrh = VALUE(rh, ro - rh->hseqbase);
    5311             :                                 } else {
    5312             :                                         /* TYPE_void */
    5313           0 :                                         rhval = ro - rh->hseqbase + rh->tseqbase;
    5314             :                                 }
    5315       19689 :                                 if (BETWEEN(vl, vrl, linc, vrh, hinc, any) != 1)
    5316       16043 :                                         continue;
    5317        9743 :                                 if (BATcount(r1) == BATcapacity(r1)) {
    5318           2 :                                         BUN newcap = BATgrows(r1);
    5319           2 :                                         if (newcap > maxsize)
    5320             :                                                 newcap = maxsize;
    5321           2 :                                         BATsetcount(r1, BATcount(r1));
    5322           2 :                                         if (BATextend(r1, newcap) != GDK_SUCCEED)
    5323           0 :                                                 goto bailout;
    5324           2 :                                         dst1 = (oid *) Tloc(r1, 0);
    5325           2 :                                         if (r2) {
    5326           2 :                                                 BATsetcount(r2, BATcount(r2));
    5327           2 :                                                 if (BATextend(r2, newcap) != GDK_SUCCEED)
    5328           0 :                                                         goto bailout;
    5329           2 :                                                 assert(BATcapacity(r1) == BATcapacity(r2));
    5330           2 :                                                 dst2 = (oid *) Tloc(r2, 0);
    5331             :                                         }
    5332             :                                 }
    5333        9743 :                                 dst1[r1->batCount++] = lo;
    5334        9743 :                                 if (r2) {
    5335        9734 :                                         dst2[r2->batCount++] = ro;
    5336             :                                 }
    5337             :                         }
    5338             :                 }
    5339          24 :                 TIMEOUT_CHECK(qry_ctx, GOTO_LABEL_TIMEOUT_HANDLER(bailout, qry_ctx));
    5340          23 :                 cnt = BATcount(r1);
    5341          23 :                 assert(r2 == NULL || BATcount(r1) == BATcount(r2));
    5342             :         }
    5343             : 
    5344             :         /* also set other bits of heap to correct value to indicate size */
    5345         123 :         BATsetcount(r1, cnt);
    5346             : 
    5347             :         /* set properties using an extra scan (usually not complete) */
    5348         123 :         dst1 = (oid *) Tloc(r1, 0);
    5349         123 :         r1->tkey = true;
    5350         123 :         r1->tsorted = true;
    5351         123 :         r1->trevsorted = true;
    5352         123 :         r1->tseqbase = 0;
    5353         123 :         r1->tnil = false;
    5354         123 :         r1->tnonil = true;
    5355         599 :         for (ncnt = 1; ncnt < cnt; ncnt++) {
    5356         487 :                 if (dst1[ncnt - 1] == dst1[ncnt]) {
    5357         426 :                         r1->tseqbase = oid_nil;
    5358         426 :                         r1->tkey = false;
    5359          61 :                 } else if (dst1[ncnt - 1] < dst1[ncnt]) {
    5360          58 :                         r1->trevsorted = false;
    5361          58 :                         if (dst1[ncnt - 1] + 1 != dst1[ncnt])
    5362           3 :                                 r1->tseqbase = oid_nil;
    5363             :                 } else {
    5364           3 :                         assert(sorted != 1);
    5365           3 :                         r1->tsorted = false;
    5366           3 :                         r1->tseqbase = oid_nil;
    5367           3 :                         r1->tkey = false;
    5368             :                 }
    5369         534 :                 if (!(r1->trevsorted | BATtdense(r1) | r1->tkey | ((sorted != 1) & r1->tsorted)))
    5370             :                         break;
    5371             :         }
    5372         123 :         if (BATtdense(r1))
    5373         100 :                 r1->tseqbase = cnt > 0 ? dst1[0] : 0;
    5374         123 :         if (r2) {
    5375         104 :                 BATsetcount(r2, cnt);
    5376         104 :                 dst2 = (oid *) Tloc(r2, 0);
    5377         104 :                 r2->tkey = true;
    5378         104 :                 r2->tsorted = true;
    5379         104 :                 r2->trevsorted = true;
    5380         104 :                 r2->tseqbase = 0;
    5381         104 :                 r2->tnil = false;
    5382         104 :                 r2->tnonil = true;
    5383         574 :                 for (ncnt = 1; ncnt < cnt; ncnt++) {
    5384         483 :                         if (dst2[ncnt - 1] == dst2[ncnt]) {
    5385          42 :                                 r2->tseqbase = oid_nil;
    5386          42 :                                 r2->tkey = false;
    5387         441 :                         } else if (dst2[ncnt - 1] < dst2[ncnt]) {
    5388         431 :                                 r2->trevsorted = false;
    5389         431 :                                 if (dst2[ncnt - 1] + 1 != dst2[ncnt])
    5390         127 :                                         r2->tseqbase = oid_nil;
    5391             :                         } else {
    5392          10 :                                 assert(sorted != 2);
    5393          10 :                                 r2->tsorted = false;
    5394          10 :                                 r2->tseqbase = oid_nil;
    5395          10 :                                 r2->tkey = false;
    5396             :                         }
    5397         655 :                         if (!(r2->trevsorted | BATtdense(r2) | r2->tkey | ((sorted != 2) & r2->tsorted)))
    5398             :                                 break;
    5399             :                 }
    5400         104 :                 if (BATtdense(r2))
    5401          77 :                         r2->tseqbase = cnt > 0 ? dst2[0] : 0;
    5402             :         }
    5403         123 :         TRC_DEBUG(ALGO, "l=%s,rl=%s,rh=%s -> "
    5404             :                   "(" ALGOBATFMT "," ALGOOPTBATFMT ")\n",
    5405             :                   BATgetId(l), BATgetId(rl), BATgetId(rh),
    5406             :                   ALGOBATPAR(r1), ALGOOPTBATPAR(r2));
    5407         123 :         bat_iterator_end(&li);
    5408         124 :         bat_iterator_end(&rli);
    5409         125 :         bat_iterator_end(&rhi);
    5410         125 :         return GDK_SUCCEED;
    5411             : 
    5412           0 :   bailout:
    5413           0 :         bat_iterator_end(&li);
    5414           0 :         bat_iterator_end(&rli);
    5415           0 :         bat_iterator_end(&rhi);
    5416           0 :         BBPreclaim(r1);
    5417           0 :         BBPreclaim(r2);
    5418             :         return GDK_FAIL;
    5419             : }
    5420             : 
    5421             : gdk_return
    5422         147 : BATrangejoin(BAT **r1p, BAT **r2p, BAT *l, BAT *rl, BAT *rh,
    5423             :              BAT *sl, BAT *sr, bool linc, bool hinc, bool anti, bool symmetric,
    5424             :              BUN estimate)
    5425             : {
    5426         147 :         struct canditer lci, rci;
    5427         147 :         BAT *r1 = NULL, *r2 = NULL;
    5428         147 :         BUN maxsize;
    5429         147 :         lng t0 = 0;
    5430             : 
    5431         147 :         TRC_DEBUG_IF(ALGO) t0 = GDKusec();
    5432         147 :         *r1p = NULL;
    5433         147 :         if (r2p) {
    5434         122 :                 *r2p = NULL;
    5435             :         }
    5436         147 :         if (joinparamcheck(l, rl, rh, sl, sr, __func__) != GDK_SUCCEED)
    5437             :                 return GDK_FAIL;
    5438         147 :         canditer_init(&lci, l, sl);
    5439         146 :         canditer_init(&rci, rl, sr);
    5440         147 :         if (lci.ncand == 0 ||
    5441         137 :             rci.ncand == 0 ||
    5442         125 :             (l->ttype == TYPE_void && is_oid_nil(l->tseqbase)) ||
    5443         125 :             ((rl->ttype == TYPE_void && is_oid_nil(rl->tseqbase)) &&
    5444           0 :              (rh->ttype == TYPE_void && is_oid_nil(rh->tseqbase)))) {
    5445             :                 /* trivial: empty input */
    5446          22 :                 return nomatch(r1p, r2p, NULL, l, rl, &lci, 0, false, false,
    5447             :                                __func__, t0);
    5448             :         }
    5449         125 :         if (rl->ttype == TYPE_void && is_oid_nil(rl->tseqbase)) {
    5450           0 :                 if (!anti)
    5451           0 :                         return nomatch(r1p, r2p, NULL, l, rl, &lci, 0, false, false,
    5452             :                                        __func__, t0);
    5453           0 :                 return thetajoin(r1p, r2p, l, rh, sl, sr, MASK_GT, estimate, false,
    5454             :                                  __func__, t0);
    5455             :         }
    5456         125 :         if (rh->ttype == TYPE_void && is_oid_nil(rh->tseqbase)) {
    5457           0 :                 if (!anti)
    5458           0 :                         return nomatch(r1p, r2p, NULL, l, rl, &lci, 0, false, false,
    5459             :                                        __func__, t0);
    5460           0 :                 return thetajoin(r1p, r2p, l, rl, sl, sr, MASK_LT, estimate, false,
    5461             :                                  __func__, t0);
    5462             :         }
    5463             : 
    5464         144 :         if ((maxsize = joininitresults(&r1, r2p ? &r2 : NULL, NULL, sl ? BATcount(sl) : BATcount(l), sr ? BATcount(sr) : BATcount(rl), false, false, false, false, false, false, estimate)) == BUN_NONE)
    5465             :                 return GDK_FAIL;
    5466         124 :         *r1p = r1;
    5467         124 :         if (r2p) {
    5468         106 :                 *r2p = r2;
    5469             :         }
    5470         124 :         if (maxsize == 0)
    5471             :                 return GDK_SUCCEED;
    5472             : 
    5473         124 :         return rangejoin(r1, r2, l, rl, rh, &lci, &rci, linc, hinc, anti, symmetric, maxsize);
    5474             : }

Generated by: LCOV version 1.14